diff options
author | Sumit Bose <sbose@redhat.com> | 2009-02-24 19:37:42 -0500 |
---|---|---|
committer | Simo Sorce <ssorce@redhat.com> | 2009-02-24 21:01:02 -0500 |
commit | fcef1231eea30ee9cdc75f3f39f4b9207a84ea1d (patch) | |
tree | 50525e47d7136efe2c7c746edff0de897a8d2b81 /sss_client/pam_sss.c | |
parent | 98531e56318b65eb1bb6883fdfe12e771d8a1efe (diff) | |
download | sssd-fcef1231eea30ee9cdc75f3f39f4b9207a84ea1d.tar.gz sssd-fcef1231eea30ee9cdc75f3f39f4b9207a84ea1d.tar.xz sssd-fcef1231eea30ee9cdc75f3f39f4b9207a84ea1d.zip |
Add PAM client
Also rename nss_client to sss_client and reuse the same
pipe protocol for both the NSS and PAM client libraries.
Signed-off-by: Simo Sorce <ssorce@redhat.com>
Diffstat (limited to 'sss_client/pam_sss.c')
-rw-r--r-- | sss_client/pam_sss.c | 324 |
1 files changed, 324 insertions, 0 deletions
diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c new file mode 100644 index 000000000..25a1d2caf --- /dev/null +++ b/sss_client/pam_sss.c @@ -0,0 +1,324 @@ + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#define PAM_SM_SESSION +#define PAM_SM_PASSWORD + +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdint.h> +#include <security/pam_modules.h> +#include <security/pam_misc.h> + +#include "sss_cli.h" + +struct pam_items { + const char* pam_service; + const char* pam_user; + const char* pam_tty; + const char* pam_ruser; + const char* pam_rhost; + const char* pam_authtok; + const char* pam_newauthtok; + const char* pamstack_authtok; + const char* pamstack_oldauthtok; + int pam_service_size; + int pam_user_size; + int pam_tty_size; + int pam_ruser_size; + int pam_rhost_size; + int pam_authtok_type; + int pam_authtok_size; + int pam_newauthtok_type; + int pam_newauthtok_size; +}; + + +static int get_pam_items(pam_handle_t *pamh, struct pam_items *pi) { + int ret; + + ret = pam_get_item(pamh, PAM_SERVICE, (const void **) &(pi->pam_service)); + if (ret != PAM_SUCCESS) return ret; + if (pi->pam_service == NULL) pi->pam_service=""; + pi->pam_service_size=strlen(pi->pam_service)+1; + + ret = pam_get_item(pamh, PAM_USER, (const void **) &(pi->pam_user)); + if (ret != PAM_SUCCESS) return ret; + if (pi->pam_user == NULL) pi->pam_user=""; + pi->pam_user_size=strlen(pi->pam_user)+1; + + ret = pam_get_item(pamh, PAM_TTY, (const void **) &(pi->pam_tty)); + if (ret != PAM_SUCCESS) return ret; + if (pi->pam_tty == NULL) pi->pam_tty=""; + pi->pam_tty_size=strlen(pi->pam_tty)+1; + + ret = pam_get_item(pamh, PAM_RUSER, (const void **) &(pi->pam_ruser)); + if (ret != PAM_SUCCESS) return ret; + if (pi->pam_ruser == NULL) pi->pam_ruser=""; + pi->pam_ruser_size=strlen(pi->pam_ruser)+1; + + ret = pam_get_item(pamh, PAM_RHOST, (const void **) &(pi->pam_rhost)); + if (ret != PAM_SUCCESS) return ret; + if (pi->pam_rhost == NULL) pi->pam_rhost=""; + pi->pam_rhost_size=strlen(pi->pam_rhost)+1; + + ret = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &(pi->pamstack_authtok)); + if (ret != PAM_SUCCESS) return ret; + if (pi->pamstack_authtok == NULL) pi->pamstack_authtok=""; + + ret = pam_get_item(pamh, PAM_OLDAUTHTOK, (const void **) &(pi->pamstack_oldauthtok)); + if (ret != PAM_SUCCESS) return ret; + if (pi->pamstack_oldauthtok == NULL) pi->pamstack_oldauthtok=""; + + return PAM_SUCCESS; +} + +static void print_pam_items(struct pam_items pi) { + D(("Service: %s", *pi.pam_service!='\0' ? pi.pam_service : "(not available)")); + D(("User: %s", *pi.pam_user!='\0' ? pi.pam_user : "(not available)")); + D(("Tty: %s", *pi.pam_tty!='\0' ? pi.pam_tty : "(not available)")); + D(("Ruser: %s", *pi.pam_ruser!='\0' ? pi.pam_ruser : "(not available)")); + D(("Rhost: %s", *pi.pam_rhost!='\0' ? pi.pam_rhost : "(not available)")); + D(("Authtok: %s", *pi.pamstack_authtok!='\0' ? pi.pamstack_authtok : "(not available)")); + D(("Oldauthtok: %s", *pi.pamstack_oldauthtok!='\0' ? pi.pamstack_oldauthtok : "(not available)")); +} + +static int pam_sss(int task, pam_handle_t *pamh, int flags, int argc, + const char **argv) { + int ret; + int errnop; + struct pam_items pi; + struct sss_cli_req_data rd; + uint8_t *repbuf=NULL; + size_t replen; + size_t rp; + char *buf=NULL; + struct pam_conv *conv; + struct pam_message *mesg[1]; + struct pam_response *resp=NULL; + int pam_status; + char *domain; + + D(("Hello pam_sssd: %d", task)); + + ret = get_pam_items(pamh, &pi); + if (ret != PAM_SUCCESS) { + D(("get items returned error: %s", pam_strerror(pamh,ret))); + return ret; + } + + pi.pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY; + pi.pam_authtok = NULL; + pi.pam_authtok_size = 0; + pi.pam_newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY; + pi.pam_newauthtok = NULL; + pi.pam_newauthtok_size = 0; +/* according to pam_conv(3) only one message should be requested by conv to + * keep compatibility to Solaris. Therefore we make separate calls to request + * AUTHTOK and OLDAUTHTOK. */ + if (task == SSS_PAM_AUTHENTICATE || task == SSS_PAM_CHAUTHTOK) { + ret=pam_get_item(pamh, PAM_CONV, (const void **) &conv); + if (ret != PAM_SUCCESS) return ret; + + mesg[0] = malloc(sizeof(struct pam_message)); + if (mesg[0] == NULL) { + D(("Malloc failed.\n")); + return PAM_SYSTEM_ERR; + } + mesg[0]->msg_style = PAM_PROMPT_ECHO_OFF; + mesg[0]->msg = strdup("Password: "); + + ret=conv->conv(1, (const struct pam_message **) mesg, &resp, + conv->appdata_ptr); + free((void *)mesg[0]->msg); + free(mesg[0]); + if (ret != PAM_SUCCESS) { + D(("Conversation failure: %s.\n", pam_strerror(pamh,ret))); + pam_status = ret; + goto done; + } + + if (resp[0].resp == NULL) { + D(("Empty password\n")); + pi.pam_authtok = NULL; + pi.pam_authtok_type = SSS_AUTHTOK_TYPE_EMPTY; + } else { + pi.pam_authtok = strdup(resp[0].resp); + pi.pam_authtok_type = SSS_AUTHTOK_TYPE_PASSWORD; + } + pi.pam_authtok_size=strlen(pi.pam_authtok); + } + + if (task == SSS_PAM_CHAUTHTOK) { + ret=pam_get_item(pamh, PAM_CONV, (const void **) &conv); + if (ret != PAM_SUCCESS) return ret; + + mesg[0] = malloc(sizeof(struct pam_message)); + if (mesg[0] == NULL) { + D(("Malloc failed.\n")); + return PAM_SYSTEM_ERR; + } + mesg[0]->msg_style = PAM_PROMPT_ECHO_OFF; + mesg[0]->msg = strdup("New Password: "); + + ret=conv->conv(1, (const struct pam_message **) mesg, &resp, + conv->appdata_ptr); + free((void *)mesg[0]->msg); + free(mesg[0]); + if (ret != PAM_SUCCESS) { + D(("Conversation failure: %s.\n", pam_strerror(pamh,ret))); + pam_status = ret; + goto done; + } + + if (resp[0].resp == NULL) { + D(("Empty password\n")); + pi.pam_newauthtok = NULL; + pi.pam_newauthtok_type = SSS_AUTHTOK_TYPE_EMPTY; + } else { + pi.pam_newauthtok = strdup(resp[0].resp); + pi.pam_newauthtok_type = SSS_AUTHTOK_TYPE_PASSWORD; + } + pi.pam_newauthtok_size=strlen(pi.pam_newauthtok); + } + + print_pam_items(pi); + + if (pi.pam_user) { + rd.len = pi.pam_user_size + + pi.pam_service_size + + pi.pam_tty_size + + pi.pam_ruser_size + + pi.pam_rhost_size + + 2*sizeof(uint32_t) + pi.pam_authtok_size + + 2*sizeof(uint32_t) + pi.pam_newauthtok_size + + sizeof(uint32_t); + buf = malloc(rd.len); + + memcpy(buf, pi.pam_user, pi.pam_user_size); + rp = pi.pam_user_size; + + memcpy(&buf[rp], pi.pam_service, pi.pam_service_size); + rp += pi.pam_service_size; + + memcpy(&buf[rp], pi.pam_tty, pi.pam_tty_size); + rp += pi.pam_tty_size; + + memcpy(&buf[rp], pi.pam_ruser, pi.pam_ruser_size); + rp += pi.pam_ruser_size; + + memcpy(&buf[rp], pi.pam_rhost, pi.pam_rhost_size); + rp += pi.pam_rhost_size; + + ((uint32_t *)(&buf[rp]))[0] = pi.pam_authtok_type; + rp += sizeof(uint32_t); + ((uint32_t *)(&buf[rp]))[0] = pi.pam_authtok_size; + rp += sizeof(uint32_t); + memcpy(&buf[rp], pi.pam_authtok, pi.pam_authtok_size); + rp += pi.pam_authtok_size; + _pam_overwrite((void *)pi.pam_authtok); + free((void *)pi.pam_authtok); + + ((uint32_t *)(&buf[rp]))[0] = pi.pam_newauthtok_type; + rp += sizeof(uint32_t); + ((uint32_t *)(&buf[rp]))[0] = pi.pam_newauthtok_size; + rp += sizeof(uint32_t); + memcpy(&buf[rp], pi.pam_newauthtok, pi.pam_newauthtok_size); + rp += pi.pam_newauthtok_size; + _pam_overwrite((void *)pi.pam_newauthtok); + free((void *)pi.pam_newauthtok); + + ((uint32_t *)(&buf[rp]))[0] = END_OF_PAM_REQUEST; + rp += sizeof(uint32_t); + + if (rp != rd.len) { + D(("error during packet creation.")); + pam_status = PAM_ABORT; + goto done; + } + rd.data = buf; + + ret = sss_pam_make_request(task, &rd, &repbuf, &replen, &errnop); + + if (ret != NSS_STATUS_SUCCESS) { + D(("sss_pam_make_request failed.")); + pam_status = ret; + goto done; + } + + if (replen<sizeof(int) || repbuf[replen-1]!='\0') { + D(("response not in expected format.")); + pam_status=PAM_SYSTEM_ERR; + goto done; + } + + pam_status = ((int32_t *)repbuf)[0]; + domain = (char *)(repbuf + sizeof(uint32_t)); + D(("received: %d (%s)", pam_status, pam_strerror(pamh,pam_status))); + D(("received: %s", domain)); + } else { + D(("no user found, doing nothing")); + return PAM_SUCCESS; + } + +done: + if ( resp != NULL ) { + _pam_overwrite((void *)resp[0].resp); + free(resp[0].resp); + free(resp); + } + if ( buf != NULL && repbuf != NULL) _pam_overwrite_n(buf, rd.len); + free(buf); + free(repbuf); + + return pam_status; +} + +PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, + const char **argv ) { + return pam_sss(SSS_PAM_AUTHENTICATE, pamh, flags, argc, argv); +} + + +PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, + const char **argv ) { + return pam_sss(SSS_PAM_SETCRED, pamh, flags, argc, argv); +} + +PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, + const char **argv ) { + return pam_sss(SSS_PAM_ACCT_MGMT, pamh, flags, argc, argv); +} + +PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, + const char **argv ) { + return pam_sss(SSS_PAM_CHAUTHTOK, pamh, flags, argc, argv); +} + +PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, + const char **argv ) { + return pam_sss(SSS_PAM_OPEN_SESSION, pamh, flags, argc, argv); +} + +PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, + const char **argv ) { + return pam_sss(SSS_PAM_CLOSE_SESSION, pamh, flags, argc, argv); +} + + +#ifdef PAM_STATIC + +/* static module data */ + +struct pam_module _pam_sssd_modstruct = { + "pam_sssd", + pam_sm_authenticate, + pam_sm_setcred, + pam_sm_acct_mgmt, + pam_sm_open_session, + pam_sm_close_session, + pam_sm_chauthtok +}; + +#endif |