From 1d44738a7d07247eb99e5493c7d4578b9fbf2904 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Thu, 15 Oct 2015 22:26:15 +0200 Subject: [PATCH 01/11] PAM: Move PAM packet parsing functionality to a separate module For easier mocking of this interface in pam_sss tests that need to parse the packets coming from pam_sss. --- Makefile.am | 2 + src/responder/pam/pamsrv.h | 3 + src/responder/pam/pamsrv_cmd.c | 341 -------------------------------- src/responder/pam/pamsrv_extract.c | 391 +++++++++++++++++++++++++++++++++++++ 4 files changed, 396 insertions(+), 341 deletions(-) create mode 100644 src/responder/pam/pamsrv_extract.c diff --git a/Makefile.am b/Makefile.am index 9144274c787a9a1fd8bef72e7ac6e68a1a28a0e3..e6bb69f3a30fda3e47d5eb8493763e8e3d6dbb67 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1131,6 +1131,7 @@ sssd_pam_SOURCES = \ src/responder/pam/pam_LOCAL_domain.c \ src/responder/pam/pamsrv.c \ src/responder/pam/pamsrv_cmd.c \ + src/responder/pam/pamsrv_extract.c \ src/responder/pam/pamsrv_p11.c \ src/responder/pam/pamsrv_dp.c \ src/responder/pam/pam_helpers.c \ @@ -1937,6 +1938,7 @@ pam_srv_tests_SOURCES = \ src/tests/cmocka/test_pam_srv.c \ src/sss_client/pam_message.c \ src/responder/pam/pamsrv_cmd.c \ + src/responder/pam/pamsrv_extract.c \ src/responder/pam/pamsrv_p11.c \ src/responder/pam/pam_helpers.c \ src/responder/pam/pamsrv_dp.c \ diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h index b44e1c3378817aa169fa1fe8995bdb223f593cb0..324291ab38c82cca8845e8eeab37b4146bb8bf40 100644 --- a/src/responder/pam/pamsrv.h +++ b/src/responder/pam/pamsrv.h @@ -101,4 +101,7 @@ errno_t pam_set_last_online_auth_with_curr_token(struct sss_domain_info *domain, const char *username, uint64_t value); + +errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd); + #endif /* __PAMSRV_H__ */ diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index d86807e79f98b04d9ab14505ad8b2e92677bd292..a6d7c12fa001c38c7e6ee8be4ab7ed57d2274161 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -123,87 +123,6 @@ static bool is_domain_requested(struct pam_data *pd, const char *domain_name) return false; } -static int extract_authtok_v2(struct sss_auth_token *tok, - size_t data_size, uint8_t *body, size_t blen, - size_t *c) -{ - uint32_t auth_token_type; - uint32_t auth_token_length; - uint8_t *auth_token_data; - int ret = EOK; - - if (data_size < sizeof(uint32_t) || *c+data_size > blen || - SIZE_T_OVERFLOW(*c, data_size)) return EINVAL; - - SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c); - auth_token_length = data_size - sizeof(uint32_t); - auth_token_data = body+(*c); - - switch (auth_token_type) { - case SSS_AUTHTOK_TYPE_EMPTY: - sss_authtok_set_empty(tok); - break; - case SSS_AUTHTOK_TYPE_PASSWORD: - if (auth_token_length == 0) { - sss_authtok_set_empty(tok); - } else { - ret = sss_authtok_set_password(tok, (const char *)auth_token_data, - auth_token_length); - } - break; - case SSS_AUTHTOK_TYPE_2FA: - ret = sss_authtok_set(tok, SSS_AUTHTOK_TYPE_2FA, - auth_token_data, auth_token_length); - break; - case SSS_AUTHTOK_TYPE_SC_PIN: - ret = sss_authtok_set_sc_pin(tok, (const char *) auth_token_data, - auth_token_length); - break; - case SSS_AUTHTOK_TYPE_SC_KEYPAD: - sss_authtok_set_sc_keypad(tok); - break; - default: - return EINVAL; - } - - *c += auth_token_length; - - return ret; -} - -static int extract_string(char **var, size_t size, uint8_t *body, size_t blen, - size_t *c) { - uint8_t *str; - - if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL; - - str = body+(*c); - - if (str[size-1]!='\0') return EINVAL; - - /* If the string isn't valid UTF-8, fail */ - if (!sss_utf8_check(str, size-1)) { - return EINVAL; - } - - *c += size; - - *var = (char *) str; - - return EOK; -} - -static int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body, - size_t blen, size_t *c) { - - if (size != sizeof(uint32_t) || *c+size > blen || SIZE_T_OVERFLOW(*c, size)) - return EINVAL; - - SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c); - - return EOK; -} - static int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd) { const char *name; @@ -224,204 +143,6 @@ static int pd_set_primary_name(const struct ldb_message *msg,struct pam_data *pd return EOK; } -static int pam_parse_in_data_v2(struct pam_data *pd, - uint8_t *body, size_t blen) -{ - size_t c; - uint32_t type; - uint32_t size; - int ret; - uint32_t start; - uint32_t terminator; - char *requested_domains; - - if (blen < 4*sizeof(uint32_t)+2) { - DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n"); - return EINVAL; - } - - SAFEALIGN_COPY_UINT32(&start, body, NULL); - SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL); - - if (start != SSS_START_OF_PAM_REQUEST - || terminator != SSS_END_OF_PAM_REQUEST) { - DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n"); - return EINVAL; - } - - c = sizeof(uint32_t); - do { - SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c); - - if (type == SSS_END_OF_PAM_REQUEST) { - if (c != blen) return EINVAL; - } else { - SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c); - /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to - * the remaining buffer */ - if (size > (blen - c - sizeof(uint32_t))) { - DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n"); - return EINVAL; - } - - switch(type) { - case SSS_PAM_ITEM_USER: - ret = extract_string(&pd->logon_name, size, body, blen, &c); - if (ret != EOK) return ret; - break; - case SSS_PAM_ITEM_SERVICE: - ret = extract_string(&pd->service, size, body, blen, &c); - if (ret != EOK) return ret; - break; - case SSS_PAM_ITEM_TTY: - ret = extract_string(&pd->tty, size, body, blen, &c); - if (ret != EOK) return ret; - break; - case SSS_PAM_ITEM_RUSER: - ret = extract_string(&pd->ruser, size, body, blen, &c); - if (ret != EOK) return ret; - break; - case SSS_PAM_ITEM_RHOST: - ret = extract_string(&pd->rhost, size, body, blen, &c); - if (ret != EOK) return ret; - break; - case SSS_PAM_ITEM_REQUESTED_DOMAINS: - ret = extract_string(&requested_domains, size, body, blen, - &c); - if (ret != EOK) return ret; - - ret = split_on_separator(pd, requested_domains, ',', true, - true, &pd->requested_domains, - NULL); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to parse requested_domains list!\n"); - return ret; - } - break; - case SSS_PAM_ITEM_CLI_PID: - ret = extract_uint32_t(&pd->cli_pid, size, - body, blen, &c); - if (ret != EOK) return ret; - break; - case SSS_PAM_ITEM_AUTHTOK: - ret = extract_authtok_v2(pd->authtok, - size, body, blen, &c); - if (ret != EOK) return ret; - break; - case SSS_PAM_ITEM_NEWAUTHTOK: - ret = extract_authtok_v2(pd->newauthtok, - size, body, blen, &c); - if (ret != EOK) return ret; - break; - default: - DEBUG(SSSDBG_CRIT_FAILURE, - "Ignoring unknown data type [%d].\n", type); - c += size; - } - } - - } while(c < blen); - - return EOK; - -} - -static int pam_parse_in_data_v3(struct pam_data *pd, - uint8_t *body, size_t blen) -{ - int ret; - - ret = pam_parse_in_data_v2(pd, body, blen); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "pam_parse_in_data_v2 failed.\n"); - return ret; - } - - if (pd->cli_pid == 0) { - DEBUG(SSSDBG_CRIT_FAILURE, "Missing client PID.\n"); - return EINVAL; - } - - return EOK; -} - -static int extract_authtok_v1(struct sss_auth_token *tok, - uint8_t *body, size_t blen, size_t *c) -{ - uint32_t auth_token_type; - uint32_t auth_token_length; - uint8_t *auth_token_data; - int ret = EOK; - - SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c); - SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, &body[*c], blen, c); - auth_token_data = body+(*c); - - switch (auth_token_type) { - case SSS_AUTHTOK_TYPE_EMPTY: - sss_authtok_set_empty(tok); - break; - case SSS_AUTHTOK_TYPE_PASSWORD: - ret = sss_authtok_set_password(tok, (const char *)auth_token_data, - auth_token_length); - break; - default: - return EINVAL; - } - - *c += auth_token_length; - - return ret; -} - -static int pam_parse_in_data(struct pam_data *pd, - uint8_t *body, size_t blen) -{ - size_t start; - size_t end; - size_t last; - int ret; - - last = blen - 1; - end = 0; - - /* user name */ - for (start = end; end < last; end++) if (body[end] == '\0') break; - if (body[end++] != '\0') return EINVAL; - pd->logon_name = (char *) &body[start]; - - for (start = end; end < last; end++) if (body[end] == '\0') break; - if (body[end++] != '\0') return EINVAL; - pd->service = (char *) &body[start]; - - for (start = end; end < last; end++) if (body[end] == '\0') break; - if (body[end++] != '\0') return EINVAL; - pd->tty = (char *) &body[start]; - - for (start = end; end < last; end++) if (body[end] == '\0') break; - if (body[end++] != '\0') return EINVAL; - pd->ruser = (char *) &body[start]; - - for (start = end; end < last; end++) if (body[end] == '\0') break; - if (body[end++] != '\0') return EINVAL; - pd->rhost = (char *) &body[start]; - - ret = extract_authtok_v1(pd->authtok, body, blen, &end); - if (ret) { - DEBUG(SSSDBG_CRIT_FAILURE, "Invalid auth token\n"); - return ret; - } - ret = extract_authtok_v1(pd->newauthtok, body, blen, &end); - if (ret) { - DEBUG(SSSDBG_CRIT_FAILURE, "Invalid new auth token\n"); - return ret; - } - - DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd); - - return EOK; -} /*=Save-Last-Login-State===================================================*/ @@ -926,68 +647,6 @@ static int pam_check_user_done(struct pam_auth_req *preq, int ret); * PAM_ENVIRONMENT, so that we can save performing some calls and cache * data. */ -static errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd) -{ - uint8_t *body; - size_t blen; - errno_t ret; - uint32_t terminator; - - sss_packet_get_body(cctx->creq->in, &body, &blen); - if (blen >= sizeof(uint32_t)) { - SAFEALIGN_COPY_UINT32(&terminator, - body + blen - sizeof(uint32_t), - NULL); - if (terminator != SSS_END_OF_PAM_REQUEST) { - DEBUG(SSSDBG_CRIT_FAILURE, "Received data not terminated.\n"); - ret = EINVAL; - goto done; - } - } - - switch (cctx->cli_protocol_version->version) { - case 1: - ret = pam_parse_in_data(pd, body, blen); - break; - case 2: - ret = pam_parse_in_data_v2(pd, body, blen); - break; - case 3: - ret = pam_parse_in_data_v3(pd, body, blen); - break; - default: - DEBUG(SSSDBG_CRIT_FAILURE, "Illegal protocol version [%d].\n", - cctx->cli_protocol_version->version); - ret = EINVAL; - } - if (ret != EOK) { - goto done; - } - - if (pd->logon_name != NULL) { - ret = sss_parse_name_for_domains(pd, cctx->rctx->domains, - cctx->rctx->default_domain, - pd->logon_name, - &pd->domain, &pd->user); - } else { - /* Only SSS_PAM_PREAUTH request may have a missing name, e.g. if the - * name is determined with the help of a certificate */ - if (pd->cmd == SSS_PAM_PREAUTH - && may_do_cert_auth(talloc_get_type(cctx->rctx->pvt_ctx, - struct pam_ctx), pd)) { - ret = EOK; - } else { - DEBUG(SSSDBG_CRIT_FAILURE, "Missing logon name in PAM request.\n"); - ret = ERR_NO_CREDS; - goto done; - } - } - - DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd); - -done: - return ret; -} static int pam_auth_req_destructor(struct pam_auth_req *preq) { diff --git a/src/responder/pam/pamsrv_extract.c b/src/responder/pam/pamsrv_extract.c new file mode 100644 index 0000000000000000000000000000000000000000..fc0b2896073e10e08f98eabd9bba4464a64b92d8 --- /dev/null +++ b/src/responder/pam/pamsrv_extract.c @@ -0,0 +1,391 @@ +/* + SSSD + + PAM Responder + + Copyright (C) Simo Sorce 2009 + Copyright (C) Sumit Bose 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "util/util.h" +#include "providers/data_provider.h" +#include "responder/pam/pamsrv.h" +#include "responder/common/responder_packet.h" + +static int pam_parse_in_data(struct pam_data *pd, + uint8_t *body, size_t blen); +static int pam_parse_in_data_v2(struct pam_data *pd, + uint8_t *body, size_t blen); +static int pam_parse_in_data_v3(struct pam_data *pd, + uint8_t *body, size_t blen); + +errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd) +{ + uint8_t *body; + size_t blen; + errno_t ret; + uint32_t terminator; + + sss_packet_get_body(cctx->creq->in, &body, &blen); + if (blen >= sizeof(uint32_t)) { + SAFEALIGN_COPY_UINT32(&terminator, + body + blen - sizeof(uint32_t), + NULL); + if (terminator != SSS_END_OF_PAM_REQUEST) { + DEBUG(SSSDBG_CRIT_FAILURE, "Received data not terminated.\n"); + ret = EINVAL; + goto done; + } + } + + switch (cctx->cli_protocol_version->version) { + case 1: + ret = pam_parse_in_data(pd, body, blen); + break; + case 2: + ret = pam_parse_in_data_v2(pd, body, blen); + break; + case 3: + ret = pam_parse_in_data_v3(pd, body, blen); + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Illegal protocol version [%d].\n", + cctx->cli_protocol_version->version); + ret = EINVAL; + } + if (ret != EOK) { + goto done; + } + + if (pd->logon_name != NULL) { + ret = sss_parse_name_for_domains(pd, cctx->rctx->domains, + cctx->rctx->default_domain, + pd->logon_name, + &pd->domain, &pd->user); + } else { + /* Only SSS_PAM_PREAUTH request may have a missing name, e.g. if the + * name is determined with the help of a certificate */ + if (pd->cmd == SSS_PAM_PREAUTH + && may_do_cert_auth(talloc_get_type(cctx->rctx->pvt_ctx, + struct pam_ctx), pd)) { + ret = EOK; + } else { + DEBUG(SSSDBG_CRIT_FAILURE, "Missing logon name in PAM request.\n"); + ret = ERR_NO_CREDS; + goto done; + } + } + + DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd); + +done: + return ret; +} + +static int extract_authtok_v1(struct sss_auth_token *tok, + uint8_t *body, size_t blen, size_t *c); +static int extract_authtok_v2(struct sss_auth_token *tok, + size_t data_size, uint8_t *body, size_t blen, + size_t *c); +static int extract_string(char **var, size_t size, uint8_t *body, size_t blen, + size_t *c); +static int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body, + size_t blen, size_t *c); + +static int pam_parse_in_data(struct pam_data *pd, + uint8_t *body, size_t blen) +{ + size_t start; + size_t end; + size_t last; + int ret; + + last = blen - 1; + end = 0; + + /* user name */ + for (start = end; end < last; end++) if (body[end] == '\0') break; + if (body[end++] != '\0') return EINVAL; + pd->logon_name = (char *) &body[start]; + + for (start = end; end < last; end++) if (body[end] == '\0') break; + if (body[end++] != '\0') return EINVAL; + pd->service = (char *) &body[start]; + + for (start = end; end < last; end++) if (body[end] == '\0') break; + if (body[end++] != '\0') return EINVAL; + pd->tty = (char *) &body[start]; + + for (start = end; end < last; end++) if (body[end] == '\0') break; + if (body[end++] != '\0') return EINVAL; + pd->ruser = (char *) &body[start]; + + for (start = end; end < last; end++) if (body[end] == '\0') break; + if (body[end++] != '\0') return EINVAL; + pd->rhost = (char *) &body[start]; + + ret = extract_authtok_v1(pd->authtok, body, blen, &end); + if (ret) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid auth token\n"); + return ret; + } + ret = extract_authtok_v1(pd->newauthtok, body, blen, &end); + if (ret) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid new auth token\n"); + return ret; + } + + DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd); + + return EOK; +} + +static int pam_parse_in_data_v2(struct pam_data *pd, + uint8_t *body, size_t blen) +{ + size_t c; + uint32_t type; + uint32_t size; + int ret; + uint32_t start; + uint32_t terminator; + char *requested_domains; + + if (blen < 4*sizeof(uint32_t)+2) { + DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n"); + return EINVAL; + } + + SAFEALIGN_COPY_UINT32(&start, body, NULL); + SAFEALIGN_COPY_UINT32(&terminator, body + blen - sizeof(uint32_t), NULL); + + if (start != SSS_START_OF_PAM_REQUEST + || terminator != SSS_END_OF_PAM_REQUEST) { + DEBUG(SSSDBG_CRIT_FAILURE, "Received data is invalid.\n"); + return EINVAL; + } + + c = sizeof(uint32_t); + do { + SAFEALIGN_COPY_UINT32_CHECK(&type, &body[c], blen, &c); + + if (type == SSS_END_OF_PAM_REQUEST) { + if (c != blen) return EINVAL; + } else { + SAFEALIGN_COPY_UINT32_CHECK(&size, &body[c], blen, &c); + /* the uint32_t end maker SSS_END_OF_PAM_REQUEST does not count to + * the remaining buffer */ + if (size > (blen - c - sizeof(uint32_t))) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid data size.\n"); + return EINVAL; + } + + switch(type) { + case SSS_PAM_ITEM_USER: + ret = extract_string(&pd->logon_name, size, body, blen, &c); + if (ret != EOK) return ret; + break; + case SSS_PAM_ITEM_SERVICE: + ret = extract_string(&pd->service, size, body, blen, &c); + if (ret != EOK) return ret; + break; + case SSS_PAM_ITEM_TTY: + ret = extract_string(&pd->tty, size, body, blen, &c); + if (ret != EOK) return ret; + break; + case SSS_PAM_ITEM_RUSER: + ret = extract_string(&pd->ruser, size, body, blen, &c); + if (ret != EOK) return ret; + break; + case SSS_PAM_ITEM_RHOST: + ret = extract_string(&pd->rhost, size, body, blen, &c); + if (ret != EOK) return ret; + break; + case SSS_PAM_ITEM_REQUESTED_DOMAINS: + ret = extract_string(&requested_domains, size, body, blen, + &c); + if (ret != EOK) return ret; + + ret = split_on_separator(pd, requested_domains, ',', true, + true, &pd->requested_domains, + NULL); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to parse requested_domains list!\n"); + return ret; + } + break; + case SSS_PAM_ITEM_CLI_PID: + ret = extract_uint32_t(&pd->cli_pid, size, + body, blen, &c); + if (ret != EOK) return ret; + break; + case SSS_PAM_ITEM_AUTHTOK: + ret = extract_authtok_v2(pd->authtok, + size, body, blen, &c); + if (ret != EOK) return ret; + break; + case SSS_PAM_ITEM_NEWAUTHTOK: + ret = extract_authtok_v2(pd->newauthtok, + size, body, blen, &c); + if (ret != EOK) return ret; + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, + "Ignoring unknown data type [%d].\n", type); + c += size; + } + } + + } while(c < blen); + + return EOK; + +} + +static int pam_parse_in_data_v3(struct pam_data *pd, + uint8_t *body, size_t blen) +{ + int ret; + + ret = pam_parse_in_data_v2(pd, body, blen); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "pam_parse_in_data_v2 failed.\n"); + return ret; + } + + if (pd->cli_pid == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, "Missing client PID.\n"); + return EINVAL; + } + + return EOK; +} + +static int extract_string(char **var, size_t size, uint8_t *body, size_t blen, + size_t *c) +{ + uint8_t *str; + + if (*c+size > blen || SIZE_T_OVERFLOW(*c, size)) return EINVAL; + + str = body+(*c); + + if (str[size-1]!='\0') return EINVAL; + + /* If the string isn't valid UTF-8, fail */ + if (!sss_utf8_check(str, size-1)) { + return EINVAL; + } + + *c += size; + + *var = (char *) str; + + return EOK; +} + +static int extract_uint32_t(uint32_t *var, size_t size, uint8_t *body, + size_t blen, size_t *c) +{ + + if (size != sizeof(uint32_t) + || *c+size > blen + || SIZE_T_OVERFLOW(*c, size)) { + return EINVAL; + } + + SAFEALIGN_COPY_UINT32_CHECK(var, &body[*c], blen, c); + + return EOK; +} + +static int extract_authtok_v1(struct sss_auth_token *tok, + uint8_t *body, size_t blen, size_t *c) +{ + uint32_t auth_token_type; + uint32_t auth_token_length; + uint8_t *auth_token_data; + int ret = EOK; + + SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c); + SAFEALIGN_COPY_UINT32_CHECK(&auth_token_length, &body[*c], blen, c); + auth_token_data = body+(*c); + + switch (auth_token_type) { + case SSS_AUTHTOK_TYPE_EMPTY: + sss_authtok_set_empty(tok); + break; + case SSS_AUTHTOK_TYPE_PASSWORD: + ret = sss_authtok_set_password(tok, (const char *)auth_token_data, + auth_token_length); + break; + default: + return EINVAL; + } + + *c += auth_token_length; + + return ret; +} + +static int extract_authtok_v2(struct sss_auth_token *tok, + size_t data_size, uint8_t *body, size_t blen, + size_t *c) +{ + uint32_t auth_token_type; + uint32_t auth_token_length; + uint8_t *auth_token_data; + int ret = EOK; + + if (data_size < sizeof(uint32_t) || *c+data_size > blen || + SIZE_T_OVERFLOW(*c, data_size)) return EINVAL; + + SAFEALIGN_COPY_UINT32_CHECK(&auth_token_type, &body[*c], blen, c); + auth_token_length = data_size - sizeof(uint32_t); + auth_token_data = body+(*c); + + switch (auth_token_type) { + case SSS_AUTHTOK_TYPE_EMPTY: + sss_authtok_set_empty(tok); + break; + case SSS_AUTHTOK_TYPE_PASSWORD: + if (auth_token_length == 0) { + sss_authtok_set_empty(tok); + } else { + ret = sss_authtok_set_password(tok, (const char *)auth_token_data, + auth_token_length); + } + break; + case SSS_AUTHTOK_TYPE_2FA: + ret = sss_authtok_set(tok, SSS_AUTHTOK_TYPE_2FA, + auth_token_data, auth_token_length); + break; + case SSS_AUTHTOK_TYPE_SC_PIN: + ret = sss_authtok_set_sc_pin(tok, (const char *) auth_token_data, + auth_token_length); + break; + case SSS_AUTHTOK_TYPE_SC_KEYPAD: + sss_authtok_set_sc_keypad(tok); + break; + default: + return EINVAL; + } + + *c += auth_token_length; + + return ret; +} -- 2.4.11