Skip to content

Commit 2c3cbc5

Browse files
committed
creds-util: add IPC client wrapper for new varlink apis
1 parent 8464f7c commit 2c3cbc5

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

src/shared/creds-util.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "stat-util.h"
3131
#include "tpm2-util.h"
3232
#include "user-util.h"
33+
#include "varlink.h"
3334

3435
#define PUBLIC_KEY_MAX (UINT32_C(1024) * UINT32_C(1024))
3536

@@ -1534,3 +1535,130 @@ int decrypt_credential_and_warn(const char *validate_name, usec_t validate_times
15341535
}
15351536

15361537
#endif
1538+
1539+
int ipc_encrypt_credential(const char *name, usec_t timestamp, usec_t not_after, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret) {
1540+
_cleanup_(varlink_unrefp) Varlink *vl = NULL;
1541+
int r;
1542+
1543+
assert(input && iovec_is_valid(input));
1544+
assert(ret);
1545+
1546+
r = varlink_connect_address(&vl, "/run/systemd/io.systemd.Credentials");
1547+
if (r < 0)
1548+
return log_error_errno(r, "Failed to connect to io.systemd.Credentials: %m");
1549+
1550+
/* Mark anything we get from the service as sensitive, given that it might use a NULL cypher, at least in theory */
1551+
r = varlink_set_input_sensitive(vl);
1552+
if (r < 0)
1553+
return log_error_errno(r, "Failed to enable sensitive Varlink input: %m");
1554+
1555+
/* Create the input data blob object separately, so that we can mark it as sensitive */
1556+
_cleanup_(json_variant_unrefp) JsonVariant *jinput = NULL;
1557+
r = json_build(&jinput, JSON_BUILD_IOVEC_BASE64(input));
1558+
if (r < 0)
1559+
return log_error_errno(r, "Failed to create input object: %m");
1560+
1561+
json_variant_sensitive(jinput);
1562+
1563+
_cleanup_(json_variant_unrefp) JsonVariant *reply = NULL;
1564+
const char *error_id = NULL;
1565+
r = varlink_callb(vl,
1566+
"io.systemd.Credentials.Encrypt",
1567+
&reply,
1568+
&error_id,
1569+
JSON_BUILD_OBJECT(
1570+
JSON_BUILD_PAIR_CONDITION(name, "name", JSON_BUILD_STRING(name)),
1571+
JSON_BUILD_PAIR("data", JSON_BUILD_VARIANT(jinput)),
1572+
JSON_BUILD_PAIR_CONDITION(timestamp != USEC_INFINITY, "timestamp", JSON_BUILD_UNSIGNED(timestamp)),
1573+
JSON_BUILD_PAIR_CONDITION(not_after != USEC_INFINITY, "notAfter", JSON_BUILD_UNSIGNED(not_after)),
1574+
JSON_BUILD_PAIR_CONDITION(!FLAGS_SET(flags, CREDENTIAL_ANY_SCOPE), "scope", JSON_BUILD_STRING(uid_is_valid(uid) ? "user" : "system")),
1575+
JSON_BUILD_PAIR_CONDITION(uid_is_valid(uid), "uid", JSON_BUILD_UNSIGNED(uid))));
1576+
if (r < 0)
1577+
return log_error_errno(r, "Failed to call Encrypt() varlink call.");
1578+
if (!isempty(error_id)) {
1579+
if (streq(error_id, "io.systemd.Credentials.NoSuchUser"))
1580+
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "No such user.");
1581+
1582+
return log_error_errno(varlink_error_to_errno(error_id, reply), "Failed to encrypt: %s", error_id);
1583+
}
1584+
1585+
r = json_dispatch(
1586+
reply,
1587+
(const JsonDispatch[]) {
1588+
{ "blob", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, PTR_TO_SIZE(ret), JSON_MANDATORY },
1589+
{},
1590+
},
1591+
JSON_LOG|JSON_ALLOW_EXTENSIONS,
1592+
/* userdata= */ NULL);
1593+
if (r < 0)
1594+
return r;
1595+
1596+
return 0;
1597+
}
1598+
1599+
int ipc_decrypt_credential(const char *validate_name, usec_t validate_timestamp, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret) {
1600+
_cleanup_(varlink_unrefp) Varlink *vl = NULL;
1601+
int r;
1602+
1603+
assert(input && iovec_is_valid(input));
1604+
assert(ret);
1605+
1606+
r = varlink_connect_address(&vl, "/run/systemd/io.systemd.Credentials");
1607+
if (r < 0)
1608+
return log_error_errno(r, "Failed to connect to io.systemd.Credentials: %m");
1609+
1610+
r = varlink_set_input_sensitive(vl);
1611+
if (r < 0)
1612+
return log_error_errno(r, "Failed to enable sensitive Varlink input: %m");
1613+
1614+
/* Create the input data blob object separately, so that we can mark it as sensitive (it's supposed
1615+
* to be encrypted, but who knows maybe it uses the NULL cypher). */
1616+
_cleanup_(json_variant_unrefp) JsonVariant *jinput = NULL;
1617+
r = json_build(&jinput, JSON_BUILD_IOVEC_BASE64(input));
1618+
if (r < 0)
1619+
return log_error_errno(r, "Failed to create input object: %m");
1620+
1621+
json_variant_sensitive(jinput);
1622+
1623+
_cleanup_(json_variant_unrefp) JsonVariant *reply = NULL;
1624+
const char *error_id = NULL;
1625+
r = varlink_callb(vl,
1626+
"io.systemd.Credentials.Decrypt",
1627+
&reply,
1628+
&error_id,
1629+
JSON_BUILD_OBJECT(
1630+
JSON_BUILD_PAIR_CONDITION(validate_name, "name", JSON_BUILD_STRING(validate_name)),
1631+
JSON_BUILD_PAIR("blob", JSON_BUILD_VARIANT(jinput)),
1632+
JSON_BUILD_PAIR_CONDITION(validate_timestamp != USEC_INFINITY, "timestamp", JSON_BUILD_UNSIGNED(validate_timestamp)),
1633+
JSON_BUILD_PAIR_CONDITION(!FLAGS_SET(flags, CREDENTIAL_ANY_SCOPE), "scope", JSON_BUILD_STRING(uid_is_valid(uid) ? "user" : "system")),
1634+
JSON_BUILD_PAIR_CONDITION(uid_is_valid(uid), "uid", JSON_BUILD_UNSIGNED(uid))));
1635+
if (r < 0)
1636+
return log_error_errno(r, "Failed to call Decrypt() varlink call.");
1637+
if (!isempty(error_id)) {
1638+
if (streq(error_id, "io.systemd.Credentials.BadFormat"))
1639+
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Bad credential format.");
1640+
if (streq(error_id, "io.systemd.Credentials.NameMismatch"))
1641+
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "Name in credential doesn't match expectations.");
1642+
if (streq(error_id, "io.systemd.Credentials.TimeMismatch"))
1643+
return log_error_errno(SYNTHETIC_ERRNO(ESTALE), "Outside of credential validity time window.");
1644+
if (streq(error_id, "io.systemd.Credentials.NoSuchUser"))
1645+
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "No such user.");
1646+
if (streq(error_id, "io.systemd.Credentials.BadScope"))
1647+
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Scope mismtach.");
1648+
1649+
return log_error_errno(varlink_error_to_errno(error_id, reply), "Failed to decrypt: %s", error_id);
1650+
}
1651+
1652+
r = json_dispatch(
1653+
reply,
1654+
(const JsonDispatch[]) {
1655+
{ "data", JSON_VARIANT_STRING, json_dispatch_unbase64_iovec, PTR_TO_SIZE(ret), JSON_MANDATORY },
1656+
{},
1657+
},
1658+
JSON_LOG|JSON_ALLOW_EXTENSIONS,
1659+
/* userdata= */ NULL);
1660+
if (r < 0)
1661+
return r;
1662+
1663+
return 0;
1664+
}

src/shared/creds-util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,6 @@ typedef enum CredentialFlags {
9090

9191
int encrypt_credential_and_warn(sd_id128_t with_key, const char *name, usec_t timestamp, usec_t not_after, const char *tpm2_device, uint32_t tpm2_hash_pcr_mask, const char *tpm2_pubkey_path, uint32_t tpm2_pubkey_pcr_mask, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret);
9292
int decrypt_credential_and_warn(const char *validate_name, usec_t validate_timestamp, const char *tpm2_device, const char *tpm2_signature_path, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret);
93+
94+
int ipc_encrypt_credential(const char *name, usec_t timestamp, usec_t not_after, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret);
95+
int ipc_decrypt_credential(const char *validate_name, usec_t validate_timestamp, uid_t uid, const struct iovec *input, CredentialFlags flags, struct iovec *ret);

0 commit comments

Comments
 (0)