Compare commits
11 Commits
5dd1469ef1
...
fbc6d1716f
Author | SHA1 | Date |
---|---|---|
Zbigniew Jędrzejewski-Szmek | fbc6d1716f | |
Lennart Poettering | c8f145adbb | |
Lennart Poettering | 1a53adb3ab | |
Lennart Poettering | 2fcbf417b6 | |
Lennart Poettering | fa3709c5fb | |
Lennart Poettering | e8dd54ab3c | |
Lennart Poettering | b847192699 | |
Lennart Poettering | 20f4a308bf | |
Lennart Poettering | e4005ffe00 | |
Lennart Poettering | 5b3f4a20ea | |
Lennart Poettering | cbffdcecae |
|
@ -202,6 +202,13 @@ static int write_string_file_atomic(
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FLAGS_SET(flags, WRITE_STRING_FILE_SYNC)) {
|
||||||
|
/* Sync the rename, too */
|
||||||
|
r = fsync_directory_of_file(fileno(f));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
|
@ -292,7 +292,7 @@ int home_save_record(Home *h) {
|
||||||
|
|
||||||
fn = strjoina("/var/lib/systemd/home/", h->user_name, ".identity");
|
fn = strjoina("/var/lib/systemd/home/", h->user_name, ".identity");
|
||||||
|
|
||||||
r = write_string_file(fn, text, WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MODE_0600);
|
r = write_string_file(fn, text, WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MODE_0600|WRITE_STRING_FILE_SYNC);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -471,6 +471,8 @@ static int convert_worker_errno(Home *h, int e, sd_bus_error *error) {
|
||||||
return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_ACTIVE, "Home %s is currently not active", h->user_name);
|
return sd_bus_error_setf(error, BUS_ERROR_HOME_NOT_ACTIVE, "Home %s is currently not active", h->user_name);
|
||||||
case -ENOSPC:
|
case -ENOSPC:
|
||||||
return sd_bus_error_setf(error, BUS_ERROR_NO_DISK_SPACE, "Not enough disk space for home %s", h->user_name);
|
return sd_bus_error_setf(error, BUS_ERROR_NO_DISK_SPACE, "Not enough disk space for home %s", h->user_name);
|
||||||
|
case -EKEYREVOKED:
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_HOME_CANT_AUTHENTICATE, "Home %s has no password or other authentication mechanism defined.", h->user_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -329,21 +329,36 @@ static int manager_add_home_by_record(
|
||||||
_cleanup_(user_record_unrefp) UserRecord *hr = NULL;
|
_cleanup_(user_record_unrefp) UserRecord *hr = NULL;
|
||||||
unsigned line, column;
|
unsigned line, column;
|
||||||
int r, is_signed;
|
int r, is_signed;
|
||||||
|
struct stat st;
|
||||||
Home *h;
|
Home *h;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(name);
|
assert(name);
|
||||||
assert(fname);
|
assert(fname);
|
||||||
|
|
||||||
|
if (fstatat(dir_fd, fname, &st, 0) < 0)
|
||||||
|
return log_error_errno(errno, "Failed to stat identity record %s: %m", fname);
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode)) {
|
||||||
|
log_debug("Identity record file %s is not a regular file, ignoring.", fname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_size == 0)
|
||||||
|
goto unlink_this_file;
|
||||||
|
|
||||||
r = json_parse_file_at(NULL, dir_fd, fname, JSON_PARSE_SENSITIVE, &v, &line, &column);
|
r = json_parse_file_at(NULL, dir_fd, fname, JSON_PARSE_SENSITIVE, &v, &line, &column);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to parse identity record at %s:%u%u: %m", fname, line, column);
|
return log_error_errno(r, "Failed to parse identity record at %s:%u%u: %m", fname, line, column);
|
||||||
|
|
||||||
|
if (json_variant_is_blank_object(v))
|
||||||
|
goto unlink_this_file;
|
||||||
|
|
||||||
hr = user_record_new();
|
hr = user_record_new();
|
||||||
if (!hr)
|
if (!hr)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET);
|
r = user_record_load(hr, v, USER_RECORD_LOAD_REFUSE_SECRET|USER_RECORD_LOG);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -394,6 +409,19 @@ static int manager_add_home_by_record(
|
||||||
h->signed_locally = is_signed == USER_RECORD_SIGNED_EXCLUSIVE;
|
h->signed_locally = is_signed == USER_RECORD_SIGNED_EXCLUSIVE;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
unlink_this_file:
|
||||||
|
/* If this is an empty file, then let's just remove it. An empty file is not useful in any case, and
|
||||||
|
* apparently xfs likes to leave empty files around when not unmounted cleanly (see
|
||||||
|
* https://github.com/systemd/systemd/issues/15178 for example). Note that we don't delete non-empty
|
||||||
|
* files even if they are invalid, because that's just too risky, we might delete data the user still
|
||||||
|
* needs. But empty files are never useful, hence let's just remove them. */
|
||||||
|
|
||||||
|
if (unlinkat(dir_fd, fname, 0) < 0)
|
||||||
|
return log_error_errno(errno, "Failed to remove empty user record file %s: %m", fname);
|
||||||
|
|
||||||
|
log_notice("Discovered empty user record file /var/lib/systemd/home/%s, removed automatically.", fname);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_enumerate_records(Manager *m) {
|
static int manager_enumerate_records(Manager *m) {
|
||||||
|
@ -485,7 +513,7 @@ static int search_quota(uid_t uid, const char *exclude_quota_path) {
|
||||||
if (ERRNO_IS_NOT_SUPPORTED(r))
|
if (ERRNO_IS_NOT_SUPPORTED(r))
|
||||||
log_debug_errno(r, "No UID quota support on %s, ignoring.", where);
|
log_debug_errno(r, "No UID quota support on %s, ignoring.", where);
|
||||||
else
|
else
|
||||||
log_warning_errno(r, "Failed to query quota on %s, ignoring.", where);
|
log_warning_errno(r, "Failed to query quota on %s, ignoring: %m", where);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1309,7 +1337,7 @@ static int manager_generate_key_pair(Manager *m) {
|
||||||
if (PEM_write_PUBKEY(fpublic, m->private_key) <= 0)
|
if (PEM_write_PUBKEY(fpublic, m->private_key) <= 0)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key.");
|
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write public key.");
|
||||||
|
|
||||||
r = fflush_and_check(fpublic);
|
r = fflush_sync_and_check(fpublic);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to write private key: %m");
|
return log_error_errno(r, "Failed to write private key: %m");
|
||||||
|
|
||||||
|
@ -1323,7 +1351,7 @@ static int manager_generate_key_pair(Manager *m) {
|
||||||
if (PEM_write_PrivateKey(fprivate, m->private_key, NULL, NULL, 0, NULL, 0) <= 0)
|
if (PEM_write_PrivateKey(fprivate, m->private_key, NULL, NULL, 0, NULL, 0) <= 0)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write private key pair.");
|
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to write private key pair.");
|
||||||
|
|
||||||
r = fflush_and_check(fprivate);
|
r = fflush_sync_and_check(fprivate);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to write private key: %m");
|
return log_error_errno(r, "Failed to write private key: %m");
|
||||||
|
|
||||||
|
@ -1337,10 +1365,14 @@ static int manager_generate_key_pair(Manager *m) {
|
||||||
|
|
||||||
if (rename(temp_private, "/var/lib/systemd/home/local.private") < 0) {
|
if (rename(temp_private, "/var/lib/systemd/home/local.private") < 0) {
|
||||||
(void) unlink_noerrno("/var/lib/systemd/home/local.public"); /* try to remove the file we already created */
|
(void) unlink_noerrno("/var/lib/systemd/home/local.public"); /* try to remove the file we already created */
|
||||||
return log_error_errno(errno, "Failed to move privtate key file into place: %m");
|
return log_error_errno(errno, "Failed to move private key file into place: %m");
|
||||||
}
|
}
|
||||||
temp_private = mfree(temp_private);
|
temp_private = mfree(temp_private);
|
||||||
|
|
||||||
|
r = fsync_path_at(AT_FDCWD, "/var/lib/systemd/home/");
|
||||||
|
if (r < 0)
|
||||||
|
log_warning_errno(r, "Failed to sync /var/lib/systemd/home/, ignoring: %m");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -727,9 +727,10 @@ static int luks_validate_home_record(
|
||||||
if (!user_record_compatible(h, lhr))
|
if (!user_record_compatible(h, lhr))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "LUKS home record not compatible with host record, refusing.");
|
return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "LUKS home record not compatible with host record, refusing.");
|
||||||
|
|
||||||
r = user_record_authenticate(lhr, h, pkcs11_decrypted_passwords);
|
r = user_record_authenticate(lhr, h, pkcs11_decrypted_passwords, /* strict_verify= */ true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
assert(r > 0); /* Insist that a password was verified */
|
||||||
|
|
||||||
*ret_luks_home_record = TAKE_PTR(lhr);
|
*ret_luks_home_record = TAKE_PTR(lhr);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
int user_record_authenticate(
|
int user_record_authenticate(
|
||||||
UserRecord *h,
|
UserRecord *h,
|
||||||
UserRecord *secret,
|
UserRecord *secret,
|
||||||
char ***pkcs11_decrypted_passwords) {
|
char ***pkcs11_decrypted_passwords,
|
||||||
|
bool strict_verify) {
|
||||||
|
|
||||||
bool need_password = false, need_token = false, need_pin = false, need_protected_authentication_path_permitted = false,
|
bool need_password = false, need_token = false, need_pin = false, need_protected_authentication_path_permitted = false,
|
||||||
pin_locked = false, pin_incorrect = false, pin_incorrect_few_tries_left = false, pin_incorrect_one_try_left = false;
|
pin_locked = false, pin_incorrect = false, pin_incorrect_few_tries_left = false, pin_incorrect_one_try_left = false;
|
||||||
|
@ -66,7 +67,7 @@ int user_record_authenticate(
|
||||||
return log_error_errno(r, "Failed to validate password of record: %m");
|
return log_error_errno(r, "Failed to validate password of record: %m");
|
||||||
else {
|
else {
|
||||||
log_info("Provided password unlocks user record.");
|
log_info("Provided password unlocks user record.");
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Second, let's see if any of the PKCS#11 security tokens are plugged in and help us */
|
/* Second, let's see if any of the PKCS#11 security tokens are plugged in and help us */
|
||||||
|
@ -86,7 +87,7 @@ int user_record_authenticate(
|
||||||
return log_error_errno(r, "Failed to check supplied PKCS#11 password: %m");
|
return log_error_errno(r, "Failed to check supplied PKCS#11 password: %m");
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
log_info("Previously acquired PKCS#11 password unlocks user record.");
|
log_info("Previously acquired PKCS#11 password unlocks user record.");
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ int user_record_authenticate(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
need_token = true;
|
need_token = true;
|
||||||
|
@ -156,7 +157,18 @@ int user_record_authenticate(
|
||||||
return -ENOKEY;
|
return -ENOKEY;
|
||||||
|
|
||||||
/* Hmm, this means neither PCKS#11 nor classic hashed passwords were supplied, we cannot authenticate this reasonably */
|
/* Hmm, this means neither PCKS#11 nor classic hashed passwords were supplied, we cannot authenticate this reasonably */
|
||||||
return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED), "No hashed passwords and no PKCS#11 tokens defined, cannot authenticate user record.");
|
if (strict_verify)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(EKEYREVOKED),
|
||||||
|
"No hashed passwords and no PKCS#11 tokens defined, cannot authenticate user record, refusing.");
|
||||||
|
|
||||||
|
/* If strict verification is off this means we are possibly in the case where we encountered an
|
||||||
|
* unfixated record, i.e. a synthetic one that accordingly lacks any authentication data. In this
|
||||||
|
* case, allow the authentication to pass for now, so that the second (or third) authentication level
|
||||||
|
* (the ones of the user record in the LUKS header or inside the home directory) will then catch
|
||||||
|
* invalid passwords. The second/third authentication always runs in strict verification mode. */
|
||||||
|
log_debug("No hashed passwords and no PKCS#11 tokens defined in record, cannot authenticate user record. "
|
||||||
|
"Deferring to embedded user record.");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int home_setup_undo(HomeSetup *setup) {
|
int home_setup_undo(HomeSetup *setup) {
|
||||||
|
@ -402,9 +414,10 @@ int home_load_embedded_identity(
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "Embedded home record not compatible with host record, refusing.");
|
return log_error_errno(SYNTHETIC_ERRNO(EREMCHG), "Embedded home record not compatible with host record, refusing.");
|
||||||
|
|
||||||
/* Insist that credentials the user supplies also unlocks any embedded records. */
|
/* Insist that credentials the user supplies also unlocks any embedded records. */
|
||||||
r = user_record_authenticate(embedded_home, h, pkcs11_decrypted_passwords);
|
r = user_record_authenticate(embedded_home, h, pkcs11_decrypted_passwords, /* strict_verify= */ true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
assert(r > 0); /* Insist that a password was verified */
|
||||||
|
|
||||||
/* At this point we have three records to deal with:
|
/* At this point we have three records to deal with:
|
||||||
*
|
*
|
||||||
|
@ -615,7 +628,7 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) {
|
||||||
if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
|
if (!IN_SET(user_record_storage(h), USER_LUKS, USER_DIRECTORY, USER_SUBVOLUME, USER_FSCRYPT, USER_CIFS))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Activating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
|
return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), "Activating home directories of type '%s' currently not supported.", user_storage_to_string(user_record_storage(h)));
|
||||||
|
|
||||||
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
|
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -1177,9 +1190,10 @@ static int home_update(UserRecord *h, UserRecord **ret) {
|
||||||
assert(h);
|
assert(h);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
|
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
assert(r > 0); /* Insist that a password was verified */
|
||||||
|
|
||||||
r = home_validate_update(h, &setup);
|
r = home_validate_update(h, &setup);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -1233,9 +1247,10 @@ static int home_resize(UserRecord *h, UserRecord **ret) {
|
||||||
if (h->disk_size == UINT64_MAX)
|
if (h->disk_size == UINT64_MAX)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No target size specified, refusing.");
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No target size specified, refusing.");
|
||||||
|
|
||||||
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
|
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
assert(r > 0); /* Insist that a password was verified */
|
||||||
|
|
||||||
r = home_validate_update(h, &setup);
|
r = home_validate_update(h, &setup);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -1343,7 +1358,7 @@ static int home_inspect(UserRecord *h, UserRecord **ret_home) {
|
||||||
assert(h);
|
assert(h);
|
||||||
assert(ret_home);
|
assert(ret_home);
|
||||||
|
|
||||||
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
|
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -1413,7 +1428,7 @@ static int home_unlock(UserRecord *h) {
|
||||||
/* Note that we don't check if $HOME is actually mounted, since we want to avoid disk accesses on
|
/* Note that we don't check if $HOME is actually mounted, since we want to avoid disk accesses on
|
||||||
* that mount until we have resumed the device. */
|
* that mount until we have resumed the device. */
|
||||||
|
|
||||||
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords);
|
r = user_record_authenticate(h, h, &pkcs11_decrypted_passwords, /* strict_verify= */ false);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -1489,6 +1504,7 @@ static int run(int argc, char *argv[]) {
|
||||||
* EBUSY → file system is currently active
|
* EBUSY → file system is currently active
|
||||||
* ENOEXEC → file system is currently not active
|
* ENOEXEC → file system is currently not active
|
||||||
* ENOSPC → not enough disk space for operation
|
* ENOSPC → not enough disk space for operation
|
||||||
|
* EKEYREVOKED → user record has not suitable hashed password or pkcs#11 entry, we cannot authenticate
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (streq(argv[1], "activate"))
|
if (streq(argv[1], "activate"))
|
||||||
|
|
|
@ -56,6 +56,6 @@ int home_load_embedded_identity(UserRecord *h, int root_fd, UserRecord *header_h
|
||||||
int home_store_embedded_identity(UserRecord *h, int root_fd, uid_t uid, UserRecord *old_home);
|
int home_store_embedded_identity(UserRecord *h, int root_fd, uid_t uid, UserRecord *old_home);
|
||||||
int home_extend_embedded_identity(UserRecord *h, UserRecord *used, HomeSetup *setup);
|
int home_extend_embedded_identity(UserRecord *h, UserRecord *used, HomeSetup *setup);
|
||||||
|
|
||||||
int user_record_authenticate(UserRecord *h, UserRecord *secret, char ***pkcs11_decrypted_passwords);
|
int user_record_authenticate(UserRecord *h, UserRecord *secret, char ***pkcs11_decrypted_passwords, bool strict_verify);
|
||||||
|
|
||||||
int home_sync_and_statfs(int root_fd, struct statfs *ret);
|
int home_sync_and_statfs(int root_fd, struct statfs *ret);
|
||||||
|
|
|
@ -134,6 +134,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_NOT_LOCKED, ENOEXEC),
|
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_NOT_LOCKED, ENOEXEC),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_TOO_MANY_OPERATIONS, ENOBUFS),
|
SD_BUS_ERROR_MAP(BUS_ERROR_TOO_MANY_OPERATIONS, ENOBUFS),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_AUTHENTICATION_LIMIT_HIT, ETOOMANYREFS),
|
SD_BUS_ERROR_MAP(BUS_ERROR_AUTHENTICATION_LIMIT_HIT, ETOOMANYREFS),
|
||||||
|
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_CANT_AUTHENTICATE, EKEYREVOKED),
|
||||||
|
|
||||||
SD_BUS_ERROR_MAP_END
|
SD_BUS_ERROR_MAP_END
|
||||||
};
|
};
|
||||||
|
|
|
@ -115,5 +115,6 @@
|
||||||
#define BUS_ERROR_NO_DISK_SPACE "org.freedesktop.home1.NoDiskSpace"
|
#define BUS_ERROR_NO_DISK_SPACE "org.freedesktop.home1.NoDiskSpace"
|
||||||
#define BUS_ERROR_TOO_MANY_OPERATIONS "org.freedesktop.home1.TooManyOperations"
|
#define BUS_ERROR_TOO_MANY_OPERATIONS "org.freedesktop.home1.TooManyOperations"
|
||||||
#define BUS_ERROR_AUTHENTICATION_LIMIT_HIT "org.freedesktop.home1.AuthenticationLimitHit"
|
#define BUS_ERROR_AUTHENTICATION_LIMIT_HIT "org.freedesktop.home1.AuthenticationLimitHit"
|
||||||
|
#define BUS_ERROR_HOME_CANT_AUTHENTICATE "org.freedesktop.home1.HomeCantAuthenticate"
|
||||||
|
|
||||||
BUS_ERROR_MAP_ELF_USE(bus_common_errors);
|
BUS_ERROR_MAP_ELF_USE(bus_common_errors);
|
||||||
|
|
|
@ -1591,6 +1591,12 @@ int bus_add_implementation(sd_bus *bus, const BusObjectImplementation *impl, voi
|
||||||
impl->path);
|
impl->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (impl->manager) {
|
||||||
|
r = sd_bus_add_object_manager(bus, NULL, impl->path);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to add object manager for %s: %m", impl->path);
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; impl->children && impl->children[i]; i++) {
|
for (size_t i = 0; impl->children && impl->children[i]; i++) {
|
||||||
r = bus_add_implementation(bus, impl->children[i], userdata);
|
r = bus_add_implementation(bus, impl->children[i], userdata);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
Loading…
Reference in New Issue