summaryrefslogtreecommitdiffstats
path: root/src/responder/sudo/sudosrv_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/responder/sudo/sudosrv_query.c')
-rw-r--r--src/responder/sudo/sudosrv_query.c225
1 files changed, 184 insertions, 41 deletions
diff --git a/src/responder/sudo/sudosrv_query.c b/src/responder/sudo/sudosrv_query.c
index 8b98da6e..dd9e1e88 100644
--- a/src/responder/sudo/sudosrv_query.c
+++ b/src/responder/sudo/sudosrv_query.c
@@ -26,11 +26,11 @@
#include "util/util.h"
#include "responder/sudo/sudosrv_private.h"
-int sudosrv_response_append_string(TALLOC_CTX *mem_ctx,
- const char *str,
- size_t str_len,
- uint8_t **_response_body,
- size_t *_response_len)
+static int sudosrv_response_append_string(TALLOC_CTX *mem_ctx,
+ const char *str,
+ size_t str_len,
+ uint8_t **_response_body,
+ size_t *_response_len)
{
size_t response_len = *_response_len;
uint8_t *response_body = *_response_body;
@@ -50,10 +50,10 @@ int sudosrv_response_append_string(TALLOC_CTX *mem_ctx,
return EOK;
}
-int sudosrv_response_append_uint32(TALLOC_CTX *mem_ctx,
- uint32_t number,
- uint8_t **_response_body,
- size_t *_response_len)
+static int sudosrv_response_append_uint32(TALLOC_CTX *mem_ctx,
+ uint32_t number,
+ uint8_t **_response_body,
+ size_t *_response_len)
{
size_t response_len = *_response_len;
uint8_t *response_body = *_response_body;
@@ -72,11 +72,71 @@ int sudosrv_response_append_uint32(TALLOC_CTX *mem_ctx,
return EOK;
}
-int sudosrv_response_append_rule(TALLOC_CTX *mem_ctx,
- int attrs_num,
- struct ldb_message_element *attrs,
- uint8_t **_response_body,
- size_t *_response_len)
+static int sudosrv_response_append_attr(TALLOC_CTX *mem_ctx,
+ const char *name,
+ unsigned int values_num,
+ struct ldb_val *values,
+ uint8_t **_response_body,
+ size_t *_response_len)
+{
+ uint8_t *response_body = *_response_body;
+ size_t response_len = *_response_len;
+ TALLOC_CTX *tmp_ctx = NULL;
+ int i = 0;
+ int ret = EOK;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ return ENOMEM;
+ }
+
+ /* attr name */
+ ret = sudosrv_response_append_string(tmp_ctx, name, strlen(name) + 1,
+ &response_body, &response_len);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* values count */
+ ret = sudosrv_response_append_uint32(tmp_ctx, values_num,
+ &response_body, &response_len);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* values */
+ for (i = 0; i < values_num; i++) {
+ if (strlen((char*)(values[i].data)) != values[i].length) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("value is not a string"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = sudosrv_response_append_string(tmp_ctx,
+ (const char*)values[i].data,
+ values[i].length + 1,
+ &response_body, &response_len);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+ *_response_body = talloc_steal(mem_ctx, response_body);
+ *_response_len = response_len;
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static int sudosrv_response_append_rule(TALLOC_CTX *mem_ctx,
+ int attrs_num,
+ struct ldb_message_element *attrs,
+ uint8_t **_response_body,
+ size_t *_response_len)
{
uint8_t *response_body = *_response_body;
size_t response_len = *_response_len;
@@ -117,18 +177,26 @@ done:
return ret;
}
-int sudosrv_response_append_attr(TALLOC_CTX *mem_ctx,
- const char *name,
- unsigned int values_num,
- struct ldb_val *values,
- uint8_t **_response_body,
- size_t *_response_len)
+/*
+ * Response format:
+ * <error_code(uint32_t)><num_entries(uint32_t)><rule1><rule2>...
+ * <ruleN> = <num_attrs(uint32_t)><attr1><attr2>...
+ * <attrN> = <name(char*)>\0<num_values(uint32_t)><value1(char*)>\0<value2(char*)>\0...
+ *
+ * if <error_code> is not SSS_SUDO_ERROR_OK, the rest of the data is skipped.
+ */
+errno_t sudosrv_build_response(TALLOC_CTX *mem_ctx,
+ uint32_t error,
+ int rules_num,
+ struct sysdb_attrs **rules,
+ uint8_t **_response_body,
+ size_t *_response_len)
{
- uint8_t *response_body = *_response_body;
- size_t response_len = *_response_len;
+ uint8_t *response_body = NULL;
+ size_t response_len = 0;
TALLOC_CTX *tmp_ctx = NULL;
int i = 0;
- int ret = EOK;
+ errno_t ret = EOK;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
@@ -136,42 +204,117 @@ int sudosrv_response_append_attr(TALLOC_CTX *mem_ctx,
return ENOMEM;
}
- /* attr name */
- ret = sudosrv_response_append_string(tmp_ctx, name, strlen(name) + 1,
+ /* error code */
+ ret = sudosrv_response_append_uint32(tmp_ctx, error,
&response_body, &response_len);
if (ret != EOK) {
+ goto fail;
+ }
+
+ if (error != SSS_SUDO_ERROR_OK) {
goto done;
}
- /* values count */
- ret = sudosrv_response_append_uint32(tmp_ctx, values_num,
+ /* rules count */
+ ret = sudosrv_response_append_uint32(tmp_ctx, (uint32_t)rules_num,
&response_body, &response_len);
if (ret != EOK) {
- goto done;
+ goto fail;
}
- /* values */
- for (i = 0; i < values_num; i++) {
- if (strlen((char*)(values[i].data)) != values[i].length) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("value is not a string"));
- ret = EINVAL;
- goto done;
- }
-
- ret = sudosrv_response_append_string(tmp_ctx,
- (const char*)values[i].data,
- values[i].length + 1,
- &response_body, &response_len);
+ /* rules */
+ for (i = 0; i < rules_num; i++) {
+ ret = sudosrv_response_append_rule(tmp_ctx, rules[i]->num, rules[i]->a,
+ &response_body, &response_len);
if (ret != EOK) {
- goto done;
+ goto fail;
}
}
+done:
*_response_body = talloc_steal(mem_ctx, response_body);
*_response_len = response_len;
ret = EOK;
+fail:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ * Query format:
+ * <username[@domain]>
+ */
+errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx,
+ struct resp_ctx *rctx,
+ uint8_t *query_body,
+ size_t query_len,
+ char **_username,
+ struct sss_domain_info **_domain)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ struct sss_domain_info *domain = NULL;
+ size_t offset = 0;
+ size_t rawname_len = 0;
+ char *rawname = NULL;
+ char *domainname = NULL;
+ char *username = NULL;
+ errno_t ret;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ return ENOMEM;
+ }
+
+ /* username[@domain] */
+
+ rawname = (char*)(query_body + offset);
+ rawname_len = query_len - offset; /* strlen + zero */
+
+ if (rawname[rawname_len - 1] != '\0') {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Username is not zero terminated\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (rawname_len < 2) { /* at least one character and zero */
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Query does not contain username\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (!sss_utf8_check((uint8_t*)rawname, rawname_len - 1)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Supplied data is not valid UTF-8 string\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ /* parse username */
+
+ ret = sss_parse_name_for_domains(tmp_ctx, rctx->domains, rawname,
+ &domainname, &username);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid name received [%s]\n", rawname));
+ goto done;
+ }
+
+ if (domainname != NULL) {
+ /* mem_ctx because it duplicates only subdomains not domains
+ * so I cannot easily steal it */
+ domain = responder_get_domain(mem_ctx, rctx, domainname);
+ if (domain == NULL) {
+ ret = ENOENT;
+ goto done;
+ }
+ }
+
+ *_username = talloc_steal(mem_ctx, username);
+ *_domain = domain; /* do not steal on mem_ctx */
+
+ ret = EOK;
+
done:
talloc_free(tmp_ctx);
return ret;