/* 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) + 1] = "n/a"; char uid_buf[DECIMAL_STR_MAX(uid_t) + 1] = "n/a"; char gid_buf[DECIMAL_STR_MAX(gid_t) + 1] = "n/a"; if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0) xsprintf(login_uid_buf, UID_FMT, login_uid); if (sd_bus_creds_get_euid(audit->creds, &uid) >= 0) xsprintf(uid_buf, UID_FMT, uid); if (sd_bus_creds_get_egid(audit->creds, &gid) >= 0) xsprintf(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 ? "\"" : ""); return 0; }
static int check_good_user(sd_bus_message *m, uid_t good_user) { _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; uid_t sender_uid; int r; assert(m); if (good_user == UID_INVALID) return 0; r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds); if (r < 0) return r; /* Don't trust augmented credentials for authorization */ assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM); r = sd_bus_creds_get_euid(creds, &sender_uid); if (r < 0) return r; return sender_uid == good_user; }
_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; }
static int rename_service(sd_bus *a, sd_bus *b) { _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; _cleanup_free_ char *p = NULL, *name = NULL; const char *comm; char **cmdline; uid_t uid; pid_t pid; int r; assert(a); assert(b); r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; r = sd_bus_creds_get_euid(creds, &uid); if (r < 0) return r; r = sd_bus_creds_get_pid(creds, &pid); if (r < 0) return r; r = sd_bus_creds_get_cmdline(creds, &cmdline); if (r < 0) return r; r = sd_bus_creds_get_comm(creds, &comm); if (r < 0) return r; name = uid_to_name(uid); if (!name) return -ENOMEM; p = strv_join(cmdline, " "); if (!p) return -ENOMEM; /* The status string gets the full command line ... */ sd_notifyf(false, "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)", pid, p, uid, name); /* ... and the argv line only the short comm */ if (arg_command_line_buffer) { size_t m, w; m = strlen(arg_command_line_buffer); w = snprintf(arg_command_line_buffer, m, "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]", pid, comm, uid, name); if (m > w) memzero(arg_command_line_buffer + w, m - w); } log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s", pid, p, uid, name, a->unique_name); return 0; }