static bool arg_pretty = false;
static bool arg_quiet = false;
static bool arg_varlink = false;
+static uid_t arg_uid = UID_INVALID;
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep);
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep);
timestamp,
arg_tpm2_device,
arg_tpm2_signature,
- getuid(),
+ uid_is_valid(arg_uid) ? arg_uid : getuid(),
&IOVEC_MAKE(data, size),
CREDENTIAL_ANY_SCOPE,
&plaintext);
arg_tpm2_pcr_mask,
arg_tpm2_public_key,
arg_tpm2_public_key_pcr_mask,
- /* uid= */ UID_INVALID,
+ arg_uid,
&plaintext,
/* flags= */ 0,
&output);
timestamp,
arg_tpm2_device,
arg_tpm2_signature,
- /* uid= */ UID_INVALID,
+ arg_uid,
&input,
/* flags= */ 0,
&plaintext);
" Specify TPM2 PCRs to seal against (public key)\n"
" --tpm2-signature=PATH\n"
" Specify signature for public key PCR policy\n"
+ " --user Select user-scoped credential encryption\n"
+ " --uid=UID Select user for scoped credentials\n"
" -q --quiet Suppress output for 'has-tpm2' verb\n"
"\nSee the %2$s for details.\n"
, program_invocation_short_name
ARG_NAME,
ARG_TIMESTAMP,
ARG_NOT_AFTER,
+ ARG_USER,
+ ARG_UID,
};
static const struct option options[] = {
{ "timestamp", required_argument, NULL, ARG_TIMESTAMP },
{ "not-after", required_argument, NULL, ARG_NOT_AFTER },
{ "quiet", no_argument, NULL, 'q' },
+ { "user", no_argument, NULL, ARG_USER },
+ { "uid", required_argument, NULL, ARG_UID },
{}
};
break;
+ case ARG_USER:
+ if (!uid_is_valid(arg_uid))
+ arg_uid = getuid();
+
+ break;
+
+ case ARG_UID:
+ if (isempty(optarg))
+ arg_uid = UID_INVALID;
+ else if (streq(optarg, "self"))
+ arg_uid = getuid();
+ else {
+ const char *name = optarg;
+
+ r = get_user_creds(
+ &name,
+ &arg_uid,
+ /* ret_gid= */ NULL,
+ /* ret_home= */ NULL,
+ /* ret_shell= */ NULL,
+ /* flags= */ 0);
+ if (r < 0)
+ return log_error_errno(r, "Failed to resolve user '%s': %m", optarg);
+ }
+ break;
+
case 'q':
arg_quiet = true;
break;
}
}
+ if (uid_is_valid(arg_uid)) {
+ /* If a UID is specified, then switch to scoped credentials */
+
+ if (sd_id128_equal(arg_with_key, _CRED_AUTO))
+ arg_with_key = _CRED_AUTO_SCOPED;
+ else if (sd_id128_in_set(arg_with_key, CRED_AES256_GCM_BY_HOST, CRED_AES256_GCM_BY_HOST_SCOPED))
+ arg_with_key = CRED_AES256_GCM_BY_HOST_SCOPED;
+ else if (sd_id128_in_set(arg_with_key, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED))
+ arg_with_key = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_SCOPED;
+ else if (sd_id128_in_set(arg_with_key, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK, CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED))
+ arg_with_key = CRED_AES256_GCM_BY_HOST_AND_TPM2_HMAC_WITH_PK_SCOPED;
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Selected key not available in --uid= scoped mode, refusing.");
+ }
+
if (arg_tpm2_pcr_mask == UINT32_MAX)
arg_tpm2_pcr_mask = TPM2_PCR_MASK_DEFAULT;
if (arg_tpm2_public_key_pcr_mask == UINT32_MAX)
arg_tpm2_pcr_mask,
arg_tpm2_public_key,
arg_tpm2_public_key_pcr_mask,
- /* uid= */ UID_INVALID,
+ arg_uid,
p.text ? &IOVEC_MAKE_STRING(p.text) : &p.data,
/* flags= */ 0,
&output);
p.timestamp,
arg_tpm2_device,
arg_tpm2_signature,
- /* uid= */ UID_INVALID,
+ arg_uid,
&p.blob,
/* flags= */ 0,
&output);