summaryrefslogtreecommitdiff
path: root/server/infopipe
diff options
context:
space:
mode:
Diffstat (limited to 'server/infopipe')
-rw-r--r--server/infopipe/infopipe.c256
-rw-r--r--server/infopipe/infopipe.h3
-rw-r--r--server/infopipe/infopipe_private.h64
-rw-r--r--server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml2
-rw-r--r--server/infopipe/org.freeipa.sssd.infopipe.conf1
5 files changed, 322 insertions, 4 deletions
diff --git a/server/infopipe/infopipe.c b/server/infopipe/infopipe.c
index 9c129d26..80b1bef0 100644
--- a/server/infopipe/infopipe.c
+++ b/server/infopipe/infopipe.c
@@ -29,7 +29,8 @@
#include "monitor/monitor_sbus.h"
#include "monitor/monitor_interfaces.h"
#include "infopipe/sysbus.h"
-#include "infopipe.h"
+#include "infopipe/infopipe.h"
+#include "infopipe/infopipe_private.h"
struct infp_ctx {
struct event_context *ev;
@@ -127,12 +128,13 @@ static int infp_monitor_init(struct infp_ctx *infp_ctx)
}
struct sbus_method infp_methods[] = {
+ INFP_PERMISSION_METHODS
INFP_USER_METHODS
INFP_GROUP_METHODS
{ NULL, NULL }
};
-#define INTROSPECT_CHUNK_SIZE 128
+#define INTROSPECT_CHUNK_SIZE 4096 /* Read in one memory page at a time */
int infp_introspect(DBusMessage *message, struct sbus_message_ctx *reply)
{
@@ -250,9 +252,257 @@ static int infp_process_init(TALLOC_CTX *mem_ctx,
return ret;
}
+int get_object_type(const char *obj)
+{
+ int object_type = INFP_OBJ_TYPE_INVALID;
+
+ if (strcasecmp(obj, "user") == 0)
+ object_type = INFP_OBJ_TYPE_USER;
+ else if (strcasecmp(obj, "group") == 0)
+ object_type = INFP_OBJ_TYPE_GROUP;
+
+ return object_type;
+}
+
+int get_action_type(const char *action)
+{
+ int action_type = INFP_ACTION_TYPE_INVALID;
+
+ if (strcasecmp(action, "create") == 0)
+ action_type = INFP_ACTION_TYPE_CREATE;
+ else if ((strcasecmp(action, "delete") == 0))
+ action_type = INFP_ACTION_TYPE_DELETE;
+ else if ((strcasecmp(action, "modify") == 0))
+ action_type = INFP_ACTION_TYPE_MODIFY;
+ else if ((strcasecmp(action, "addmember") == 0))
+ action_type = INFP_ACTION_TYPE_ADDMEMBER;
+ else if ((strcasecmp(action, "removemember") == 0))
+ action_type = INFP_ACTION_TYPE_REMOVEMEMBER;
+
+ return action_type;
+}
+
+int get_attribute_type(const char *attribute)
+{
+ int attribute_type = INFP_ATTR_TYPE_INVALID;
+
+ if(strcasecmp(attribute, "defaultgroup") == 0)
+ attribute_type = INFP_ATTR_TYPE_DEFAULTGROUP;
+ else if (strcasecmp(attribute, "gecos") == 0) {
+ attribute_type = INFP_ATTR_TYPE_GECOS;
+ }
+ else if (strcasecmp(attribute, "homedir") == 0) {
+ attribute_type = INFP_ATTR_TYPE_HOMEDIR;
+ }
+ else if (strcasecmp(attribute, "shell") == 0) {
+ attribute_type = INFP_ATTR_TYPE_SHELL;
+ }
+ else if (strcasecmp(attribute, "fullname") == 0) {
+ attribute_type = INFP_ATTR_TYPE_FULLNAME;
+ }
+ else if (strcasecmp(attribute, "locale") == 0) {
+ attribute_type = INFP_ATTR_TYPE_LOCALE;
+ }
+ else if (strcasecmp(attribute, "keyboard") == 0) {
+ attribute_type = INFP_ATTR_TYPE_KEYBOARD;
+ }
+ else if (strcasecmp(attribute, "session") == 0) {
+ attribute_type = INFP_ATTR_TYPE_SESSION;
+ }
+ else if (strcasecmp(attribute, "last_login") == 0) {
+ attribute_type = INFP_ATTR_TYPE_LAST_LOGIN;
+ }
+ else if (strcasecmp(attribute, "userpic") == 0) {
+ attribute_type = INFP_ATTR_TYPE_USERPIC;
+ }
+
+ return attribute_type;
+}
+
+bool infp_get_permissions(const char *username,
+ const char *domain,
+ int object_type,
+ const char *instance,
+ int action_type,
+ int action_attribute)
+{
+ /* TODO: have a real ACL mechanism.
+ * For right now, root is God and no one else can do anything.
+ * Note: this is buggy. It will return true for ALL requests,
+ * even the nonsensical ones.
+ */
+ if (strcmp(username, "root") == 0)
+ return true;
+ return false;
+}
+
+/* CheckPermissions(STRING domain, STRING object, STRING instance
+ * ARRAY(STRING action_type, STRING attribute) actions)
+ */
int infp_check_permissions(DBusMessage *message, struct sbus_message_ctx *reply)
{
- reply->reply_message = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented");
+ TALLOC_CTX *tmp_ctx;
+ int current_type;
+ DBusConnection *conn;
+ const char *conn_name;
+ uid_t uid;
+ char *username;
+ DBusMessageIter iter;
+ DBusMessageIter action_array_iter;
+ DBusMessageIter action_struct_iter;
+ DBusError error;
+ int object_type;
+ const char *einval_msg;
+ const char *domain;
+ const char *object;
+ const char *instance;
+ const char *action;
+ const char *attribute;
+ int action_type, attribute_type;
+ dbus_bool_t *permissions;
+ size_t count;
+
+ tmp_ctx = talloc_new(reply);
+ if(tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ /* Get the connection UID */
+ conn = sbus_get_connection(reply->mh_ctx->conn_ctx);
+ conn_name = dbus_message_get_sender(message);
+ if (conn_name == NULL) {
+ DEBUG(0, ("Critical error: D-BUS client has no unique name\n"));
+ return EIO;
+ }
+ dbus_error_init(&error);
+ uid = dbus_bus_get_unix_user(conn, conn_name, &error);
+ if (uid == -1) {
+ DEBUG(0, ("Could not identify unix user. Error message was '%s:%s'\n", error.name, error.message));
+ dbus_error_free(&error);
+ return EIO;
+ }
+ username = get_username_from_uid(tmp_ctx, uid);
+ if (username == NULL) {
+ DEBUG(0, ("No username matched the connected UID\n"));
+ return EIO;
+ }
+
+ if (!dbus_message_iter_init(message, &iter)) {
+ einval_msg = talloc_strdup(tmp_ctx, "No arguments received.");
+ goto einval;
+ }
+
+ /* domain */
+ current_type = dbus_message_iter_get_arg_type (&iter);
+ if (current_type != DBUS_TYPE_STRING) {
+ einval_msg = talloc_strdup(tmp_ctx, "Expected domain");
+ goto einval;
+ }
+ dbus_message_iter_get_basic(&iter, &domain);
+ DEBUG(9, ("Domain: %s\n", domain));
+
+ /* Object */
+ dbus_message_iter_next(&iter);
+ current_type = dbus_message_iter_get_arg_type (&iter);
+ if (current_type != DBUS_TYPE_STRING) {
+ einval_msg = talloc_strdup(tmp_ctx, "Expected object");
+ goto einval;
+ }
+ dbus_message_iter_get_basic(&iter, &object);
+ DEBUG(9, ("Object: %s\n", object));
+ object_type = get_object_type(object);
+ if (object_type == INFP_OBJ_TYPE_INVALID) {
+ einval_msg = talloc_strdup(tmp_ctx, "Invalid object type");
+ goto einval;
+ }
+
+ /* Instance */
+ dbus_message_iter_next(&iter);
+ current_type = dbus_message_iter_get_arg_type (&iter);
+ if (current_type != DBUS_TYPE_STRING) {
+ einval_msg = talloc_strdup(tmp_ctx, "Expected instance");
+ goto einval;
+ }
+ dbus_message_iter_get_basic(&iter, &instance);
+ DEBUG(9, ("Instance: %s\n", instance));
+ if(strcmp(instance,"")==0) {
+ instance = NULL;
+ }
+
+ /* Actions */
+ dbus_message_iter_next(&iter);
+ current_type = dbus_message_iter_get_arg_type (&iter);
+ if (current_type != DBUS_TYPE_ARRAY) {
+ einval_msg = talloc_strdup(tmp_ctx, "Expected array of actions");
+ goto einval;
+ }
+
+ dbus_message_iter_recurse(&iter, &action_array_iter);
+ count = 0;
+ while((current_type=dbus_message_iter_get_arg_type(&action_array_iter)) != DBUS_TYPE_INVALID) {
+ if (current_type != DBUS_TYPE_STRUCT) {
+ einval_msg = talloc_strdup(tmp_ctx, "Action array entry was not a struct");
+ goto einval;
+ }
+ dbus_message_iter_recurse(&action_array_iter, &action_struct_iter);
+ /* action_type */
+ if (dbus_message_iter_get_arg_type(&action_struct_iter) != DBUS_TYPE_STRING) {
+ einval_msg = talloc_strdup(tmp_ctx, "Missing action_type");
+ goto einval;
+ }
+ dbus_message_iter_get_basic(&action_struct_iter, &action);
+ DEBUG(9, ("Action type: %s\n", action));
+ action_type = get_action_type(action);
+ if(action_type == INFP_ACTION_TYPE_INVALID) {
+ einval_msg = talloc_asprintf(tmp_ctx, "Action type [%s] is not valid", action);
+ goto einval;
+ }
+
+ /* attribute */
+ dbus_message_iter_next(&action_struct_iter);
+ if (dbus_message_iter_get_arg_type(&action_struct_iter) != DBUS_TYPE_STRING) {
+ einval_msg = talloc_strdup(tmp_ctx, "Missing attribute");
+ goto einval;
+ }
+ dbus_message_iter_get_basic(&action_struct_iter, &attribute);
+ DEBUG(9, ("Action attribute: %s\n", attribute));
+ attribute_type = get_attribute_type(attribute);
+ if(attribute_type == INFP_ATTR_TYPE_INVALID) {
+ einval_msg = talloc_asprintf(tmp_ctx, "Attribute [%s] is not valid", attribute);
+ goto einval;
+ }
+
+ if (dbus_message_iter_has_next(&action_struct_iter)) {
+ einval_msg = talloc_strdup(tmp_ctx, "Unexpected value in action struct");
+ goto einval;
+ }
+
+ /* Process the actions */
+ count++;
+ permissions=talloc_realloc(tmp_ctx, permissions,dbus_bool_t, count);
+ permissions[count-1] = infp_get_permissions(username, domain,
+ object_type, instance,
+ action_type, attribute_type);
+
+ dbus_message_iter_next(&action_array_iter);
+ }
+
+ /* Create response message */
+ reply->reply_message = dbus_message_new_method_return(message);
+ if (reply->reply_message == NULL) return ENOMEM;
+
+ talloc_steal(reply, permissions);
+ dbus_message_append_args(reply->reply_message,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &permissions, count,
+ DBUS_TYPE_INVALID);
+
+ talloc_free(tmp_ctx);
+ return EOK;
+
+einval:
+ talloc_steal(reply, einval_msg);
+ reply->reply_message = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, einval_msg);
+ talloc_free(tmp_ctx);
return EOK;
}
diff --git a/server/infopipe/infopipe.h b/server/infopipe/infopipe.h
index 83a3d8d4..9db5c0d1 100644
--- a/server/infopipe/infopipe.h
+++ b/server/infopipe/infopipe.h
@@ -55,6 +55,9 @@ int infp_introspect(DBusMessage *message, struct sbus_message_ctx *reply);
#define INFP_CHECK_PERMISSIONS "CheckPermissions1"
int infp_check_permissions(DBusMessage *message, struct sbus_message_ctx *reply);
+#define INFP_PERMISSION_METHODS \
+ {INFP_CHECK_PERMISSIONS,infp_check_permissions},
+
/**********************************************************
* User Methods (from infopipe_users.c) *
**********************************************************/
diff --git a/server/infopipe/infopipe_private.h b/server/infopipe/infopipe_private.h
new file mode 100644
index 00000000..afac334b
--- /dev/null
+++ b/server/infopipe/infopipe_private.h
@@ -0,0 +1,64 @@
+/*
+ SSSD
+
+ InfoPipe
+
+ Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009
+
+ 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 INFOPIPE_PRIVATE_H_
+#define INFOPIPE_PRIVATE_H_
+
+enum object_types {
+ INFP_OBJ_TYPE_INVALID = 0,
+ INFP_OBJ_TYPE_USER,
+ INFP_OBJ_TYPE_GROUP
+};
+int get_object_type(const char *obj);
+
+enum action_types {
+ INFP_ACTION_TYPE_INVALID = 0,
+ INFP_ACTION_TYPE_CREATE,
+ INFP_ACTION_TYPE_DELETE,
+ INFP_ACTION_TYPE_MODIFY,
+ INFP_ACTION_TYPE_ADDMEMBER,
+ INFP_ACTION_TYPE_REMOVEMEMBER
+};
+int get_action_type(const char *action);
+
+enum attribute_types {
+ INFP_ATTR_TYPE_INVALID = 0,
+ INFP_ATTR_TYPE_DEFAULTGROUP,
+ INFP_ATTR_TYPE_GECOS,
+ INFP_ATTR_TYPE_HOMEDIR,
+ INFP_ATTR_TYPE_SHELL,
+ INFP_ATTR_TYPE_FULLNAME,
+ INFP_ATTR_TYPE_LOCALE,
+ INFP_ATTR_TYPE_KEYBOARD,
+ INFP_ATTR_TYPE_SESSION,
+ INFP_ATTR_TYPE_LAST_LOGIN,
+ INFP_ATTR_TYPE_USERPIC
+};
+int get_attribute_type(const char *attribute);
+
+bool infp_get_permissions(const char *username,
+ const char *domain,
+ int object_type,
+ const char *instance,
+ int action_type,
+ int action_attribute);
+
+#endif /* INFOPIPE_PRIVATE_H_ */
diff --git a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml
index 5c50cfe8..41220606 100644
--- a/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml
+++ b/server/infopipe/org.freeipa.sssd.infopipe.Introspect.xml
@@ -123,7 +123,7 @@
defaultgroup(STRING)
gecos(STRING)
homedir(STRING)
- shell(STRSING)
+ shell(STRING)
fullname(STRING)
locale(STRING)
keyboard(STRING)
diff --git a/server/infopipe/org.freeipa.sssd.infopipe.conf b/server/infopipe/org.freeipa.sssd.infopipe.conf
index b9ca5588..2ed3cf1b 100644
--- a/server/infopipe/org.freeipa.sssd.infopipe.conf
+++ b/server/infopipe/org.freeipa.sssd.infopipe.conf
@@ -16,6 +16,7 @@
<!-- Right now, this will be handled by a limited ACL
within the InfoPipe Daemon. -->
<policy context="default">
+ <allow own="org.freeipa.sssd.infopipe1.test"/>
<allow send_interface="org.freeipa.sssd.infopipe1"/>
</policy>