Skip to content

Commit

Permalink
Passkey: Conditional fixes
Browse files Browse the repository at this point in the history
Reviewed-by: Alexey Tikhonov <[email protected]>
Reviewed-by: Pavel Březina <[email protected]>
(cherry picked from commit 053b6e1)
  • Loading branch information
justin-stephenson authored and pbrezina committed Sep 4, 2023
1 parent ee8f50f commit 2a3a132
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 80 deletions.
2 changes: 2 additions & 0 deletions src/providers/ipa/ipa_subdomains.c
Original file line number Diff line number Diff line change
Expand Up @@ -2610,7 +2610,9 @@ static errno_t ipa_subdomains_refresh_retry(struct tevent_req *req);
static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq);
static void ipa_subdomains_refresh_ranges_done(struct tevent_req *subreq);
static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq);
#ifdef BUILD_PASSKEY
static void ipa_subdomains_refresh_passkey_done(struct tevent_req *subreq);
#endif /* BUILD_PASSKEY */
static void ipa_subdomains_refresh_master_done(struct tevent_req *subreq);
static void ipa_subdomains_refresh_slave_done(struct tevent_req *subreq);
static void ipa_subdomains_refresh_view_name_done(struct tevent_req *subreq);
Expand Down
170 changes: 90 additions & 80 deletions src/providers/krb5/krb5_child.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,20 @@
#include "util/sss_chain_id.h"
#include "util/sss_ptr_hash.h"
#include "src/util/util_errors.h"
#include "responder/pam/pamsrv_passkey.h"
#include "providers/backend.h"
#include "providers/krb5/krb5_auth.h"
#include "providers/krb5/krb5_utils.h"
#include "krb5_plugin/idp/idp.h"
#ifdef BUILD_PASSKEY
#include "responder/pam/pamsrv_passkey.h"
#include "krb5_plugin/passkey/passkey.h"
#endif /* BUILD_PASSKEY */
#include "sss_cli.h"

#define SSSD_KRB5_CHANGEPW_PRINCIPAL "kadmin/changepw"
#ifndef BUILD_PASSKEY
#define SSSD_PASSKEY_QUESTION "passkey"
#endif /* BUILD_PASSKEY */

typedef krb5_error_code
(*k5_init_creds_password_fn_t)(krb5_context context, krb5_creds *creds,
Expand Down Expand Up @@ -122,7 +127,9 @@ static krb5_context krb5_error_ctx;

static errno_t k5c_attach_otp_info_msg(struct krb5_req *kr);
static errno_t k5c_attach_oauth2_info_msg(struct krb5_req *kr, struct sss_idp_oauth2 *data);
#ifdef BUILD_PASSKEY
static errno_t k5c_attach_passkey_msg(struct krb5_req *kr, struct sss_passkey_challenge *data);
#endif /* BUILD_PASSKEY */
static errno_t k5c_attach_keep_alive_msg(struct krb5_req *kr);
static errno_t k5c_recv_data(struct krb5_req *kr, int fd, uint32_t *offline);
static errno_t k5c_send_data(struct krb5_req *kr, int fd, errno_t error);
Expand Down Expand Up @@ -937,6 +944,87 @@ static krb5_error_code answer_idp_oauth2(krb5_context kctx,
return kerr;
}

#ifdef BUILD_PASSKEY
static errno_t k5c_attach_passkey_msg(struct krb5_req *kr,
struct sss_passkey_challenge *data)
{
uint8_t *msg;
const char *user_verification;
int i;
size_t msg_len = 0;
size_t domain_len = 0;
size_t crypto_len = 0;
size_t num_creds = 0;
size_t cred_len = 0;
size_t verification_len = 0;
size_t idx = 0;
errno_t ret;

if (data->domain == NULL || data->credential_id_list == NULL
|| data->cryptographic_challenge == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Empty passkey domain, credential id list, or cryptographic "
"challenge\n");
return EINVAL;
}

user_verification = data->user_verification == 0 ? "false" : "true";
verification_len = strlen(user_verification) + 1;
msg_len += verification_len;

crypto_len = strlen(data->cryptographic_challenge) + 1;
msg_len += crypto_len;

domain_len = strlen(data->domain) + 1;
msg_len += domain_len;

/* credentials list size */
msg_len += sizeof(uint32_t);

for (i = 0; data->credential_id_list[i] != NULL; i++) {
msg_len += (strlen(data->credential_id_list[i]) + 1);
}
num_creds = i;

msg = talloc_zero_size(kr, msg_len);
if (msg == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
return ENOMEM;
}

/* To avoid sending extraneous data back and forth to pam_sss,
* (and reduce boilerplate memcpy code) only the user
* verification and cryptographic challenge are retrieved in pam_sss.
*
* The remaining passkey data (domain, creds list, num_creds)
* is sent to the PAM responder and stored in a hash table. The
* challenge is used as a unique key of the hash table. The pam_sss
* reply includes the challenge which is used to lookup the passkey
* data in the PAM responder, ensuring it matches the originating
* request */
memcpy(msg + idx, user_verification, verification_len);
idx += verification_len;

memcpy(msg + idx, data->cryptographic_challenge, crypto_len);
idx += crypto_len;

memcpy(msg + idx, data->domain, domain_len);
idx += domain_len;

SAFEALIGN_COPY_UINT32(msg + idx, &num_creds, &idx);

for (i = 0; data->credential_id_list[i] != NULL; i++) {
cred_len = strlen(data->credential_id_list[i]) + 1;
memcpy(msg + idx, data->credential_id_list[i], cred_len);
idx += cred_len;
}

ret = pam_add_response(kr->pd, SSS_PAM_PASSKEY_KRB_INFO, msg_len, msg);
talloc_zfree(msg);

return ret;
}

static krb5_error_code passkey_preauth(struct krb5_req *kr,
struct sss_passkey_challenge *passkey)
{
Expand Down Expand Up @@ -994,6 +1082,7 @@ static krb5_error_code passkey_preauth(struct krb5_req *kr,
talloc_free(tmpkr);
return ret;
}
#endif /* BUILD_PASSKEY */

static krb5_error_code answer_passkey(krb5_context kctx,
struct krb5_req *kr,
Expand Down Expand Up @@ -1564,85 +1653,6 @@ static errno_t k5c_attach_oauth2_info_msg(struct krb5_req *kr,
return ret;
}

static errno_t k5c_attach_passkey_msg(struct krb5_req *kr,
struct sss_passkey_challenge *data)
{
uint8_t *msg;
const char *user_verification;
int i;
size_t msg_len = 0;
size_t domain_len = 0;
size_t crypto_len = 0;
size_t num_creds = 0;
size_t cred_len = 0;
size_t verification_len = 0;
size_t idx = 0;
errno_t ret;

if (data->domain == NULL || data->credential_id_list == NULL
|| data->cryptographic_challenge == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Empty passkey domain, credential id list, or cryptographic "
"challenge\n");
return EINVAL;
}

user_verification = data->user_verification == 0 ? "false" : "true";
verification_len = strlen(user_verification) + 1;
msg_len += verification_len;

crypto_len = strlen(data->cryptographic_challenge) + 1;
msg_len += crypto_len;

domain_len = strlen(data->domain) + 1;
msg_len += domain_len;

/* credentials list size */
msg_len += sizeof(uint32_t);

for (i = 0; data->credential_id_list[i] != NULL; i++) {
msg_len += (strlen(data->credential_id_list[i]) + 1);
}
num_creds = i;

msg = talloc_zero_size(kr, msg_len);
if (msg == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
return ENOMEM;
}

/* To avoid sending extraneous data back and forth to pam_sss,
* (and reduce boilerplate memcpy code) only the user
* verification and cryptographic challenge are retrieved in pam_sss.
*
* The remaining passkey data (domain, creds list, num_creds)
* is sent to the PAM responder and stored in a hash table. The
* challenge is used as a unique key of the hash table. The pam_sss
* reply includes the challenge which is used to lookup the passkey
* data in the PAM responder, ensuring it matches the originating
* request */
memcpy(msg + idx, user_verification, verification_len);
idx += verification_len;

memcpy(msg + idx, data->cryptographic_challenge, crypto_len);
idx += crypto_len;

memcpy(msg + idx, data->domain, domain_len);
idx += domain_len;

SAFEALIGN_COPY_UINT32(msg + idx, &num_creds, &idx);

for (i = 0; data->credential_id_list[i] != NULL; i++) {
cred_len = strlen(data->credential_id_list[i]) + 1;
memcpy(msg + idx, data->credential_id_list[i], cred_len);
idx += cred_len;
}

ret = pam_add_response(kr->pd, SSS_PAM_PASSKEY_KRB_INFO, msg_len, msg);
talloc_zfree(msg);

return ret;
}

static errno_t k5c_attach_keep_alive_msg(struct krb5_req *kr)
{
Expand Down

0 comments on commit 2a3a132

Please sign in to comment.