summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2011-11-15 10:18:51 +0100
committerPavel Březina <pbrezina@redhat.com>2011-11-21 16:12:13 +0100
commitfc36652d35b49383d17d4cdf4a68b5e29976784f (patch)
tree814eee0b69a5c44a20b51c34ababa2df28aeb3be
parent33dfb88f627c8ccbb6c351abe6314224cba87db4 (diff)
downloadsssd_unused-fc36652d35b49383d17d4cdf4a68b5e29976784f.tar.gz
sssd_unused-fc36652d35b49383d17d4cdf4a68b5e29976784f.tar.xz
sssd_unused-fc36652d35b49383d17d4cdf4a68b5e29976784f.zip
SUDO Integration - SUDO responder refactored
-rw-r--r--Makefile.am2
-rw-r--r--src/responder/sudo/sudosrv.h2
-rw-r--r--src/responder/sudo/sudosrv_check.c349
-rw-r--r--src/responder/sudo/sudosrv_cmd.c269
-rw-r--r--src/responder/sudo/sudosrv_private.h107
-rw-r--r--src/responder/sudo/sudosrv_query.c264
-rw-r--r--src/sss_client/sudo_plugin/sss_sudoplugin.c20
7 files changed, 791 insertions, 222 deletions
diff --git a/Makefile.am b/Makefile.am
index c1340e75..29b3d0f0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -431,6 +431,8 @@ sssd_pam_LDADD = \
sssd_sudo_SOURCES = \
src/responder/sudo/sudosrv.c \
src/responder/sudo/sudosrv_cmd.c \
+ src/responder/sudo/sudosrv_check.c \
+ src/responder/sudo/sudosrv_query.c \
src/responder/sudo/sudosrv_dp.c \
$(SSSD_RESPONDER_OBJ)
sssd_sudo_LDADD = \
diff --git a/src/responder/sudo/sudosrv.h b/src/responder/sudo/sudosrv.h
index 314fddd6..c1d11a4b 100644
--- a/src/responder/sudo/sudosrv.h
+++ b/src/responder/sudo/sudosrv.h
@@ -21,6 +21,8 @@
#ifndef SUDOSRV_H_
#define SUDOSRV_H_
+#include "responder/common/responder.h"
+
#define SSS_SUDO_SBUS_SERVICE_VERSION 0x0001
#define SSS_SUDO_SBUS_SERVICE_NAME "sudo"
diff --git a/src/responder/sudo/sudosrv_check.c b/src/responder/sudo/sudosrv_check.c
new file mode 100644
index 00000000..6f85fd65
--- /dev/null
+++ b/src/responder/sudo/sudosrv_check.c
@@ -0,0 +1,349 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2011 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <talloc.h>
+
+#include "util/util.h"
+#include "confdb/confdb.h"
+#include "responder/common/responder.h"
+#include "responder/sudo/sudosrv.h"
+#include "responder/sudo/sudosrv_private.h"
+#include "sss_client/sudo_plugin/sss_sudoplugin.h"
+
+struct sudo_check_output * sudosrv_check(TALLOC_CTX *mem_ctx,
+ struct cli_ctx *cli_ctx,
+ struct sudo_check_input *input)
+{
+ struct sudo_command_info command_info;
+ struct sudo_check_output *output = NULL;
+ TALLOC_CTX *tmp_ctx;
+ int ret = EOK;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ output = talloc_zero(tmp_ctx, struct sudo_check_output);
+ if (output == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero() failed\n"));
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ /*
+ * there is no logic yet
+ * allow everything
+ */
+
+ /* set return code */
+ output->return_code = SSS_SUDO_RESPONSE_ALLOW;
+
+ /* build argv */
+ ret = sudosrv_copy_string_array(output, input->argc,
+ input->argv, &(output->argv));
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ /* build command info */
+ command_info.command = input->command_name;
+ ret = sudosrv_check_build_command_info(output, &command_info,
+ &(output->command_info));
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ /* build env out */
+ ret = sudosrv_copy_string_array(output, input->user_env_count,
+ input->user_env, &(output->user_env));
+
+ /* contact DP */
+ ret = sudo_dp_refresh_send(cli_ctx, cli_ctx->rctx->domains->name,
+ SSS_CLI_SOCKET_TIMEOUT / 2);
+
+ talloc_steal(mem_ctx, output);
+ talloc_free(tmp_ctx);
+
+ return output;
+
+fail:
+ talloc_free(tmp_ctx);
+ errno = ret;
+
+ return NULL;
+}
+
+/*
+ * This may not be needed in final version.
+ */
+int sudosrv_copy_string_array(TALLOC_CTX *mem_ctx,
+ int count,
+ char **array,
+ char ***_array_out)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ char **array_out = NULL;
+ int ret = EOK;
+ int i = 0;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ array_out = talloc_array(tmp_ctx, char*, count + 1);
+ if (array_out == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_array() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (i = 0; i < count; i++) {
+ array_out[i] = talloc_strdup(array, array[i]);
+ if (array_out[i] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ array_out[count] = NULL;
+
+ *_array_out = talloc_steal(mem_ctx, array_out);
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ * Currently only "command" is supported.
+ */
+int sudosrv_check_build_command_info(TALLOC_CTX *mem_ctx,
+ struct sudo_command_info *command_info,
+ char ***_command_info_array)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ char **array = NULL;
+ int count = 0;
+ int ret = EOK;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* command */
+ if (command_info->command != NULL) {
+ count++;
+ array = talloc_realloc(tmp_ctx, array, char*, count);
+ if (array == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_realloc() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ array[count - 1] = talloc_asprintf(array, "command=%s",
+ command_info->command);
+ if (array[count - 1] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ /* terminate with NULL */
+ count++;
+ array = talloc_realloc(tmp_ctx, array, char*, count);
+ if (array == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_realloc() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ array[count - 1] = NULL;
+
+ *_command_info_array = talloc_steal(mem_ctx, array);
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+struct sudo_check_input * sudosrv_check_parse_query(TALLOC_CTX *mem_ctx,
+ char *query,
+ int query_length)
+{
+ struct sudo_check_input *input = NULL;
+ TALLOC_CTX *tmp_ctx = NULL;
+ int next_pos = 0;
+ int ret = EOK;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ input = talloc_zero(tmp_ctx, struct sudo_check_input);
+ if (input == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero() failed\n"));
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ /* command name */
+ ret = sudosrv_query_parse_string(input, query, query_length,
+ next_pos, &next_pos,
+ &(input->command_name));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query - command name\n"));
+ goto fail;
+ }
+
+ /* argv */
+ ret = sudosrv_query_parse_array(input, query, query_length,
+ next_pos, &next_pos,
+ &(input->argc),
+ &(input->argv));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query - argv\n"));
+ goto fail;
+ }
+
+ /* env_add */
+ ret = sudosrv_query_parse_array(input, query, query_length,
+ next_pos, &next_pos,
+ &(input->env_add_count),
+ &(input->env_add));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query - env_add \n"));
+ goto fail;
+ }
+
+
+ /* user_env */
+ ret = sudosrv_query_parse_array(input, query, query_length,
+ next_pos, &next_pos,
+ &(input->user_env_count),
+ &(input->user_env));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query - user_env\n"));
+ goto fail;
+ }
+
+ /* settings */
+ ret = sudosrv_query_parse_array(input, query, query_length,
+ next_pos, &next_pos,
+ &(input->settings_count),
+ &(input->settings));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query - settings\n"));
+ goto fail;
+ }
+
+ /* user_info */
+ ret = sudosrv_query_parse_array(input, query, query_length,
+ next_pos, &next_pos,
+ &(input->user_info_count),
+ &(input->user_info));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query - user_info\n"));
+ goto fail;
+ }
+
+ talloc_steal(mem_ctx, input);
+ talloc_free(tmp_ctx);
+
+ return input;
+
+fail:
+ talloc_free(tmp_ctx);
+ errno = ret;
+
+ return NULL;
+}
+
+int sudosrv_check_build_response(TALLOC_CTX *mem_ctx,
+ struct sudo_check_output *output,
+ uint8_t **_response_body,
+ size_t *_response_length)
+{
+ uint8_t *response_body = NULL;
+ size_t response_length = 0;
+ TALLOC_CTX *tmp_ctx = NULL;
+ int ret = EOK;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ return ENOMEM;
+ }
+
+ /* return code */
+ ret = sudosrv_response_append_int(tmp_ctx, output->return_code,
+ &response_body, &response_length);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to build response - return code\n"));
+ goto done;
+ }
+
+ /* argv */
+ ret = sudosrv_response_append_array(tmp_ctx, output->argv,
+ &response_body, &response_length);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to build response - argv\n"));
+ goto done;
+ }
+
+ /* command info */
+ ret = sudosrv_response_append_array(tmp_ctx, output->command_info,
+ &response_body, &response_length);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to build response - command_info\n"));
+ goto done;
+ }
+
+ /* user env */
+ ret = sudosrv_response_append_array(tmp_ctx, output->user_env,
+ &response_body, &response_length);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to build response - user_env\n"));
+ goto done;
+ }
+
+ *_response_body = talloc_steal(mem_ctx, response_body);
+ *_response_length = response_length;
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c
index 11409c40..6cd5b656 100644
--- a/src/responder/sudo/sudosrv_cmd.c
+++ b/src/responder/sudo/sudosrv_cmd.c
@@ -23,249 +23,90 @@
#include <sudo_plugin.h>
#include "util/util.h"
-#include "confdb/confdb.h"
#include "responder/common/responder.h"
#include "responder/common/responder_packet.h"
#include "responder/sudo/sudosrv.h"
-#include "sss_client/sudo_plugin/sss_sudoplugin.h"
-#include "sss_client/sss_cli.h"
+#include "responder/sudo/sudosrv_private.h"
-static int sudo_cmd_check_response(struct cli_ctx *cctx,
- int return_code,
- int argc,
- char **argv,
- char *command_info,
- int command_info_length,
- char **user_env)
+static int sudo_cmd_check(struct cli_ctx *cli_ctx)
{
-#define APPEND_ELEMENT(element, length) do { \
- iter_length = length; \
- sss_packet_grow(packet_out, iter_length * sizeof(char)); \
- sss_packet_get_body(packet_out, &body, &blen); \
- memcpy(body + packet_offset, element, iter_length); \
- packet_offset += iter_length; \
-} while(0)
+ struct sudo_check_output *output = NULL;
+ struct sudo_check_input *input = NULL;
+ struct sss_packet *packet = NULL;
+ uint8_t *packet_body = NULL;
+ size_t packet_length = 0;
+ TALLOC_CTX *mem_ctx = NULL;
+ uint8_t *response_body = NULL;
+ size_t response_length = 0;
+ uint8_t *query_body = NULL;
+ size_t query_length = 0;
+ int ret = EOK;
-#define APPEND_ZERO() do { \
- sss_packet_grow(packet_out, 1 * sizeof(char)); \
- sss_packet_get_body(packet_out, &body, &blen); \
- body[packet_offset] = '\0'; \
- packet_offset++; \
-} while(0)
-
- int i;
- int ret;
- int iter_length;
- uint8_t *body;
- size_t blen;
- size_t packet_offset = 0;
- struct sss_packet *packet_out = NULL;
-
- ret = sss_packet_new(cctx->creq, 0,
- sss_packet_get_cmd(cctx->creq->in),
- &cctx->creq->out);
- if (ret != EOK) {
- return ret;
- }
- packet_out = cctx->creq->out;
-
- sss_packet_set_error(packet_out, EOK);
-
- /* fill data */
-
- /* result */
- ret = sss_packet_grow(packet_out, sizeof(int));
- if (ret != EOK) {
- return ret;
- }
- sss_packet_get_body(packet_out, &body, &blen);
- SAFEALIGN_SET_VALUE(&body[packet_offset], return_code, int, &packet_offset);
-
- if (return_code == SSS_SUDO_RESPONSE_ALLOW) {
- /* argv */
- for (i = 0; i < argc; i++) {
- APPEND_ELEMENT(argv[i], strlen(argv[i]) + 1);
- }
- APPEND_ZERO();
-
- /* command_info */
- APPEND_ELEMENT(command_info, command_info_length);
- APPEND_ZERO();
-
- /* user_env */
- APPEND_ZERO();
- APPEND_ZERO();
- }
-
- return EOK;
-
-#undef APPEND_ELEMENT
-#undef APPEND_ZERO
-}
-
-static int sudo_cmd_check_parse_query(TALLOC_CTX *mem_ctx,
- char *query,
- int query_length,
- char **_command_out,
- char ***_argv_out,
- int *_argc_out)
-{
- TALLOC_CTX *tmp_ctx;
- char *current_position = query;
- char **argv_out;
- int argc_out = 0;
- int ret;
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed"));
- ret = ENOMEM;
- goto done;
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ return ENOMEM;
}
- /* get command */
- *_command_out = current_position;
- current_position = strchr(current_position, '\0');
- if (current_position == NULL) {
- ret = ESPIPE;
+ /* get query */
+ sss_packet_get_body(cli_ctx->creq->in, &query_body, &query_length);
+ if (query_length <= 0 || query_body == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Query is empty\n"));
+ ret = EINVAL;
goto done;
}
- current_position++;
-
- /* get argv */
- while (*current_position != '\0') {
- argc_out++;
- argv_out = talloc_realloc(tmp_ctx, argv_out, char*, argc_out);
- argv_out[argc_out - 1] = current_position;
-
- current_position = strchr(current_position, '\0');
- if (current_position == NULL) {
- ret = ESPIPE;
- goto done;
- }
- current_position++;
- }
- current_position++;
-
- /* TODO get env_add */
-
- /* TODO get user_env */
-
- /* TODO get settings */
-
- /* TODO get user_info */
-
- *_argc_out = argc_out;
- *_argv_out = talloc_steal(mem_ctx, argv_out);
-
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-static int sudo_cmd_check_create_command_info(TALLOC_CTX *mem_ctx,
- char *command,
- char **command_info_out,
- int *command_info_length_out)
-{
- TALLOC_CTX *tmp_ctx;
- char *command_info;
- int command_info_length = 0;
- int ret;
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed"));
- ret = ENOMEM;
+ /* parse query */
+ input = sudosrv_check_parse_query(mem_ctx, (char*)query_body, query_length);
+ if (input == NULL) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Unable to parse query: %s\n", strerror(ret)));
goto done;
}
- command_info = talloc_asprintf(tmp_ctx, "command=%s", command);
- if (command_info == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_asprintf() failed"));
- ret = ENOMEM;
+ /* evaluate sudo rules */
+ output = sudosrv_check(mem_ctx, cli_ctx, input);
+ if (output == NULL) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Unable to evaluate sudo rules: %s\n", strerror(ret)));
goto done;
}
- command_info_length += strlen(command_info) + 1; /* with \0 */
-
- /* TODO support other fields */
-
- *command_info_length_out = command_info_length;
- *command_info_out = talloc_steal(mem_ctx, command_info);
-
- ret = EOK;
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-static int sudo_cmd_check(struct cli_ctx *cctx) {
- TALLOC_CTX *mem_ctx;
- uint8_t *body;
- size_t blen;
- char *query = NULL;
- char *command_in = NULL;
- char **argv_in = NULL;
- char *command_info_out = NULL;
- int command_info_out_length = 0;
- int argc_in = 0;
- int ret;
- int sudo_result;
-
- mem_ctx = talloc_new(NULL);
- if (mem_ctx == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed"));
- return ENOMEM;
- }
-
- /* get query string */
- sss_packet_get_body(cctx->creq->in, &body, &blen);
- if (blen <= 0 || body == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Query string is empty"));
- ret = EINVAL;
+ /* create response message */
+ ret = sudosrv_check_build_response(mem_ctx, output,
+ &response_body, &response_length);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Unable to create response message: %s\n", strerror(ret)));
goto done;
}
- query = (char*)body;
- /* parse query string */
- ret = sudo_cmd_check_parse_query(mem_ctx, query, blen, &command_in,
- &argv_in, &argc_in);
+ /* set response */
+ ret = sss_packet_new(cli_ctx->creq, 0,
+ sss_packet_get_cmd(cli_ctx->creq->in),
+ &cli_ctx->creq->out);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("Unable to parse query string"));
- goto done;
+ return ret;
}
+ packet = cli_ctx->creq->out;
- /* TODO can user run this command? */
-
- sudo_result = SSS_SUDO_RESPONSE_ALLOW;
+ sss_packet_set_error(packet, EOK);
- /* create command info */
- if (sudo_result == SSS_SUDO_RESPONSE_ALLOW) {
- ret = sudo_cmd_check_create_command_info(mem_ctx, command_in,
- &command_info_out,
- &command_info_out_length);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to create command info string"));
- return ENOMEM;
- }
+ ret = sss_packet_grow(packet, response_length);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Unable to create response: %s\n", strerror(ret)));
+ return ret;
}
-
- /* contact DP */
- ret = sudo_dp_refresh_send(cctx, cctx->rctx->domains->name,
- SSS_CLI_SOCKET_TIMEOUT/2);
-
- /* send response */
- sudo_cmd_check_response(cctx, sudo_result, argc_in, argv_in,
- command_info_out, command_info_out_length, NULL);
+ sss_packet_get_body(packet, &packet_body, &packet_length);
+ memcpy(packet_body, response_body, response_length);
ret = EOK;
done:
- sss_cmd_done(cctx, NULL);
+ sss_cmd_done(cli_ctx, NULL);
talloc_free(mem_ctx);
return ret;
diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
new file mode 100644
index 00000000..012f5d96
--- /dev/null
+++ b/src/responder/sudo/sudosrv_private.h
@@ -0,0 +1,107 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2011 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef SUDOSRV_PRIVATE_H_
+#define SUDOSRV_PRIVATE_H_
+
+struct sudo_check_input {
+ char *command_name;
+
+ int argc;
+ char **argv;
+
+ int env_add_count;
+ char **env_add;
+
+ int user_env_count;
+ char **user_env;
+
+ int settings_count;
+ char **settings;
+
+ int user_info_count;
+ char **user_info;
+};
+
+struct sudo_check_output {
+ int return_code;
+ char **argv;
+ char **command_info;
+ char **user_env;
+};
+
+struct sudo_command_info {
+ char *command;
+};
+
+struct sudo_check_output * sudosrv_check(TALLOC_CTX *mem_ctx,
+ struct cli_ctx *cli_ctx,
+ struct sudo_check_input *input);
+
+int sudosrv_copy_string_array(TALLOC_CTX *mem_ctx,
+ int argc,
+ char **argv,
+ char ***_argv_out);
+
+int sudosrv_check_build_command_info(TALLOC_CTX *mem_ctx,
+ struct sudo_command_info *command_info,
+ char ***_command_info);
+
+struct sudo_check_input * sudosrv_check_parse_query(TALLOC_CTX *mem_ctx,
+ char *query,
+ int query_length);
+
+int sudosrv_check_build_response(TALLOC_CTX *mem_ctx,
+ struct sudo_check_output *output,
+ uint8_t **_response_body,
+ size_t *_response_length);
+
+int sudosrv_query_parse_array(TALLOC_CTX *mem_ctx,
+ char *query,
+ int query_length,
+ int start_pos,
+ int *_end_pos,
+ int *_count,
+ char ***_array);
+
+int sudosrv_query_parse_string(TALLOC_CTX *mem_ctx,
+ char *query,
+ int query_length,
+ int start_pos,
+ int *_end_pos,
+ char **_string);
+
+int sudosrv_response_append_array(TALLOC_CTX *mem_ctx,
+ char **array,
+ uint8_t **_response,
+ size_t *_response_length);
+
+int sudosrv_response_append_string(TALLOC_CTX *mem_ctx,
+ const char *str,
+ size_t str_length,
+ uint8_t **_response,
+ size_t *_response_length);
+
+int sudosrv_response_append_int(TALLOC_CTX *mem_ctx,
+ int number,
+ uint8_t **_response,
+ size_t *_response_length);
+
+#endif /* SUDOSRV_PRIVATE_H_ */
diff --git a/src/responder/sudo/sudosrv_query.c b/src/responder/sudo/sudosrv_query.c
new file mode 100644
index 00000000..fcf01333
--- /dev/null
+++ b/src/responder/sudo/sudosrv_query.c
@@ -0,0 +1,264 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2011 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <errno.h>
+#include <talloc.h>
+
+#include "util/util.h"
+#include "responder/sudo/sudosrv.h"
+#include "responder/sudo/sudosrv_private.h"
+
+/*
+ * Reads null-terminated string.
+ */
+int sudosrv_query_parse_string(TALLOC_CTX *mem_ctx,
+ char *query,
+ int query_length,
+ int start_pos,
+ int *_end_pos,
+ char **_string)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ char *current_pos = query + start_pos;
+ char *string = NULL;
+ int ret = EOK;
+
+ if (start_pos > query_length) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Query is too short\n"));
+ return EINVAL;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (*current_pos != '\0') {
+ string = talloc_strdup(tmp_ctx, current_pos);
+ if (string == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup() failed\n"));
+ return ENOMEM;
+ }
+
+ current_pos = strchr(current_pos, '\0');
+ if (current_pos == NULL) {
+ ret = ESPIPE;
+ goto done;
+ }
+ }
+
+ /* go one char past \0 */
+ current_pos++;
+
+ *_end_pos = current_pos - query;
+ *_string = talloc_steal(mem_ctx, string);
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ * Reads array in format:
+ * value1\0value2\0...\0\0
+ */
+int sudosrv_query_parse_array(TALLOC_CTX *mem_ctx,
+ char *query,
+ int query_length,
+ int start_pos,
+ int *_end_pos,
+ int *_count,
+ char ***_array)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ char *current_pos = query + start_pos;
+ char **array = NULL;
+ int count = 0;
+ int ret = EOK;
+
+ if (start_pos > query_length) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Query is too short\n"));
+ return EINVAL;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (*current_pos != '\0') {
+ /* array with at least one element */
+ do {
+ count++;
+
+ array = talloc_realloc(tmp_ctx, array, char*, count);
+ if (array == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_realloc() failed\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ array[count - 1] = talloc_strdup(array, current_pos);
+ if (array[count - 1] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_strdup() failed\n"));
+ return ENOMEM;
+ }
+
+ /* find end of this element */
+ current_pos = strchr(current_pos, '\0');
+ if (current_pos == NULL) {
+ ret = ESPIPE;
+ goto done;
+ }
+
+ /* go to the start of the next element (one char past \0) */
+ current_pos++;
+ } while (*current_pos != '\0');
+ } else {
+ /* special case for empty arrays - go one char past \0 */
+ current_pos++;
+ }
+
+ /* go to the next array */
+ current_pos++;
+
+ if (_count != NULL) {
+ *_count = count;
+ }
+ *_array = talloc_steal(mem_ctx, array);
+ *_end_pos = current_pos - query;
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ * Appends null-terminated string array.
+ */
+int sudosrv_response_append_array(TALLOC_CTX *mem_ctx,
+ char **array,
+ uint8_t **_response,
+ size_t *_response_length)
+{
+ size_t response_length = *_response_length;
+ uint8_t *response = *_response;
+ TALLOC_CTX *tmp_ctx = NULL;
+ char **iter = NULL;
+ int ret = EOK;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (array == NULL || *array == NULL) {
+ /* empty array - append two \0 */
+ ret = sudosrv_response_append_string(tmp_ctx, "\0\0", 2,
+ &response, &response_length);
+ if (ret != EOK) {
+ goto done;
+ }
+ } else {
+ for (iter = array; *iter != NULL; iter++) {
+ /* append element with ending \0 */
+ ret = sudosrv_response_append_string(tmp_ctx, *iter,
+ strlen(*iter) + 1,
+ &response, &response_length);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+ /* append \0 to mark end of this array */
+ ret = sudosrv_response_append_string(tmp_ctx, "\0", 1,
+ &response, &response_length);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+ *_response_length = response_length;
+ *_response = talloc_steal(mem_ctx, response);
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+int sudosrv_response_append_string(TALLOC_CTX *mem_ctx,
+ const char *str,
+ size_t str_length,
+ uint8_t **_response,
+ size_t *_response_length)
+{
+ size_t response_length = *_response_length;
+ uint8_t *response = *_response;
+
+ response = talloc_realloc(mem_ctx, response, uint8_t,
+ response_length + (str_length * sizeof(char)));
+ if (response == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_realloc() failed\n"));
+ return ENOMEM;
+ }
+ memcpy(response + response_length, str, str_length);
+ response_length += str_length;
+
+ *_response = response;
+ *_response_length = response_length;
+
+ return EOK;
+}
+
+int sudosrv_response_append_int(TALLOC_CTX *mem_ctx,
+ int number,
+ uint8_t **_response,
+ size_t *_response_length)
+{
+ size_t response_length = *_response_length;
+ uint8_t *response = *_response;
+
+ response = talloc_realloc(mem_ctx, response, uint8_t,
+ response_length + sizeof(int));
+ if (response == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_realloc() failed\n"));
+ return ENOMEM;
+ }
+ SAFEALIGN_SET_VALUE(response + response_length,
+ number, int, &response_length);
+
+ *_response = response;
+ *_response_length = response_length;
+
+ return EOK;
+}
diff --git a/src/sss_client/sudo_plugin/sss_sudoplugin.c b/src/sss_client/sudo_plugin/sss_sudoplugin.c
index 9e2dfce0..3e5e2c08 100644
--- a/src/sss_client/sudo_plugin/sss_sudoplugin.c
+++ b/src/sss_client/sudo_plugin/sss_sudoplugin.c
@@ -347,15 +347,19 @@ errno_t policy_check_parse_response(char *response,
{
#define LOAD_ARRAY(element) do { \
i = 0; \
- while (*current_position != '\0') { \
- i++; \
- element = (char**)realloc(element, i * sizeof(char*)); \
- element[i - 1] = current_position; \
- current_position = strchr(current_position, '\0'); \
- if (current_position == NULL) { \
- ret = ESPIPE; \
- goto done; \
+ if (*current_position != '\0') { \
+ while (*current_position != '\0') { \
+ i++; \
+ element = (char**)realloc(element, i * sizeof(char*)); \
+ element[i - 1] = current_position; \
+ current_position = strchr(current_position, '\0'); \
+ if (current_position == NULL) { \
+ ret = ESPIPE; \
+ goto done; \
+ } \
+ current_position++; \
} \
+ } else { \
current_position++; \
} \
i++; \