/*
Copyright (C) 2015 Red Hat
SSSD tests: PAM tests
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
#include
#include
#include "sss_cli.h"
#include "responder/pam/pamsrv.h"
#include "responder/common/responder_packet.h"
#include "providers/data_provider.h"
/* FIXME - move the definition to a private header */
struct sss_packet {
size_t memsize;
/* Structure of the buffer:
* Bytes Content
* ---------------------------------
* 0-15 packet header
* 0-3 packet length (uint32_t)
* 4-7 command type (uint32_t)
* 8-11 status (uint32_t)
* 12-15 reserved
* 16+ packet body */
uint8_t *buffer;
/* io pointer */
size_t iop;
};
/* Make linker happy */
int __wrap_sss_parse_name_for_domains(TALLOC_CTX *memctx,
struct sss_domain_info *domains,
const char *default_domain,
const char *orig,
char **domain, char **name)
{
char *atsign;
atsign = strrchr(orig, '@');
if (atsign == NULL) {
*domain = NULL;
*name = talloc_strdup(memctx, orig);
if (*name == NULL) {
return ENOMEM;
}
return EOK;
}
*name = talloc_strndup(memctx, orig, atsign - orig);
*domain = talloc_strdup(memctx, atsign+1);
if (*name == NULL || *domain == NULL) {
return ENOMEM;
}
return EOK;
}
void __wrap_sss_packet_get_body(struct sss_packet *packet, uint8_t **body, size_t *blen)
{
*body = packet->buffer;
*blen = packet->memsize;
}
static struct cli_ctx *
mock_pam_cctx(TALLOC_CTX *mem_ctx,
enum sss_cli_command cmd,
int cli_protocol_version,
struct sss_cli_req_data *rd)
{
struct cli_ctx *cctx = NULL;
int ret;
cctx = talloc_zero(mem_ctx, struct cli_ctx);
if (!cctx) goto fail;
cctx->creq = talloc_zero(cctx, struct cli_request);
if (cctx->creq == NULL) goto fail;
cctx->cli_protocol_version = talloc_zero(cctx,
struct cli_protocol_version);
if (cctx->cli_protocol_version == NULL) goto fail;
cctx->cli_protocol_version->version = cli_protocol_version;
cctx->creq = talloc_zero(cctx, struct cli_request);
if (cctx->creq == NULL) goto fail;
ret = sss_packet_new(cctx->creq, 0, cmd, &cctx->creq->in);
if (ret != EOK) goto fail;
cctx->rctx = talloc_zero(cctx, struct resp_ctx);
if (cctx->rctx == NULL) goto fail;
cctx->creq->in->buffer = discard_const(rd->data);
cctx->creq->in->memsize = rd->len;
return cctx;
fail:
talloc_free(cctx);
return NULL;
}
static struct pam_data *
mock_pam_data(TALLOC_CTX *mem_ctx, enum sss_cli_command cmd)
{
struct pam_data *pd = NULL;
pd = talloc_zero(mem_ctx, struct pam_data);
if (pd == NULL) goto fail;
pd->cmd = cmd;
pd->authtok = sss_authtok_new(pd);
pd->newauthtok = sss_authtok_new(pd);
if (pd->authtok == NULL || pd->newauthtok == NULL) goto fail;
return pd;
fail:
talloc_free(pd);
return NULL;
}
/* Receives a packed response and returns a mock reply */
int __wrap_sss_pam_make_request(enum sss_cli_command cmd,
struct sss_cli_req_data *rd,
uint8_t **repbuf, size_t *replen,
int *errnop)
{
errno_t ret;
TALLOC_CTX *test_ctx;
struct cli_ctx *cctx;
struct pam_data *pd;
test_ctx = talloc_new(NULL);
if (test_ctx == NULL) {
return ENOMEM;
}
/* The PAM responder functions expect both cctx and pd to be talloc
* contexts
*/
cctx = mock_pam_cctx(test_ctx, cmd, 3, rd);
pd = mock_pam_data(test_ctx, cmd);
if (cctx == NULL || pd == NULL) {
ret = ENOMEM;
goto done;
}
ret = pam_forwarder_parse_data(cctx, pd);
if (ret != EOK) {
goto done;
}
if (cmd == SSS_PAM_AUTHENTICATE) {
if (strcmp(pd->user, "testuser") == 0) {
const char *password;
size_t pwlen;
ret = sss_authtok_get_password(pd->authtok, &password, &pwlen);
if (ret != EOK) {
ret = EINVAL;
goto done;
}
if (strncmp(password, "secret", pwlen) == 0) {
pd->pam_status = PAM_SUCCESS;
} else {
pd->pam_status = PAM_AUTH_ERR;
}
}
}
ret = pamsrv_reply_packet(cctx->creq, pd, cmd, &cctx->creq->out);
if (ret != EOK) {
goto done;
}
*repbuf = malloc(cctx->creq->out->memsize);
memcpy(*repbuf, cctx->creq->out->buffer, cctx->creq->out->memsize);
*replen = cctx->creq->out->memsize;
ret = EOK;
done:
return ret;
}