summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2011-07-27 16:26:44 -0400
committerStephen Gallagher <sgallagh@redhat.com>2011-07-29 10:13:26 -0400
commit826937ebae068e2ebe59dd37c5f12331f09fe3b9 (patch)
tree2710b8f1e3cfbcb139d6a35910c4b0c719f11ef5
parentd6354aa46716751a41ddab86bc64c1c7c218c5cc (diff)
downloadsssd-826937ebae068e2ebe59dd37c5f12331f09fe3b9.tar.gz
sssd-826937ebae068e2ebe59dd37c5f12331f09fe3b9.tar.xz
sssd-826937ebae068e2ebe59dd37c5f12331f09fe3b9.zip
libipa_hbac: Support case-insensitive comparisons with UTF8
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac1
-rw-r--r--contrib/sssd.spec.in1
-rw-r--r--src/external/libunistring.m49
-rw-r--r--src/providers/ipa/hbac_evaluator.c114
5 files changed, 111 insertions, 17 deletions
diff --git a/Makefile.am b/Makefile.am
index 6829788ae..6647528c8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -378,7 +378,8 @@ dist_pkgconfig_DATA += src/providers/ipa/ipa_hbac.pc
libipa_hbac_la_SOURCES = \
src/providers/ipa/hbac_evaluator.c
libipa_hbac_la_LDFLAGS = \
- -version 0:0:0
+ -version 0:1:0 \
+ -lunistring
include_HEADERS = \
src/providers/ipa/ipa_hbac.h
diff --git a/configure.ac b/configure.ac
index 0e2e6d44a..248a9ae3b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -114,6 +114,7 @@ m4_include([src/external/libkeyutils.m4])
m4_include([src/external/libnl.m4])
m4_include([src/external/systemd.m4])
m4_include([src/util/signal.m4])
+m4_include([src/external/libunistring.m4])
WITH_INITSCRIPT
if test x$initscript = xsystemd; then
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
index 6798b7ae0..6f7c8bca5 100644
--- a/contrib/sssd.spec.in
+++ b/contrib/sssd.spec.in
@@ -86,6 +86,7 @@ BuildRequires: libnl-devel
BuildRequires: nscd
BuildRequires: gettext-devel
BuildRequires: pkgconfig
+BuildRequires: libunistring-devel
%description
Provides a set of daemons to manage access to remote directories and
diff --git a/src/external/libunistring.m4 b/src/external/libunistring.m4
new file mode 100644
index 000000000..69c54fe3f
--- /dev/null
+++ b/src/external/libunistring.m4
@@ -0,0 +1,9 @@
+AC_CHECK_HEADERS(unistr.h,
+ [AC_CHECK_LIB([unistring], [u8_strlen], [ UNISTRING_LIBS="-lunistring" ], [AC_MSG_ERROR([No usable libunistring library found])])],
+ [AC_MSG_ERROR([libunistring header files are not installed])]
+)
+
+AC_CHECK_HEADERS(unicase.h,
+ [AC_CHECK_LIB([unistring], [u8_casecmp], [ UNISTRING_LIBS="-lunistring" ], [AC_MSG_ERROR([No usable libunistring library found])])],
+ [AC_MSG_ERROR([libunistring header files are not installed])]
+) \ No newline at end of file
diff --git a/src/providers/ipa/hbac_evaluator.c b/src/providers/ipa/hbac_evaluator.c
index e120d51e4..ee39a09ae 100644
--- a/src/providers/ipa/hbac_evaluator.c
+++ b/src/providers/ipa/hbac_evaluator.c
@@ -25,8 +25,20 @@
#include <stdlib.h>
#include <string.h>
+#include <unistr.h>
+#include <unicase.h>
+#include <errno.h>
#include "providers/ipa/ipa_hbac.h"
+#ifndef HAVE_ERRNO_T
+#define HAVE_ERRNO_T
+typedef int errno_t;
+#endif
+
+#ifndef EOK
+#define EOK 0
+#endif
+
/* Placeholder structure for future HBAC time-based
* evaluation rules
*/
@@ -102,13 +114,17 @@ done:
return result;
}
-static bool hbac_evaluate_element(struct hbac_rule_element *rule_el,
- struct hbac_request_element *req_el);
+static errno_t hbac_evaluate_element(struct hbac_rule_element *rule_el,
+ struct hbac_request_element *req_el,
+ bool *matched);
enum hbac_eval_result_int hbac_evaluate_rule(struct hbac_rule *rule,
struct hbac_eval_req *hbac_req,
enum hbac_error_code *error)
{
+ errno_t ret;
+ bool matched;
+
if (!rule->enabled) return HBAC_EVAL_UNMATCHED;
/* Make sure we have all elements */
@@ -121,43 +137,90 @@ enum hbac_eval_result_int hbac_evaluate_rule(struct hbac_rule *rule,
}
/* Check users */
- if (!hbac_evaluate_element(rule->users, hbac_req->user)) {
+ ret = hbac_evaluate_element(rule->users,
+ hbac_req->user,
+ &matched);
+ if (ret != EOK) {
+ *error = HBAC_ERROR_UNPARSEABLE_RULE;
+ return HBAC_EVAL_MATCH_ERROR;
+ } else if (!matched) {
return HBAC_EVAL_UNMATCHED;
}
/* Check services */
- if (!hbac_evaluate_element(rule->services, hbac_req->service)) {
+ ret = hbac_evaluate_element(rule->services,
+ hbac_req->service,
+ &matched);
+ if (ret != EOK) {
+ *error = HBAC_ERROR_UNPARSEABLE_RULE;
+ return HBAC_EVAL_MATCH_ERROR;
+ } else if (!matched) {
return HBAC_EVAL_UNMATCHED;
}
/* Check target hosts */
- if (!hbac_evaluate_element(rule->targethosts, hbac_req->targethost)) {
+ ret = hbac_evaluate_element(rule->targethosts,
+ hbac_req->targethost,
+ &matched);
+ if (ret != EOK) {
+ *error = HBAC_ERROR_UNPARSEABLE_RULE;
+ return HBAC_EVAL_MATCH_ERROR;
+ } else if (!matched) {
return HBAC_EVAL_UNMATCHED;
}
/* Check source hosts */
- if (!hbac_evaluate_element(rule->srchosts, hbac_req->srchost)) {
+ ret = hbac_evaluate_element(rule->srchosts,
+ hbac_req->srchost,
+ &matched);
+ if (ret != EOK) {
+ *error = HBAC_ERROR_UNPARSEABLE_RULE;
+ return HBAC_EVAL_MATCH_ERROR;
+ } else if (!matched) {
return HBAC_EVAL_UNMATCHED;
}
-
return HBAC_EVAL_MATCHED;
}
-static bool hbac_evaluate_element(struct hbac_rule_element *rule_el,
- struct hbac_request_element *req_el)
+static errno_t hbac_evaluate_element(struct hbac_rule_element *rule_el,
+ struct hbac_request_element *req_el,
+ bool *matched)
{
size_t i, j;
+ const uint8_t *rule_name;
+ const uint8_t *req_name;
+ int result;
+ int ret;
if (rule_el->category & HBAC_CATEGORY_ALL) {
- return true;
+ *matched = true;
+ return EOK;
}
/* First check the name list */
if (rule_el->names) {
for (i = 0; rule_el->names[i]; i++) {
if (req_el->name != NULL) {
- if (strcmp(rule_el->names[i], req_el->name) == 0) {
- return true;
+ rule_name = (const uint8_t *) rule_el->names[i];
+ req_name = (const uint8_t *) req_el->name;
+
+ /* Do a case-insensitive comparison.
+ * The input must be encoded in UTF8.
+ * We have no way of knowing the language,
+ * so we'll pass NULL for the language and
+ * hope for the best.
+ */
+ errno = 0;
+ ret = u8_casecmp(rule_name, u8_strlen(rule_name),
+ req_name, u8_strlen(req_name),
+ NULL, NULL, &result);
+ if (ret < 0) {
+ return errno;
+ }
+
+ if (result == 0) {
+ *matched = true;
+ return EOK;
}
}
}
@@ -168,17 +231,36 @@ static bool hbac_evaluate_element(struct hbac_rule_element *rule_el,
* Check for group membership
*/
for (i = 0; rule_el->groups[i]; i++) {
+ rule_name = (const uint8_t *) rule_el->groups[i];
+
for (j = 0; req_el->groups[j]; j++) {
- if (strcmp(rule_el->groups[i],
- req_el->groups[j]) == 0) {
- return true;
+ req_name = (const uint8_t *) req_el->groups[j];
+
+ /* Do a case-insensitive comparison.
+ * The input must be encoded in UTF8.
+ * We have no way of knowing the language,
+ * so we'll pass NULL for the language and
+ * hope for the best.
+ */
+ errno = 0;
+ ret = u8_casecmp(rule_name, u8_strlen(rule_name),
+ req_name, u8_strlen(req_name),
+ NULL, NULL, &result);
+ if (ret < 0) {
+ return errno;
+ }
+
+ if (result == 0) {
+ *matched = true;
+ return EOK;
}
}
}
}
/* Not found in groups either */
- return false;
+ *matched = false;
+ return EOK;
}
const char *hbac_result_string(enum hbac_eval_result result)