summaryrefslogtreecommitdiffstats
path: root/src/util/authtok.c
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2016-09-23 17:11:35 +0200
committerJakub Hrozek <jhrozek@redhat.com>2017-02-23 10:15:04 +0100
commitdd17a3aaddab6f122dff3bd15b7005464c07c0ea (patch)
tree2789a97339b086c74c0b01610cca3f7b7a374b7b /src/util/authtok.c
parentf70d946f8cde55b6bdc09345e22849842bca4387 (diff)
downloadsssd-dd17a3aaddab6f122dff3bd15b7005464c07c0ea.tar.gz
sssd-dd17a3aaddab6f122dff3bd15b7005464c07c0ea.tar.xz
sssd-dd17a3aaddab6f122dff3bd15b7005464c07c0ea.zip
authtok: enhance support for Smartcard auth blobs
The blobs contains beside the PIN the name of the PKCS#11 module and the token name where the certificate of the user was found and the key id. Those data will be used e.g. by the pkinit module to make sure them right certificate is used. Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src/util/authtok.c')
-rw-r--r--src/util/authtok.c320
1 files changed, 309 insertions, 11 deletions
diff --git a/src/util/authtok.c b/src/util/authtok.c
index 6062cd875..c2f78be32 100644
--- a/src/util/authtok.c
+++ b/src/util/authtok.c
@@ -196,10 +196,9 @@ errno_t sss_authtok_set(struct sss_auth_token *tok,
case SSS_AUTHTOK_TYPE_2FA:
return sss_authtok_set_2fa_from_blob(tok, data, len);
case SSS_AUTHTOK_TYPE_SC_PIN:
- return sss_authtok_set_sc_pin(tok, (const char*)data, len);
+ return sss_authtok_set_sc_from_blob(tok, data, len);
case SSS_AUTHTOK_TYPE_SC_KEYPAD:
- sss_authtok_set_sc_keypad(tok);
- return EOK;
+ return sss_authtok_set_sc_from_blob(tok, data, len);
case SSS_AUTHTOK_TYPE_EMPTY:
sss_authtok_set_empty(tok);
return EOK;
@@ -425,6 +424,104 @@ errno_t sss_authtok_set_2fa(struct sss_auth_token *tok,
return EOK;
}
+errno_t sss_authtok_set_sc(struct sss_auth_token *tok,
+ enum sss_authtok_type type,
+ const char *pin, size_t pin_len,
+ const char *token_name, size_t token_name_len,
+ const char *module_name, size_t module_name_len,
+ const char *key_id, size_t key_id_len)
+{
+ int ret;
+ size_t needed_size;
+
+ if (type != SSS_AUTHTOK_TYPE_SC_PIN
+ && type != SSS_AUTHTOK_TYPE_SC_KEYPAD) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid type [%d].\n", type);
+ return EINVAL;
+ }
+
+ sss_authtok_set_empty(tok);
+
+ ret = sss_auth_pack_sc_blob(pin, pin_len, token_name, token_name_len,
+ module_name, module_name_len,
+ key_id, key_id_len, NULL, 0,
+ &needed_size);
+ if (ret != EAGAIN) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_auth_pack_sc_blob failed.\n");
+ return ret;
+ }
+
+ tok->data = talloc_size(tok, needed_size);
+ if (tok->data == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
+ return ENOMEM;
+ }
+
+ ret = sss_auth_pack_sc_blob(pin, pin_len, token_name, token_name_len,
+ module_name, module_name_len,
+ key_id, key_id_len, tok->data,
+ needed_size, &needed_size);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_auth_pack_sc_blob failed.\n");
+ talloc_free(tok->data);
+ return ret;
+ }
+
+ tok->length = needed_size;
+ tok->type = type;
+
+ return EOK;
+}
+
+errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok,
+ const uint8_t *data,
+ size_t len)
+{
+ int ret;
+ char *pin = NULL;
+ size_t pin_len;
+ char *token_name = NULL;
+ size_t token_name_len;
+ char *module_name = NULL;
+ size_t module_name_len;
+ char *key_id = NULL;
+ size_t key_id_len;
+ TALLOC_CTX *tmp_ctx;
+
+ if (tok == NULL) {
+ return EFAULT;
+ }
+ if (data == NULL || len == 0) {
+ return EINVAL;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_auth_unpack_sc_blob(tmp_ctx, data, len, &pin, &pin_len,
+ &token_name, &token_name_len,
+ &module_name, &module_name_len,
+ &key_id, &key_id_len);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_auth_unpack_sc_blob failed.\n");
+ goto done;
+ }
+
+ ret = sss_authtok_set_sc(tok, SSS_AUTHTOK_TYPE_SC_PIN, pin, pin_len,
+ token_name, token_name_len,
+ module_name, module_name_len,
+ key_id, key_id_len);
+
+done:
+ talloc_free(tmp_ctx);
+
+ return ret;
+}
+
errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin,
size_t len)
{
@@ -435,15 +532,17 @@ errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin,
return EINVAL;
}
- sss_authtok_set_empty(tok);
-
- return sss_authtok_set_string(tok, SSS_AUTHTOK_TYPE_SC_PIN,
- "sc_pin", pin, len);
+ return sss_authtok_set_sc(tok, SSS_AUTHTOK_TYPE_SC_PIN, pin, len,
+ NULL, 0, NULL, 0, NULL, 0);
}
-errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin,
+errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **_pin,
size_t *len)
{
+ int ret;
+ const char *pin = NULL;
+ size_t pin_len;
+
if (!tok) {
return EFAULT;
}
@@ -451,9 +550,16 @@ errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin,
case SSS_AUTHTOK_TYPE_EMPTY:
return ENOENT;
case SSS_AUTHTOK_TYPE_SC_PIN:
- *pin = (const char *)tok->data;
+ ret = sss_authtok_get_sc(tok, &pin, &pin_len,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n");
+ return ret;
+ }
+
+ *_pin = pin;
if (len) {
- *len = tok->length - 1;
+ *len = pin_len;
}
return EOK;
case SSS_AUTHTOK_TYPE_PASSWORD:
@@ -468,10 +574,202 @@ errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin,
void sss_authtok_set_sc_keypad(struct sss_auth_token *tok)
{
- if (!tok) {
+ if (tok == NULL) {
return;
}
+
sss_authtok_set_empty(tok);
tok->type = SSS_AUTHTOK_TYPE_SC_KEYPAD;
}
+
+errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx,
+ const uint8_t *blob, size_t blob_len,
+ char **pin, size_t *_pin_len,
+ char **token_name, size_t *_token_name_len,
+ char **module_name, size_t *_module_name_len,
+ char **key_id, size_t *_key_id_len)
+{
+ size_t c;
+ uint32_t pin_len;
+ uint32_t token_name_len;
+ uint32_t module_name_len;
+ uint32_t key_id_len;
+
+ c = 0;
+
+ if (blob == NULL || blob_len == 0) {
+ pin_len = 0;
+ token_name_len = 0;
+ module_name_len = 0;
+ key_id_len = 0;
+ } else if (blob_len > 0
+ && strnlen((const char *) blob, blob_len) == blob_len - 1) {
+ pin_len = blob_len;
+ token_name_len = 0;
+ module_name_len = 0;
+ key_id_len = 0;
+ } else {
+ if (blob_len < 4 * sizeof(uint32_t)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n");
+ return EINVAL;
+ }
+
+ SAFEALIGN_COPY_UINT32(&pin_len, blob, &c);
+ SAFEALIGN_COPY_UINT32(&token_name_len, blob + c, &c);
+ SAFEALIGN_COPY_UINT32(&module_name_len, blob + c, &c);
+ SAFEALIGN_COPY_UINT32(&key_id_len, blob + c, &c);
+
+ if (blob_len != 4 * sizeof(uint32_t) + pin_len + token_name_len
+ + module_name_len + key_id_len) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n");
+ return EINVAL;
+ }
+ }
+
+ if (pin_len != 0) {
+ *pin = talloc_strndup(mem_ctx, (const char *) blob + c, pin_len);
+ if (*pin == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
+ return ENOMEM;
+ }
+ } else {
+ *pin = NULL;
+ }
+
+ if (token_name_len != 0) {
+ *token_name = talloc_strndup(mem_ctx, (const char *) blob + c + pin_len,
+ token_name_len);
+ if (*token_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
+ talloc_free(*pin);
+ return ENOMEM;
+ }
+ } else {
+ *token_name = NULL;
+ }
+
+ if (module_name_len != 0) {
+ *module_name = talloc_strndup(mem_ctx,
+ (const char *) blob + c + pin_len
+ + token_name_len,
+ module_name_len);
+ if (*module_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
+ talloc_free(*pin);
+ talloc_free(*token_name);
+ return ENOMEM;
+ }
+ } else {
+ *module_name = NULL;
+ }
+
+ if (key_id_len != 0) {
+ *key_id = talloc_strndup(mem_ctx,
+ (const char *) blob + c + pin_len
+ + token_name_len
+ + module_name_len,
+ key_id_len);
+ if (*key_id == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
+ talloc_free(*pin);
+ talloc_free(*token_name);
+ talloc_free(*module_name);
+ return ENOMEM;
+ }
+ } else {
+ *key_id = NULL;
+ }
+
+ /* Re-calculate length for the case where \0 was missing in the blob */
+ if (_pin_len != NULL) {
+ *_pin_len = (*pin == NULL) ? 0 : strlen(*pin);
+ }
+ if (_token_name_len != NULL) {
+ *_token_name_len = (*token_name == NULL) ? 0 : strlen(*token_name);
+ }
+ if (_module_name_len != NULL) {
+ *_module_name_len = (*module_name == NULL) ? 0 : strlen(*module_name);
+ }
+
+ if (_key_id_len != NULL) {
+ *_key_id_len = (*key_id == NULL) ? 0 : strlen(*key_id);
+ }
+
+ return EOK;
+}
+
+errno_t sss_authtok_get_sc(struct sss_auth_token *tok,
+ const char **_pin, size_t *_pin_len,
+ const char **_token_name, size_t *_token_name_len,
+ const char **_module_name, size_t *_module_name_len,
+ const char **_key_id, size_t *_key_id_len)
+{
+ size_t c = 0;
+ size_t pin_len;
+ size_t token_name_len;
+ size_t module_name_len;
+ size_t key_id_len;
+ uint32_t tmp_uint32_t;
+
+ if (!tok) {
+ return EFAULT;
+ }
+
+ if (tok->type != SSS_AUTHTOK_TYPE_SC_PIN
+ && tok->type != SSS_AUTHTOK_TYPE_SC_KEYPAD) {
+ return (tok->type == SSS_AUTHTOK_TYPE_EMPTY) ? ENOENT : EACCES;
+ }
+
+ if (tok->length < 4 * sizeof(uint32_t)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n");
+ return EINVAL;
+ }
+
+ SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data, &c);
+ pin_len = tmp_uint32_t - 1;
+ SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c);
+ token_name_len = tmp_uint32_t - 1;
+ SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c);
+ module_name_len = tmp_uint32_t -1;
+ SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c);
+ key_id_len = tmp_uint32_t -1;
+
+ if (tok->length != 4 * sizeof(uint32_t) + 4 + pin_len + token_name_len
+ + module_name_len + key_id_len) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n");
+ return EINVAL;
+ }
+
+ if (_pin != NULL) {
+ *_pin = (const char *) tok->data + c;
+ }
+ if (_pin_len != NULL) {
+ *_pin_len = pin_len;
+ }
+
+ if (_token_name != NULL) {
+ *_token_name = (const char *) tok->data + c + pin_len + 1;
+ }
+ if (_token_name_len != NULL) {
+ *_token_name_len = token_name_len;
+ }
+
+ if (_module_name != NULL) {
+ *_module_name = (const char *) tok->data + c + pin_len + 1
+ + token_name_len + 1;
+ }
+ if (_module_name_len != NULL) {
+ *_module_name_len = module_name_len;
+ }
+
+ if (_key_id != NULL) {
+ *_key_id = (const char *) tok->data + c + pin_len + 1
+ + token_name_len + 1 + module_name_len + 1;
+ }
+ if (_key_id_len != NULL) {
+ *_key_id_len = key_id_len;
+ }
+
+ return EOK;
+}