summaryrefslogtreecommitdiffstats
path: root/server/responder/pam/pamsrv_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/responder/pam/pamsrv_cmd.c')
-rw-r--r--server/responder/pam/pamsrv_cmd.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
new file mode 100644
index 000000000..4fdded309
--- /dev/null
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -0,0 +1,196 @@
+#include <errno.h>
+#include <talloc.h>
+
+#include "util/util.h"
+#include "responder/common/responder_common.h"
+#include "responder/common/responder_cmd.h"
+#include "responder/common/responder_packet.h"
+#include "responder/pam/pamsrv.h"
+
+static int pam_parse_in_data(uint8_t *body, size_t blen, struct pam_data *pd) {
+ int start;
+ int end;
+ int last=blen-1;
+ char *delim;
+
+ start = end = 0;
+ while ( end < last && body[end++]!='\0');
+ pd->user = (char *) &body[start];
+
+ delim = strchr(pd->user, SSS_DOMAIN_DELIM);
+ if (delim != NULL ) {
+ *delim = '\0';
+ pd->domain = delim+1;
+ } else {
+ pd->domain = NULL;
+ }
+
+ start = end;
+ while ( end < last && body[end++]!='\0');
+ pd->service = (char *) &body[start];
+
+ start = end;
+ while ( end < last && body[end++]!='\0');
+ pd->tty = (char *) &body[start];
+
+ start = end;
+ while ( end < last && body[end++]!='\0');
+ pd->ruser = (char *) &body[start];
+
+ start = end;
+ while ( end < last && body[end++]!='\0');
+ pd->rhost = (char *) &body[start];
+
+ start = end;
+ pd->authtok_type = (int) body[start];
+ start += sizeof(uint32_t);
+ pd->authtok_size = (int) body[start];
+ start += sizeof(uint32_t);
+ end = start+pd->authtok_size;
+ if ( pd->authtok_size == 0 ) {
+ pd->authtok = NULL;
+ } else {
+ if ( end <= blen ) {
+ pd->authtok = (uint8_t *) &body[start];
+ } else {
+ DEBUG(1, ("Invalid authtok size: %d\n", pd->authtok_size));
+ return EINVAL;
+ }
+ }
+
+ start = end;
+ pd->newauthtok_type = (int) body[start];
+ start += sizeof(uint32_t);
+ pd->newauthtok_size = (int) body[start];
+ start += sizeof(uint32_t);
+ end = start+pd->newauthtok_size;
+ if ( pd->newauthtok_size == 0 ) {
+ pd->newauthtok = NULL;
+ } else {
+ if ( end <= blen ) {
+ pd->newauthtok = (uint8_t *) &body[start];
+ } else {
+ DEBUG(1, ("Invalid newauthtok size: %d\n", pd->newauthtok_size));
+ return EINVAL;
+ }
+ }
+
+ DEBUG_PAM_DATA(4, pd);
+
+ return EOK;
+}
+
+static void pam_reply(struct cli_ctx *cctx, int pam_status, char *domain) {
+ struct sss_cmd_ctx *nctx;
+ int32_t ret_status = pam_status;
+ uint8_t *body;
+ size_t blen;
+ int ret;
+ int err = EOK;
+
+ DEBUG(4, ("pam_reply get called.\n"));
+ nctx = talloc_zero(cctx, struct sss_cmd_ctx);
+ if (!nctx) {
+ err = ENOMEM;
+ goto done;
+ }
+ nctx->cctx = cctx;
+ nctx->check_expiration = true;
+
+ ret = sss_packet_new(cctx->creq, 0, sss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != EOK) {
+ err = ret;
+ goto done;
+ }
+
+ ret = sss_packet_grow(cctx->creq->out, sizeof(int) + strlen(domain)+1 );
+ if (ret != EOK) {
+ err = ret;
+ goto done;
+ }
+
+ sss_packet_get_body(cctx->creq->out, &body, &blen);
+ DEBUG(4, ("blen: %d\n", blen));
+ memcpy(body, &ret_status, sizeof(int32_t));
+ memcpy(body+sizeof(int32_t), domain, strlen(domain)+1);
+
+done:
+ sss_cmd_done(nctx);
+}
+
+static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
+{
+ uint8_t *body;
+ size_t blen;
+ int ret;
+ struct pam_data *pd;
+
+ pd = talloc(cctx, struct pam_data);
+ if (pd == NULL) return ENOMEM;
+
+ sss_packet_get_body(cctx->creq->in, &body, &blen);
+ if (blen >= sizeof(uint32_t) &&
+ ((uint32_t *)(&body[blen - sizeof(uint32_t)]))[0] != END_OF_PAM_REQUEST) {
+ DEBUG(1, ("Received data not terminated.\n"));
+ talloc_free(pd);
+ return EINVAL;
+ }
+
+ pd->cmd = pam_cmd;
+ ret=pam_parse_in_data(body, blen, pd);
+ if( ret != 0 ) {
+ talloc_free(pd);
+ return EINVAL;
+ }
+
+ ret=pam_dp_send_req(cctx, pam_reply, PAM_DP_TIMEOUT, pd);
+ DEBUG(4, ("pam_dp_send_req returned %d\n", ret));
+
+ return ret;
+}
+
+static int pam_cmd_authenticate(struct cli_ctx *cctx) {
+ DEBUG(4, ("entering pam_cmd_authenticate\n"));
+ return pam_forwarder(cctx, SSS_PAM_AUTHENTICATE);
+}
+
+static int pam_cmd_setcred(struct cli_ctx *cctx) {
+ DEBUG(4, ("entering pam_cmd_setcred\n"));
+ return pam_forwarder(cctx, SSS_PAM_SETCRED);
+}
+
+static int pam_cmd_acct_mgmt(struct cli_ctx *cctx) {
+ DEBUG(4, ("entering pam_cmd_acct_mgmt\n"));
+ return pam_forwarder(cctx, SSS_PAM_ACCT_MGMT);
+}
+
+static int pam_cmd_open_session(struct cli_ctx *cctx) {
+ DEBUG(4, ("entering pam_cmd_open_session\n"));
+ return pam_forwarder(cctx, SSS_PAM_OPEN_SESSION);
+}
+
+static int pam_cmd_close_session(struct cli_ctx *cctx) {
+ DEBUG(4, ("entering pam_cmd_close_session\n"));
+ return pam_forwarder(cctx, SSS_PAM_CLOSE_SESSION);
+}
+
+static int pam_cmd_chauthtok(struct cli_ctx *cctx) {
+ DEBUG(4, ("entering pam_cmd_chauthtok\n"));
+ return pam_forwarder(cctx, SSS_PAM_CHAUTHTOK);
+}
+
+struct sss_cmd_table *register_sss_cmds(void) {
+ static struct sss_cmd_table sss_cmds[] = {
+ {SSS_GET_VERSION, sss_cmd_get_version},
+ {SSS_PAM_AUTHENTICATE, pam_cmd_authenticate},
+ {SSS_PAM_SETCRED, pam_cmd_setcred},
+ {SSS_PAM_ACCT_MGMT, pam_cmd_acct_mgmt},
+ {SSS_PAM_OPEN_SESSION, pam_cmd_open_session},
+ {SSS_PAM_CLOSE_SESSION, pam_cmd_close_session},
+ {SSS_PAM_CHAUTHTOK, pam_cmd_chauthtok},
+ {SSS_CLI_NULL, NULL}
+ };
+
+ return sss_cmds;
+}