static int PmonInit(sd_bus_message *m, void *userdata, sd_bus_error *retError) { usec_t time = 0; sd_bus_message_read(m, "t", &time); int id = 0; if (openSlots == 0) { return sd_bus_reply_method_return(m, "u", -1); } uint64_t usec = 0; sd_event_now(event, CLOCK_MONOTONIC, &usec); usec += time; if (clients[lastAllocatedId] == NULL) { id = lastAllocatedId; sd_event_add_time(event, &clients[lastAllocatedId], CLOCK_MONOTONIC, usec, 1000, Timeout, (void *)sd_bus_message_get_sender(m)); lastAllocatedId += 1; openSlots -= 1; clientTimeout[id] = time; return sd_bus_reply_method_return(m, "u", id); } id = freeIds[lastFreedSlot]; sd_event_add_time(event, &clients[freeIds[lastFreedSlot]], CLOCK_MONOTONIC, usec, 1000, Timeout, (void *)sd_bus_message_get_sender(m)); lastFreedSlot -= 1; openSlots -= 1; clientTimeout[id] = time; return sd_bus_reply_method_return(m, "u", id); }
int bus_job_method_cancel(sd_bus_message *message, void *userdata, sd_bus_error *error) { Job *j = userdata; int r; assert(message); assert(j); r = mac_selinux_unit_access_check(j->unit, message, "stop", error); if (r < 0) return r; /* Access is granted to the job owner */ if (!sd_bus_track_contains(j->clients, sd_bus_message_get_sender(message))) { /* And for everybody else consult PolicyKit */ r = bus_verify_manage_units_async(j->unit->manager, message, error); if (r < 0) return r; if (r == 0) return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ } job_finish_and_invalidate(j, JOB_CANCELED, true); return sd_bus_reply_method_return(message, NULL); }
_public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) { const char *sender; assert_return(track, -EINVAL); assert_return(m, -EINVAL); sender = sd_bus_message_get_sender(m); if (!sender) return -EINVAL; return sd_bus_track_remove_name(track, sender); }
static int verify_sys_admin_or_owner_sync(sd_bus_message *message, Job *j, sd_bus_error *error) { int r; if (sd_bus_track_contains(j->clients, sd_bus_message_get_sender(message))) return 0; /* One of the job owners is calling us */ r = sd_bus_query_sender_privilege(message, CAP_SYS_ADMIN); if (r < 0) return r; if (r == 0) return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access denied to perform action"); /* Root has called us */ return 0; }
static int PmonPing(sd_bus_message *m, void *userdata, sd_bus_error *retError) { int id = 0; sd_bus_message_read(m, "u", &id); char *sid = (char*)sd_event_source_get_userdata(clients[id]); if (sid == NULL) { return sd_bus_reply_method_return(m, "b", false); } if (strcmp((char*)sd_event_source_get_userdata(clients[id]), sd_bus_message_get_sender(m)) != 0) { return sd_bus_reply_method_return(m, "b", false); } uint64_t usec = 0; sd_event_now(event, CLOCK_MONOTONIC, &usec); sd_event_source_set_time(clients[id], clientTimeout[id]+usec); return sd_bus_reply_method_return(m, "b", true); }
static int PmonRemove(sd_bus_message *m, void *userdata, sd_bus_error *retError) { int id = 0; sd_bus_message_read(m, "u", &id); char *sid = (char*)sd_event_source_get_userdata(clients[id]); if (sid == NULL) { return sd_bus_reply_method_return(m, "b", false); } if (strcmp((char*)sd_event_source_get_userdata(clients[id]), sd_bus_message_get_sender(m)) != 0) { return sd_bus_reply_method_return(m, "b", false); } sd_event_source_set_enabled(clients[id], SD_EVENT_OFF); sd_event_source_unref(clients[id]); //systemd will gc object after unrefing it. clients[id] = NULL; lastFreedSlot += 1; openSlots += 1; freeIds[lastFreedSlot] = id; return sd_bus_reply_method_return(m, "b", true); }
int bus_verify_polkit_async( sd_bus_message *call, int capability, const char *action, bool interactive, Hashmap **registry, sd_bus_error *error) { #ifdef ENABLE_POLKIT _cleanup_bus_message_unref_ sd_bus_message *pk = NULL; AsyncPolkitQuery *q; const char *sender; sd_bus_message_handler_t callback; void *userdata; #endif int r; assert(call); assert(action); assert(registry); #ifdef ENABLE_POLKIT q = hashmap_get(*registry, call); if (q) { int authorized, challenge; /* This is the second invocation of this function, and * there's already a response from polkit, let's * process it */ assert(q->reply); if (sd_bus_message_is_method_error(q->reply, NULL)) { const sd_bus_error *e; /* Copy error from polkit reply */ e = sd_bus_message_get_error(q->reply); sd_bus_error_copy(error, e); /* Treat no PK available as access denied */ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) return -EACCES; return -sd_bus_error_get_errno(e); } r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}"); if (r >= 0) r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge); if (r < 0) return r; if (authorized) return 1; return -EACCES; } #endif r = sd_bus_query_sender_privilege(call, capability); if (r < 0) return r; else if (r > 0) return 1; #ifdef ENABLE_POLKIT if (sd_bus_get_current_message(call->bus) != call) return -EINVAL; callback = sd_bus_get_current_handler(call->bus); if (!callback) return -EINVAL; userdata = sd_bus_get_current_userdata(call->bus); sender = sd_bus_message_get_sender(call); if (!sender) return -EBADMSG; r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func); if (r < 0) return r; r = sd_bus_message_new_method_call( call->bus, &pk, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization"); if (r < 0) return r; r = sd_bus_message_append( pk, "(sa{sv})sa{ss}us", "system-bus-name", 1, "name", "s", sender, action, 0, interactive ? 1 : 0, NULL); if (r < 0) return r; q = new0(AsyncPolkitQuery, 1); if (!q) return -ENOMEM; q->request = sd_bus_message_ref(call); q->callback = callback; q->userdata = userdata; r = hashmap_put(*registry, call, q); if (r < 0) { async_polkit_query_free(q); return r; } q->registry = *registry; r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0); if (r < 0) { async_polkit_query_free(q); return r; } return 0; #endif return -EACCES; }
int bus_verify_polkit( sd_bus_message *call, int capability, const char *action, bool interactive, bool *_challenge, sd_bus_error *e) { int r; assert(call); assert(action); r = sd_bus_query_sender_privilege(call, capability); if (r < 0) return r; else if (r > 0) return 1; #ifdef ENABLE_POLKIT else { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; int authorized = false, challenge = false; const char *sender; sender = sd_bus_message_get_sender(call); if (!sender) return -EBADMSG; r = sd_bus_call_method( call->bus, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization", e, &reply, "(sa{sv})sa{ss}us", "system-bus-name", 1, "name", "s", sender, action, 0, interactive ? 1 : 0, ""); if (r < 0) { /* Treat no PK available as access denied */ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) { sd_bus_error_free(e); return -EACCES; } return r; } r = sd_bus_message_enter_container(reply, 'r', "bba{ss}"); if (r < 0) return r; r = sd_bus_message_read(reply, "bb", &authorized, &challenge); if (r < 0) return r; if (authorized) return 1; if (_challenge) { *_challenge = challenge; return 0; } } #endif return -EACCES; }
int bus_test_polkit( sd_bus_message *call, int capability, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e) { int r; assert(call); assert(action); /* Tests non-interactively! */ r = check_good_user(call, good_user); if (r != 0) return r; r = sd_bus_query_sender_privilege(call, capability); if (r < 0) return r; else if (r > 0) return 1; #ifdef ENABLE_POLKIT else { _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int authorized = false, challenge = false; const char *sender, **k, **v; sender = sd_bus_message_get_sender(call); if (!sender) return -EBADMSG; r = sd_bus_message_new_method_call( call->bus, &request, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization"); if (r < 0) return r; r = sd_bus_message_append( request, "(sa{sv})s", "system-bus-name", 1, "name", "s", sender, action); if (r < 0) return r; r = sd_bus_message_open_container(request, 'a', "{ss}"); if (r < 0) return r; STRV_FOREACH_PAIR(k, v, details) { r = sd_bus_message_append(request, "{ss}", *k, *v); if (r < 0) return r; } r = sd_bus_message_close_container(request); if (r < 0) return r; r = sd_bus_message_append(request, "us", 0, NULL); if (r < 0) return r; r = sd_bus_call(call->bus, request, 0, e, &reply); if (r < 0) { /* Treat no PK available as access denied */ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) { sd_bus_error_free(e); return -EACCES; } return r; } r = sd_bus_message_enter_container(reply, 'r', "bba{ss}"); if (r < 0) return r; r = sd_bus_message_read(reply, "bb", &authorized, &challenge); if (r < 0) return r; if (authorized) return 1; if (_challenge) { *_challenge = challenge; return 0; } }
int bus_verify_polkit_async( sd_bus *bus, Hashmap **registry, sd_bus_message *m, const char *action, bool interactive, sd_bus_error *error, sd_bus_message_handler_t callback, void *userdata) { #ifdef ENABLE_POLKIT _cleanup_bus_message_unref_ sd_bus_message *pk = NULL; AsyncPolkitQuery *q; #endif const char *sender; uid_t uid; int r; assert(bus); assert(registry); assert(m); assert(action); #ifdef ENABLE_POLKIT q = hashmap_remove(*registry, m); if (q) { unsigned authorized, challenge; /* This is the second invocation of this function, and * there's already a response from polkit, let's * process it */ assert(q->reply); if (sd_bus_message_is_method_error(q->reply, NULL)) { const sd_bus_error *e; /* Treat no PK available as access denied */ if (sd_bus_message_is_method_error(q->reply, SD_BUS_ERROR_SERVICE_UNKNOWN)) { async_polkit_query_free(bus, q); return -EACCES; } e = sd_bus_message_get_error(q->reply); sd_bus_error_copy(error, e); r = sd_bus_error_get_errno(e); async_polkit_query_free(bus, q); return r; } r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}"); if (r >= 0) r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge); async_polkit_query_free(bus, q); if (r < 0) return r; if (authorized) return 1; return -EACCES; } #endif sender = sd_bus_message_get_sender(m); if (!sender) return -EBADMSG; r = sd_bus_get_owner_uid(bus, sender, &uid); if (r < 0) return r; if (uid == 0) return 1; #ifdef ENABLE_POLKIT r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func); if (r < 0) return r; r = sd_bus_message_new_method_call( bus, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization", &pk); if (r < 0) return r; r = sd_bus_message_append( pk, "(sa{sv})sa{ss}us", "system-bus-name", 1, "name", "s", sender, action, 0, interactive ? 1 : 0, ""); if (r < 0) return r; q = new0(AsyncPolkitQuery, 1); if (!q) return -ENOMEM; q->request = sd_bus_message_ref(m); q->callback = callback; q->userdata = userdata; r = hashmap_put(*registry, m, q); if (r < 0) { async_polkit_query_free(bus, q); return r; } r = sd_bus_send_with_reply(bus, pk, async_polkit_callback, q, 0, &q->serial); if (r < 0) return r; return 0; #endif return -EACCES; }
int bus_verify_polkit( sd_bus *bus, sd_bus_message *m, const char *action, bool interactive, bool *_challenge, sd_bus_error *e) { const char *sender; uid_t uid; int r; assert(bus); assert(m); assert(action); sender = sd_bus_message_get_sender(m); if (!sender) return -EBADMSG; r = sd_bus_get_owner_uid(bus, sender, &uid); if (r < 0) return r; if (uid == 0) return 1; #ifdef ENABLE_POLKIT else { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; unsigned authorized = false, challenge = false; r = sd_bus_call_method( bus, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", "CheckAuthorization", e, &reply, "(sa{sv})sa{ss}us", "system-bus-name", 1, "name", "s", sender, action, 0, interactive ? 1 : 0, ""); if (r < 0) { /* Treat no PK available as access denied */ if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) { sd_bus_error_free(e); return -EACCES; } return r; } r = sd_bus_message_read(reply, "(bb)", &authorized, &challenge); if (r < 0) return r; if (authorized) return 1; if (_challenge) { *_challenge = challenge; return 0; } } #endif return -EACCES; }