1 /***************************************************************************
2  *
3  * libpolkit-rbac.c : RBAC implementation of the libpolkit API
4  *
5  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
6  * Use is subject to license terms.
7  *
8  * Licensed under the Academic Free License version 2.1
9  *
10  **************************************************************************/
11 
12 #pragma ident	"%Z%%M%	%I%	%E% SMI"
13 
14 #ifdef HAVE_CONFIG_H
15 #  include <config.h>
16 #endif
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <pwd.h>
23 #include <grp.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <auth_attr.h>
27 #include <secdb.h>
28 
29 #include <glib.h>
30 #include <dbus/dbus-glib.h>
31 
32 #include "libpolkit.h"
33 
34 #define LIBPOLKIT_MAGIC 0x3117beef
35 
36 #ifdef __SUNPRO_C
37 #define __FUNCTION__ __func__
38 #endif
39 
40 #define LIBPOLKIT_CHECK_CONTEXT(_ctx_, _ret_)				\
41 	do {									\
42 		if (_ctx_ == NULL) {						\
43 			g_warning ("%s: given LibPolKitContext is NULL",     \
44 				   __FUNCTION__);			        \
45 			return _ret_;					        \
46 		}								\
47 		if (_ctx_->magic != LIBPOLKIT_MAGIC) {			\
48 			g_warning ("%s: given LibPolKitContext is invalid (read magic 0x%08x, should be 0x%08x)",  \
49 				   __FUNCTION__, _ctx_->magic, LIBPOLKIT_MAGIC);	\
50 			return _ret_;					        \
51 		}								\
52 	} while(0)
53 
54 
55 struct LibPolKitContext_s
56 {
57 	guint32 magic;
58 };
59 
60 /** Get a new context.
61  *
62  *  @return                     Pointer to new context or NULL if an error occured
63  */
64 LibPolKitContext *
libpolkit_new_context(DBusConnection * connection)65 libpolkit_new_context (DBusConnection *connection)
66 {
67 	LibPolKitContext *ctx;
68 
69 	ctx = g_new0 (LibPolKitContext, 1);
70 	ctx->magic = LIBPOLKIT_MAGIC;
71 
72 	return ctx;
73 }
74 
75 /** Free a context
76  *
77  *  @param  ctx                 The context obtained from libpolkit_new_context
78  *  @return                     Pointer to new context or NULL if an error occured
79  */
80 gboolean
libpolkit_free_context(LibPolKitContext * ctx)81 libpolkit_free_context (LibPolKitContext *ctx)
82 {
83 	LIBPOLKIT_CHECK_CONTEXT (ctx, FALSE);
84 
85 	ctx->magic = 0;
86 	g_free (ctx);
87 	return TRUE;
88 }
89 
90 LibPolKitResult
libpolkit_get_allowed_resources_for_privilege_for_uid(LibPolKitContext * ctx,const char * user,const char * privilege,GList ** resources,GList ** restrictions,int * num_non_temporary)91 libpolkit_get_allowed_resources_for_privilege_for_uid (LibPolKitContext    *ctx,
92 						       const char          *user,
93 						       const char          *privilege,
94 						       GList              **resources,
95 						       GList              **restrictions,
96 						       int                 *num_non_temporary)
97 {
98 	LibPolKitResult res;
99 	char **resource_list;
100 	int num_resources;
101 	char **restriction_list;
102 	int num_restrictions;
103 
104 	LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT);
105 
106 	res = LIBPOLKIT_RESULT_ERROR;
107 	*resources = NULL;
108 	*restrictions = NULL;
109 
110 	res = LIBPOLKIT_RESULT_OK;
111 
112 	return res;
113 }
114 
115 LibPolKitResult
libpolkit_is_uid_allowed_for_privilege(LibPolKitContext * ctx,const char * system_bus_unique_name,const char * user,const char * privilege,const char * resource,gboolean * out_is_allowed,gboolean * out_is_temporary,char ** out_is_privileged_but_restricted_to_system_bus_unique_name)116 libpolkit_is_uid_allowed_for_privilege (LibPolKitContext   *ctx,
117 					const char         *system_bus_unique_name,
118 					const char         *user,
119 					const char         *privilege,
120 					const char         *resource,
121 					gboolean           *out_is_allowed,
122 					gboolean           *out_is_temporary,
123 					char              **out_is_privileged_but_restricted_to_system_bus_unique_name)
124 {
125 	LibPolKitResult res;
126 	const char *myresource = "";
127 	const char *mysystem_bus_unique_name = "";
128 	char *but_restricted_to = NULL;
129 	uid_t uid;
130 	struct passwd *pw;
131 	char *authname;
132 	int i;
133 	gboolean authname_free = FALSE;
134 
135 	LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT);
136 
137 	uid = (uid_t)atol (user);
138 	if ((pw = getpwuid (uid)) == NULL) {
139 		*out_is_allowed = FALSE;
140 		*out_is_temporary = FALSE;
141 		return LIBPOLKIT_RESULT_NO_SUCH_USER;
142 	}
143 
144 	/* map PolicyKit privilege to RBAC authorization */
145 	if (strcmp (privilege, "hal-storage-removable-mount") == 0) {
146 		authname = "solaris.device.mount.removable";
147 	} else if (strcmp (privilege, "hal-storage-removable-mount-all-options") == 0) {
148 		authname = "solaris.device.mount.alloptions.removable";
149 	} else if (strcmp (privilege, "hal-storage-fixed-mount") == 0) {
150 		authname = "solaris.device.mount.fixed";
151 	} else if (strcmp (privilege, "hal-storage-fixed-mount-all-options") == 0) {
152 		authname = "solaris.device.mount.alloptions.fixed";
153 	} else if (strcmp(privilege, "hal-power-suspend") == 0) {
154 		authname = "solaris.system.power.suspend.ram";
155 	} else if (strcmp(privilege, "hal-power-hibernate") == 0) {
156                 authname = "solaris.system.power.suspend.disk";
157 	} else if ((strcmp(privilege, "hal-power-shutdown") == 0) ||
158 	    (strcmp(privilege, "hal-power-reboot") == 0)) {
159                 authname = "solaris.system.shutdown";
160 	} else if (strcmp(privilege, "hal-power-cpu") == 0) {
161                 authname = "solaris.system.power.cpu";
162 	} else if (strcmp(privilege, "hal-power-brightness") == 0) {
163                 authname = "solaris.system.power.brightness";
164 	} else if (strcmp (privilege, "hal-power-cpu") == 0) {
165 		authname = "solaris.system.power.cpu";
166 	} else {
167 		/* replace '-' with '.' */
168 		authname = g_strdup (privilege);
169 		authname_free = TRUE;
170 		for (i = 0; i < strlen (authname); i++) {
171 			if (authname[i] == '-') {
172 				authname[i] = '.';
173 			}
174 		}
175 	}
176 
177 	*out_is_allowed = (chkauthattr(authname, pw->pw_name) != 0);
178 	*out_is_temporary = FALSE;
179 
180 	if (authname_free) {
181 		g_free(authname);
182 	}
183 
184 	return LIBPOLKIT_RESULT_OK;
185 }
186 
187 LibPolKitResult
libpolkit_get_privilege_list(LibPolKitContext * ctx,GList ** result)188 libpolkit_get_privilege_list (LibPolKitContext      *ctx,
189 			      GList                **result)
190 {
191 	LibPolKitResult res;
192 	char **privilege_list;
193 	int num_privileges = 0;
194 	int i;
195 
196 	LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT);
197 
198 	*result = NULL;
199 
200 	for (i = 0; i < num_privileges; i++) {
201 		*result = g_list_append (*result, g_strdup (privilege_list[i]));
202 	}
203 
204 	res = LIBPOLKIT_RESULT_OK;
205 
206 	return res;
207 }
208 
209 LibPolKitResult
libpolkit_revoke_temporary_privilege(LibPolKitContext * ctx,const char * user,const char * privilege,const char * resource,gboolean * result)210 libpolkit_revoke_temporary_privilege (LibPolKitContext      *ctx,
211                                       const char            *user,
212                                       const char            *privilege,
213                                       const char            *resource,
214                                       gboolean              *result)
215 {
216 	return LIBPOLKIT_RESULT_OK;
217 }
218