usb_moded 0.86.0+mer64
usb_moded-user.c
Go to the documentation of this file.
1
24
25#include "usb_moded-user.h"
26#include "usb_moded-control.h"
27#include "usb_moded-log.h"
28
29#include <systemd/sd-login.h>
30
31/* ========================================================================= *
32 * Prototypes
33 * ========================================================================= */
34
35/* ------------------------------------------------------------------------- *
36 * USER
37 * ------------------------------------------------------------------------- */
38
39static void user_update_current_user(void);
40static void user_set_current_user (uid_t uid);
41uid_t user_get_current_user (void);
42
43/* ------------------------------------------------------------------------- *
44 * USER_WATCH
45 * ------------------------------------------------------------------------- */
46
47static gboolean user_watch_monitor_event_cb(GIOChannel *iochannel, GIOCondition cond, gpointer data);
48static bool user_watch_connect (void);
49static void user_watch_disconnect (void);
50bool user_watch_init (void);
51void user_watch_stop (void);
52
53/* ========================================================================= *
54 * Data
55 * ========================================================================= */
56
57static sd_login_monitor *user_watch_monitor = NULL;
58static guint user_change_watch_id = 0;
59static uid_t user_current_uid = UID_UNKNOWN;
60
61/* ========================================================================= *
62 * Functions
63 * ========================================================================= */
64
71static void user_update_current_user(void)
72{
73#ifdef SAILFISH_ACCESS_CONTROL
74 uid_t active_uid = UID_UNKNOWN;
75 char **sessions = NULL;
76
77 int rc;
78
79 if( (rc = sd_get_sessions(&sessions)) < 0 ) {
80 log_warning("sd_get_sessions: %s", strerror(-rc));
81 goto EXIT;
82 }
83
84 if( rc < 1 || !sessions )
85 goto EXIT;
86
87 for( size_t i = 0; active_uid == UID_UNKNOWN && sessions[i]; ++i ) {
88 uid_t uid = UID_UNKNOWN;
89 char *seat = NULL;
90 char *state = NULL;
91
92 if( (rc = sd_session_get_uid(sessions[i], &uid)) < 0 ) {
93 log_warning("sd_session_get_uid(%s): %s",
94 sessions[i], strerror(-rc));
95 }
96 else if( (rc = sd_session_get_state(sessions[i], &state)) < 0 ) {
97 log_warning("sd_session_get_state(%s): %s",
98 sessions[i], strerror(-rc));
99 }
100 else if( (rc = sd_session_get_seat(sessions[i], &seat)) < 0 ) {
101 /* NB: It is normal to have sessions without a seat, but
102 * sd_session_get_seat() reports error on such cases
103 * and we do not want that to cause logging noise.
104 */
105 }
106 else if( state && seat && !strcmp(seat, "seat0") ) {
107 log_debug("session: seat=%s uid=%d state=%s", seat, (int)uid, state);
108 if( !strcmp(state, "active") || !strcmp(state, "online") )
109 active_uid = uid;
110 }
111
112 free(state);
113 free(seat);
114 }
115
116EXIT:
117 if( sessions ) {
118 for( size_t i = 0; sessions[i]; ++i )
119 free(sessions[i]);
120 free(sessions);
121 }
122
123 user_set_current_user(active_uid);
124#else
125 user_set_current_user(0);
126#endif
127}
128
129static void user_set_current_user(uid_t uid)
130{
131 // User changed
132 if ( user_current_uid != uid ) {
133 log_debug("user_current_uid: %d -> %d",
134 (int)user_current_uid, (int)uid);
135 user_current_uid = uid;
137 }
138}
139
152{
153 return user_current_uid;
154}
155
158static gboolean user_watch_monitor_event_cb(GIOChannel *iochannel G_GNUC_UNUSED, GIOCondition cond,
159 gpointer data G_GNUC_UNUSED)
160{
161 LOG_REGISTER_CONTEXT;
162 bool success = true;
163
164 if( cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL) ) {
165 log_crit("user watch hangup/error");
166 success = false;
167 goto EXIT;
168 }
169 user_update_current_user();
170
171 sd_login_monitor_flush(user_watch_monitor);
172
173EXIT:
174 if ( !success ) {
175 user_change_watch_id = 0;
176 user_watch_disconnect();
177 return G_SOURCE_REMOVE;
178 }
179 return G_SOURCE_CONTINUE;
180}
181
182static bool user_watch_connect(void)
183{
184 LOG_REGISTER_CONTEXT;
185
186 bool success = false;
187 GIOChannel *iochan = NULL;
188
189 if ( sd_login_monitor_new("session", &user_watch_monitor) < 0 ) {
190 log_err("Failed to create login monitor\n");
191 goto EXIT;
192 }
193
194 user_update_current_user();
195
196 iochan = g_io_channel_unix_new(sd_login_monitor_get_fd(user_watch_monitor));
197 if ( !iochan ) {
198 log_err("Failed to setup I/O channel for sd_login_monitor\n");
199 goto EXIT;
200 }
201
202 user_change_watch_id = g_io_add_watch(iochan,
203 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
204 user_watch_monitor_event_cb,
205 NULL);
206 if ( user_change_watch_id )
207 success = true;
208
209EXIT:
210 if ( iochan )
211 g_io_channel_unref(iochan);
212 if ( !success )
213 user_watch_disconnect();
214 return success;
215}
216
217static void user_watch_disconnect(void)
218{
219 LOG_REGISTER_CONTEXT;
220
221 if ( user_change_watch_id ) {
222 g_source_remove(user_change_watch_id);
223 user_change_watch_id = 0;
224 }
225 if ( user_watch_monitor ) {
226 sd_login_monitor_unref(user_watch_monitor);
227 user_watch_monitor = NULL;
228 }
229}
230
231bool user_watch_init(void)
232{
233 LOG_REGISTER_CONTEXT;
234
235 return user_watch_connect();
236}
237
238void user_watch_stop(void)
239{
240 LOG_REGISTER_CONTEXT;
241
242 user_watch_disconnect();
243}
void control_user_changed(void)
uid_t user_get_current_user(void)