add get_file_sha256(path) to util.c
[systembsd.git] / src / util.c
1 /*
2 * Copyright (c) 2014 Ian Sutton <ian@kremlin.cc>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <unistd.h>
18 #include <limits.h>
19 #include <string.h>
20
21 #include <glib/gprintf.h>
22 #include <glib-unix.h>
23 #include <polkit/polkit.h>
24
25 #include "util.h"
26
27 const gint MAX_TOKENS = 20;
28
29 /* return must be g_free()'d */
30 gchar *get_file_sha256(const gchar *path) {
31
32 gchar *checksum;
33 GMappedFile *file;
34 GBytes *data;
35 GError *err = NULL;
36
37 file = g_mapped_file_new(path, FALSE, &err);
38
39 if(file) {
40
41 data = g_mapped_file_get_bytes(file);
42 g_mapped_file_unref(file);
43 checksum = g_compute_checksum_for_bytes(G_CHECKSUM_SHA256, data);
44 return checksum;
45 } else
46 return NULL;
47 }
48
49 /* return must be g_free()'d */
50 gchar *config_get(const gchar *path, gchar *key) {
51
52 gchar *content, **split_content, *cur, **cur_split, *ret;
53 GError *err;
54 int incr = 0;
55 gboolean breaker = TRUE;
56
57 ret = (gchar *) g_malloc0(4096);
58
59 if(!g_file_get_contents(path, &content, NULL, &err))
60 return NULL;
61
62 split_content = g_strsplit(content, "\n", MAX_TOKENS);
63
64 while(breaker && (cur = split_content[incr]) && (cur_split = g_strsplit(cur, "=", 2))) {
65
66 if(!g_strcmp0(key, cur_split[0])) {
67
68 g_strlcpy(ret, cur_split[1], 2048);
69 breaker = FALSE;
70 }
71
72 incr++;
73 g_strfreev(cur_split);
74 }
75
76 if(split_content)
77 g_strfreev(split_content);
78 if(content)
79 g_free(content);
80
81 return (ret ? ret : NULL);
82 }
83
84 gboolean config_set(const gchar *path, gchar *key, gchar *value) {
85
86 gchar *content, **split_content, *cur, **cur_split, *rewrite;
87 GError *err_set, *err_get;
88 gboolean ret = FALSE;
89 int incr = 0;
90 gboolean breaker = TRUE;
91
92 err_get = err_set = NULL;
93
94 if(!g_file_get_contents(path, &content, NULL, &err_get))
95 return FALSE;
96
97 split_content = g_strsplit(content, "\n", MAX_TOKENS);
98
99 while(breaker && (cur = split_content[incr]) && (cur_split = g_strsplit(cur, "=", 2))) {
100
101 if(!g_strcmp0(key, cur_split[0])) {
102
103 cur_split[1] = value;
104 split_content[incr] = g_strjoinv("=", cur_split);
105 ret = TRUE;
106 breaker = FALSE;
107 }
108
109 incr++;
110 }
111
112 if(ret) {
113
114 rewrite = g_strjoinv("\n", split_content);
115 ret = g_file_set_contents(path, rewrite, -1, &err_set);
116 g_free(rewrite);
117 }
118
119 if(cur_split)
120 g_strfreev(cur_split);
121 if(split_content)
122 g_strfreev(split_content);
123 if(content)
124 g_free(content);
125
126 return ret;
127 }
128
129 static gboolean is_valid_action(GList *action_list, const gchar *action) {
130
131 PolkitActionDescription *action_descr;
132 const gchar *action_descr_id;
133 GList *cur;
134 gboolean ret;
135
136 ret = FALSE;
137 cur = g_list_first(action_list);
138
139 while(cur && (action_descr = ((PolkitActionDescription *)(cur->data))) && (action_descr_id = polkit_action_description_get_action_id(action_descr))) {
140
141 if(!g_strcmp0(action, action_descr_id)) {
142 ret = TRUE;
143 break;
144 }
145
146 cur = cur->next;
147 }
148
149 g_list_free(action_list);
150
151 return ret;
152 }
153
154 check_auth_result polkit_try_auth(const gchar *bus, const gchar *action, gboolean prompt) {
155
156 GList *valid_actions;
157 PolkitAuthority *auth;
158 PolkitSubject *subj;
159 PolkitAuthorizationResult *result;
160 PolkitCheckAuthorizationFlags prompt_flag;
161 gboolean authorized, challenge;
162
163 auth = NULL;
164 subj = NULL;
165 result = NULL;
166 valid_actions = NULL;
167 authorized = challenge = FALSE;
168 prompt_flag = prompt ? POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION : POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
169
170 auth = polkit_authority_get_sync(NULL, NULL); /* TODO timeout for this */
171 subj = polkit_system_bus_name_new(bus);
172 valid_actions = polkit_authority_enumerate_actions_sync(auth, NULL, NULL);
173
174 if(!auth || !valid_actions)
175 return ERROR_GENERIC; /* extremely unlikely */
176 else if(!subj)
177 return ERROR_BADBUS;
178 else if(!is_valid_action(valid_actions, action))
179 return ERROR_BADACTION;
180
181 if(!(result = polkit_authority_check_authorization_sync(auth, subj, action, NULL, prompt_flag, NULL, NULL)))
182 return ERROR_GENERIC; /* TODO pass, check gerror and return more relevant error */
183
184 authorized = polkit_authorization_result_get_is_authorized(result);
185 challenge = polkit_authorization_result_get_is_challenge(result);
186
187 /* free()'s before return */
188 if(auth)
189 g_object_unref(auth);
190 if(subj)
191 g_object_unref(subj);
192 if(result)
193 g_object_unref(result);
194
195 if(authorized) {
196
197 if(challenge)
198 return AUTHORIZED_BY_PROMPT;
199
200 return AUTHORIZED_NATIVELY;
201
202 } else if(challenge)
203 return UNAUTHORIZED_FAILED_PROMPT;
204
205 return UNAUTHORIZED_NATIVELY;
206 }