Ejemplo n.º 1
0
/*
   Any time an access gets denied this callback will be called
   with the audit data.  We then need to just copy the audit data into the msgbuf.
*/
static int audit_callback(
                void *auditdata,
                security_class_t cls,
                char *msgbuf,
                size_t msgbufsize) {

        const struct audit_info *audit = auditdata;
        uid_t uid = 0, login_uid = 0;
        gid_t gid = 0;
        char login_uid_buf[DECIMAL_STR_MAX(uid_t)] = "n/a";
        char uid_buf[DECIMAL_STR_MAX(uid_t)] = "n/a";
        char gid_buf[DECIMAL_STR_MAX(gid_t)] = "n/a";

        if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0)
                snprintf(login_uid_buf, sizeof(login_uid_buf), UID_FMT, login_uid);
        if (sd_bus_creds_get_uid(audit->creds, &uid) >= 0)
                snprintf(uid_buf, sizeof(uid_buf), UID_FMT, uid);
        if (sd_bus_creds_get_gid(audit->creds, &gid) >= 0)
                snprintf(gid_buf, sizeof(gid_buf), GID_FMT, gid);

        snprintf(msgbuf, msgbufsize,
                 "auid=%s uid=%s gid=%s%s%s%s%s%s%s",
                 login_uid_buf, uid_buf, gid_buf,
                 audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "",
                 audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : "");

        msgbuf[msgbufsize-1] = 0;

        return 0;
}
Ejemplo n.º 2
0
_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
        uid_t our_uid;
        int r;

        assert_return(call, -EINVAL);
        assert_return(call->sealed, -EPERM);
        assert_return(call->bus, -EINVAL);
        assert_return(!bus_pid_changed(call->bus), -ECHILD);

        if (!BUS_IS_OPEN(call->bus->state))
                return -ENOTCONN;

        /* We only trust the effective capability set if this is
         * kdbus. On classic dbus1 we cannot retrieve the value
         * without races. Since this function is supposed to be useful
         * for authentication decision we hence avoid requesting and
         * using that information. */
        if (call->bus->is_kernel && capability >= 0) {
                r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
                if (r < 0)
                        return r;

                r = sd_bus_creds_has_effective_cap(creds, capability);
                if (r > 0)
                        return 1;
        } else {
                r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID, &creds);
                if (r < 0)
                        return r;
        }

        /* Now, check the UID, but only if the capability check wasn't
         * sufficient */
        our_uid = getuid();
        if (our_uid != 0 || !call->bus->is_kernel || capability < 0) {
                uid_t sender_uid;

                r = sd_bus_creds_get_uid(creds, &sender_uid);
                if (r >= 0) {
                        /* Sender has same UID as us, then let's grant access */
                        if (sender_uid == our_uid)
                                return 1;

                        /* Sender is root, we are not root. */
                        if (our_uid != 0 && sender_uid == 0)
                                return 1;
                }
        }

        return 0;
}
Ejemplo n.º 3
0
/*
   Any time an access gets denied this callback will be called
   with the aduit data.  We then need to just copy the audit data into the msgbuf.
*/
static int audit_callback(
                void *auditdata,
                security_class_t cls,
                char *msgbuf,
                size_t msgbufsize) {

        const struct audit_info *audit = auditdata;
        uid_t uid = 0, login_uid = 0;
        gid_t gid = 0;

        sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid);
        sd_bus_creds_get_uid(audit->creds, &uid);
        sd_bus_creds_get_gid(audit->creds, &gid);

        snprintf(msgbuf, msgbufsize,
                 "auid=%d uid=%d gid=%d%s%s%s%s%s%s",
                 login_uid, uid, gid,
                 audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "",
                 audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : "");

        msgbuf[msgbufsize-1] = 0;

        return 0;
}
Ejemplo n.º 4
0
_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
        uid_t our_uid;
        bool know_caps = false;
        int r;

        assert_return(call, -EINVAL);
        assert_return(call->sealed, -EPERM);
        assert_return(call->bus, -EINVAL);
        assert_return(!bus_pid_changed(call->bus), -ECHILD);

        if (!BUS_IS_OPEN(call->bus->state))
                return -ENOTCONN;

        if (capability >= 0) {

                r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
                if (r < 0)
                        return r;

                /* We cannot use augmented caps for authorization,
                 * since then data is acquired raceful from
                 * /proc. This can never actually happen, but let's
                 * better be safe than sorry, and do an extra check
                 * here. */
                assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM);

                r = sd_bus_creds_has_effective_cap(creds, capability);
                if (r > 0)
                        return 1;
                if (r == 0)
                        know_caps = true;
        } else {
                r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds);
                if (r < 0)
                        return r;
        }

        /* Now, check the UID, but only if the capability check wasn't
         * sufficient */
        our_uid = getuid();
        if (our_uid != 0 || !know_caps || capability < 0) {
                uid_t sender_uid;

                /* We cannot use augmented uid/euid for authorization,
                 * since then data is acquired raceful from
                 * /proc. This can never actually happen, but let's
                 * better be safe than sorry, and do an extra check
                 * here. */
                assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM);

                /* Try to use the EUID, if we have it. */
                r = sd_bus_creds_get_euid(creds, &sender_uid);
                if (r < 0)
                        r = sd_bus_creds_get_uid(creds, &sender_uid);

                if (r >= 0) {
                        /* Sender has same UID as us, then let's grant access */
                        if (sender_uid == our_uid)
                                return 1;

                        /* Sender is root, we are not root. */
                        if (our_uid != 0 && sender_uid == 0)
                                return 1;
                }
        }

        return 0;
}
Ejemplo n.º 5
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;
        const char *sender;
#endif
        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
        uid_t uid;
        int r;

        assert(bus);
        assert(registry);
        assert(m);
        assert(action);

#ifdef ENABLE_POLKIT
        q = hashmap_get(*registry, m);
        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_creds(m, SD_BUS_CREDS_UID, &creds);
        if (r < 0)
                return r;

        r = sd_bus_creds_get_uid(creds, &uid);
        if (r < 0)
                return r;

        if (uid == 0)
                return 1;

#ifdef ENABLE_POLKIT
        sender = sd_bus_message_get_sender(m);
        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(
                        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,
                        NULL);
        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;
        }

        q->registry = *registry;

        r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
        if (r < 0) {
                async_polkit_query_free(bus, q);
                return r;
        }

        return 0;
#endif

        return -EACCES;
}
Ejemplo n.º 6
0
int bus_verify_polkit(
                sd_bus *bus,
                sd_bus_message *m,
                const char *action,
                bool interactive,
                bool *_challenge,
                sd_bus_error *e) {

        _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
        uid_t uid;
        int r;

        assert(bus);
        assert(m);
        assert(action);

        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
        if (r < 0)
                return r;

        r = sd_bus_creds_get_uid(creds, &uid);
        if (r < 0)
                return r;

        if (uid == 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(m);
                if (!sender)
                        return -EBADMSG;

                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_enter_container(reply, 'r', "bba{ss}");
                if (r >= 0)
                        r = sd_bus_message_read(reply, "bb", &authorized, &challenge);

                if (authorized)
                        return 1;

                if (_challenge) {
                        *_challenge = challenge;
                        return 0;
                }
        }
#endif

        return -EACCES;
}