From 0fed448ec247e5092c45d226cc28f411816c64a8 Mon Sep 17 00:00:00 2001 From: Arthur de Jong Date: Wed, 12 May 2010 21:12:23 +0000 Subject: make parsing configuration options global, reorganise a bit and make code more consistent and easier to read git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@1101 ef36b2f9-881f-0410-afb5-c4e39611909c --- pam/pam.c | 501 +++++++++++++++++++++++++++++--------------------------------- 1 file changed, 231 insertions(+), 270 deletions(-) (limited to 'pam') diff --git a/pam/pam.c b/pam/pam.c index c4afccf..4295ccd 100644 --- a/pam/pam.c +++ b/pam/pam.c @@ -30,16 +30,16 @@ #include #include -#include "common.h" -#include "compat/attrs.h" -#include "compat/pam_compat.h" - /* these are defined (before including pam_modules.h) for staticly linking */ #define PAM_SM_AUTH #define PAM_SM_ACCOUNT #define PAM_SM_SESSION #define PAM_SM_PASSWORD +#include "common.h" +#include "compat/attrs.h" +#include "compat/pam_compat.h" + #ifdef HAVE_SECURITY_PAM_APPL_H #include #endif /* HAVE_SECURITY_PAM_APPL_H */ @@ -52,13 +52,7 @@ #include #endif /* not HAVE_PAM_PAM_MODULES_H */ -#define IGNORE_UNKNOWN 1 -#define IGNORE_UNAVAIL 2 - -#define USE_FIRST 1 -#define TRY_FIRST 2 -#define USE_TOKEN 4 - +/* the name we store our context under */ #define PLD_CTX "PAM_LDAPD_CTX" /* some systems don't have LOG_AUTHPRIV */ @@ -66,9 +60,10 @@ #define LOG_AUTHPRIV LOG_AUTH #endif /* not LOG_AUTHPRIV */ -/* this struct represents that context that the PAM module keeps + +/* this struct represents the context that the PAM module keeps between calls */ -typedef struct pld_ctx { +struct pld_ctx { char *user; char *dn; char *tmpluser; @@ -78,32 +73,10 @@ typedef struct pld_ctx { int authz; int sessid; char buf[1024]; -} pld_ctx; - -/* map a NSLCD PAM status code to a PAM status code */ -static int nslcd2pam_rc(int rc) -{ -#define map(i) case NSLCD_##i: return i; - switch(rc) { - map(PAM_SUCCESS); - map(PAM_PERM_DENIED); - map(PAM_AUTH_ERR); - map(PAM_CRED_INSUFFICIENT); - map(PAM_AUTHINFO_UNAVAIL); - map(PAM_USER_UNKNOWN); - map(PAM_MAXTRIES); - map(PAM_NEW_AUTHTOK_REQD); - map(PAM_ACCT_EXPIRED); - map(PAM_SESSION_ERR); - map(PAM_AUTHTOK_DISABLE_AGING); - map(PAM_IGNORE); - map(PAM_ABORT); - default: return PAM_ABORT; - } -} +}; /* clear the context to all empty values */ -static void ctx_clear(pld_ctx *ctx) +static void ctx_clear(struct pld_ctx *ctx) { if (ctx->user) { @@ -126,15 +99,15 @@ static void ctx_clear(pld_ctx *ctx) /* free the context (this is installed as handler into PAM) */ static void ctx_free(pam_handle_t *UNUSED(pamh),void *data,int UNUSED(err)) { - pld_ctx *ctx=data; + struct pld_ctx *ctx=data; ctx_clear(ctx); free(ctx); } /* try to get the module's context, returns a PAM status code */ -static int ctx_get(pam_handle_t *pamh,const char *username,pld_ctx **pctx) +static int ctx_get(pam_handle_t *pamh,const char *username,struct pld_ctx **pctx) { - pld_ctx *ctx=NULL; + struct pld_ctx *ctx=NULL; int rc; /* try to get the context from PAM */ rc=pam_get_data(pamh, PLD_CTX,(const void **)&ctx); @@ -147,21 +120,76 @@ static int ctx_get(pam_handle_t *pamh,const char *username,pld_ctx **pctx) else { /* allocate a new context */ - ctx=calloc(1,sizeof(*ctx)); - ctx_clear(ctx); - if (!ctx) + ctx=calloc(1,sizeof(struct pld_ctx)); + if (ctx==NULL) return PAM_BUF_ERR; + ctx_clear(ctx); /* store the new context with the handler to free it */ rc=pam_set_data(pamh,PLD_CTX,ctx,ctx_free); if (rc!=PAM_SUCCESS) + { ctx_free(pamh,ctx,0); + return rc; + } } - if (rc==PAM_SUCCESS) - *pctx=ctx; - return rc; + /* return the context */ + *pctx=ctx; + return PAM_SUCCESS; +} + +/* our PAM module configuration */ +struct pld_cfg { + int use_first_pass; + int try_first_pass; + int use_authtok; + int no_warn; + int ignore_unknown_user; + int ignore_authinfo_unavail; + int debug; + uid_t minimum_uid; +}; + +static void parse_args(struct pld_cfg *cfg,int flags,int argc,const char **argv) +{ + int i; + /* initialise config with defaults */ + cfg->use_first_pass=0; + cfg->try_first_pass=0; + cfg->use_authtok=0; + cfg->no_warn=0; + cfg->ignore_unknown_user=0; + cfg->ignore_authinfo_unavail=0; + cfg->debug=0; + cfg->minimum_uid=0; + /* go over arguments */ + for (i=0;iuse_first_pass=1; + else if (strcmp(argv[i],"try_first_pass")==0) + cfg->try_first_pass=1; + else if (strcmp(argv[i],"use_authtok")==0) + cfg->use_authtok=1; + else if (strcmp(argv[i], "no_warn")==0) + cfg->no_warn=1; + else if (strcmp(argv[i],"ignore_unknown_user")==0) + cfg->ignore_unknown_user=1; + else if (strcmp(argv[i],"ignore_authinfo_unavail")==0) + cfg->ignore_authinfo_unavail=1; + else if (strcmp(argv[i],"debug")==0) + cfg->debug=1; + else if (strncmp(argv[i], "minimum_uid=", 12) == 0) + cfg->minimum_uid=(uid_t)atoi(argv[i]+12); + else + syslog(LOG_AUTHPRIV|LOG_ERR,"unknown option: %s",argv[i]); + } + /* check flags */ + if (flags&PAM_SILENT) + cfg->no_warn=1; } /* ask the user for an authentication token (password) */ +/* FIXME: get rid of this and use proper pam_get_authtok() */ static int my_pam_get_authtok(pam_handle_t *pamh,int flags,char *prompt1,char *prompt2,const char **pwd) { int rc; @@ -228,8 +256,30 @@ static int my_pam_get_authtok(pam_handle_t *pamh,int flags,char *prompt1,char *p return rc; } +/* map a NSLCD PAM status code to a PAM status code */ +static int nslcd2pam_rc(int rc) +{ +#define map(i) case NSLCD_##i: return i; + switch(rc) { + map(PAM_SUCCESS); + map(PAM_PERM_DENIED); + map(PAM_AUTH_ERR); + map(PAM_CRED_INSUFFICIENT); + map(PAM_AUTHINFO_UNAVAIL); + map(PAM_USER_UNKNOWN); + map(PAM_MAXTRIES); + map(PAM_NEW_AUTHTOK_REQD); + map(PAM_ACCT_EXPIRED); + map(PAM_SESSION_ERR); + map(PAM_AUTHTOK_DISABLE_AGING); + map(PAM_IGNORE); + map(PAM_ABORT); + default: return PAM_ABORT; + } +} + /* perform an authentication call over nslcd */ -static int nslcd_request_authc(pld_ctx *ctx,const char *username, +static int nslcd_request_authc(struct pld_ctx *ctx,const char *username, const char *service,const char *passwd) { PAM_REQUEST(NSLCD_ACTION_PAM_AUTHC, @@ -246,36 +296,75 @@ static int nslcd_request_authc(pld_ctx *ctx,const char *username, READ_BUF_STRING(fp,ctx->authzmsg);) } +/* perform an authorisation call over nslcd */ +static int nslcd_request_authz(struct pld_ctx *ctx,const char *username, + const char *service,const char *ruser, + const char *rhost,const char *tty) +{ + PAM_REQUEST(NSLCD_ACTION_PAM_AUTHZ, + /* write the request parameters */ + WRITE_STRING(fp,username); + WRITE_STRING(fp,ctx->dn); + WRITE_STRING(fp,service); + WRITE_STRING(fp,ruser); + WRITE_STRING(fp,rhost); + WRITE_STRING(fp,tty), + /* read the result entry */ + READ_BUF_STRING(fp,ctx->tmpluser); + READ_BUF_STRING(fp,ctx->dn); + READ_PAM_CODE(fp,ctx->authz); + READ_BUF_STRING(fp,ctx->authzmsg);) +} + +/* do a session nslcd request (open or close) */ +static int nslcd_request_sess(struct pld_ctx *ctx,int action,const char *service, + const char *tty, const char *rhost, + const char *ruser) +{ + PAM_REQUEST(action, + /* write the request parameters */ + WRITE_STRING(fp,ctx->user); + WRITE_STRING(fp,ctx->dn); + WRITE_STRING(fp,service); + WRITE_STRING(fp,tty); + WRITE_STRING(fp,rhost); + WRITE_STRING(fp,ruser); + WRITE_INT32(fp,ctx->sessid), + /* read the result entry */ + READ_INT32(fp,ctx->sessid)) +} + +/* do a password modification nslcd call */ +static int nslcd_request_pwmod(struct pld_ctx *ctx,const char *username, + const char *service,const char *oldpasswd, + const char *newpasswd) +{ + PAM_REQUEST(NSLCD_ACTION_PAM_PWMOD, + /* write the request parameters */ + WRITE_STRING(fp,username); + WRITE_STRING(fp,ctx->dn); + WRITE_STRING(fp,service); + WRITE_STRING(fp,oldpasswd); + WRITE_STRING(fp,newpasswd), + /* read the result entry */ + READ_BUF_STRING(fp,ctx->tmpluser); + READ_BUF_STRING(fp,ctx->dn); + READ_PAM_CODE(fp,ctx->authz); + READ_BUF_STRING(fp,ctx->authzmsg);) +} + +/* PAM authentication check */ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,const char **argv) { + struct pld_cfg cfg; int rc; const char *username,*svc; char *passwd=NULL; - int first_pass=0,ignore_flags=0; int i; - pld_ctx *ctx; - uid_t minimum_uid=0; + struct pld_ctx *ctx; struct passwd *pwd; - /* go over arguments */ - for (i=0;i0) + if (cfg.minimum_uid>0) { pwd=pam_modutil_getpwnam(args->pamh,username); - if ((pwd!=NULL)&&(pwd->pw_uidpw_uidauthok; - if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL)) + if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail) rc=PAM_IGNORE; - else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN)) + else if ((rc==PAM_USER_UNKNOWN)&&cfg.ignore_unknown_user) rc=PAM_IGNORE; } - if ((rc==PAM_SUCCESS)||(first_pass&USE_FIRST)) + if ((rc==PAM_SUCCESS)||(cfg.use_first_pass)) break; - first_pass=0; + cfg.try_first_pass=0; } /* save username */ if (rc==PAM_SUCCESS) { @@ -351,59 +440,16 @@ int pam_sm_setcred(pam_handle_t UNUSED(*pamh),int UNUSED(flags), return PAM_SUCCESS; } -/* perform an authorisation call over nslcd */ -static int nslcd_request_authz(pld_ctx *ctx,const char *username, - const char *service,const char *ruser, - const char *rhost,const char *tty) -{ - PAM_REQUEST(NSLCD_ACTION_PAM_AUTHZ, - /* write the request parameters */ - WRITE_STRING(fp,username); - WRITE_STRING(fp,ctx->dn); - WRITE_STRING(fp,service); - WRITE_STRING(fp,ruser); - WRITE_STRING(fp,rhost); - WRITE_STRING(fp,tty), - /* read the result entry */ - READ_BUF_STRING(fp,ctx->tmpluser); - READ_BUF_STRING(fp,ctx->dn); - READ_PAM_CODE(fp,ctx->authz); - READ_BUF_STRING(fp,ctx->authzmsg);) -} - +/* PAM authorisation check */ int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc,const char **argv) { + struct pld_cfg cfg; int rc; const char *username,*svc,*ruser,*rhost,*tty; - int no_warn=0, ignore_flags=0; - int i; - pld_ctx *ctx=NULL, ctx2; - uid_t minimum_uid=0; + struct pld_ctx *ctx=NULL, ctx2; struct passwd *pwent; - /* go over arguments */ - for (i=0;i0) + if (cfg.minimum_uid>0) { pwent=pam_modutil_getpwnam(args->pamh,username); - if ((pwent!=NULL)&&(pwent->pw_uidpw_uiddn; ctx2.user=ctx->user; rc=nslcd_request_authz(&ctx2,username,svc,ruser,rhost,tty); - if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL)) + if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail) rc=PAM_IGNORE; - else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN)) + else if ((rc==PAM_USER_UNKNOWN)&&cfg.ignore_unknown_user) rc=PAM_IGNORE; if (rc!=PAM_SUCCESS) { if (rc!=PAM_IGNORE) - if (!no_warn) + if (!cfg.no_warn) pam_error(pamh,"LDAP authorization failed"); + return rc; } - else + /* check the returned authorisation value */ + if (ctx2.authz!=PAM_SUCCESS) { - rc=ctx2.authz; - if (ctx2.authzmsg && ctx2.authzmsg[0]) - if (!no_warn) - pam_info(pamh,"%s",ctx2.authzmsg); - if (ctx2.authz==PAM_SUCCESS) - { - rc=ctx->authz; - if (ctx->authzmsg && ctx->authzmsg[0]) - if (!no_warn) - pam_info(pamh,"%s",ctx->authzmsg); - } + if (!cfg.no_warn) + pam_error(pamh,"%s",ctx2.authzmsg); + return ctx2.authz; } - - /* update caller's idea of the user name */ - if ( (rc==PAM_SUCCESS) && ctx->tmpluser && ctx->tmpluser[0] && - (strcmp(ctx->tmpluser,username)!=0) ) { - rc=pam_set_item(pamh,PAM_USER,ctx->tmpluser); + /* check the original authorisation check from authentication */ + if (ctx->authz!=PAM_SUCCESS) + { + if (!cfg.no_warn) + pam_error(pamh,"%s",ctx->authzmsg); + return ctx->authz; } - return rc; -} - -/* do a session nslcd request (open or close) */ -static int nslcd_request_sess(pld_ctx *ctx,int action,const char *service, - const char *tty, const char *rhost, - const char *ruser) -{ - PAM_REQUEST(action, - /* write the request parameters */ - WRITE_STRING(fp,ctx->user); - WRITE_STRING(fp,ctx->dn); - WRITE_STRING(fp,service); - WRITE_STRING(fp,tty); - WRITE_STRING(fp,rhost); - WRITE_STRING(fp,ruser); - WRITE_INT32(fp,ctx->sessid), - /* read the result entry */ - READ_INT32(fp,ctx->sessid)) + /* present any informational messages to the user */ + if ((ctx2.authzmsg!=NULL)&&(ctx2.authzmsg[0]!='\0')&&(!cfg.no_warn)) + pam_info(pamh,"%s",ctx2.authzmsg); + if ((ctx->authzmsg!=NULL)&&(ctx->authzmsg[0]!='\0')&&(!cfg.no_warn)) + pam_info(pamh,"%s",ctx->authzmsg); + return PAM_SUCCESS; } +/* PAM session open/close calls */ static int pam_sm_session(pam_handle_t *pamh,int flags,int argc, const char **argv,int action) { + struct pld_cfg cfg; int rc; const char *username; - int ignore_flags=0; - int no_warn; - int i; - pld_ctx *ctx=NULL; + struct pld_ctx *ctx=NULL; const char *service=NULL,*tty=NULL,*rhost=NULL,*ruser=NULL; - uid_t minimum_uid=0; struct passwd *pwent; - /* go over arguments */ - for (i=0;i0) + if (cfg.minimum_uid>0) { pwent=pam_modutil_getpwnam(args->pamh,username); - if ((pwent!=NULL)&&(pwent->pw_uidpw_uiddn); - WRITE_STRING(fp,service); - WRITE_STRING(fp,oldpasswd); - WRITE_STRING(fp,newpasswd), - /* read the result entry */ - READ_BUF_STRING(fp,ctx->tmpluser); - READ_BUF_STRING(fp,ctx->dn); - READ_PAM_CODE(fp,ctx->authz); - READ_BUF_STRING(fp,ctx->authzmsg);) -} - -/* prompt for LDAP administrator password */ - /* ensure that the context includes and oldpassword field */ -static const char *get_old_password(pam_handle_t *pamh, int flags,pld_ctx *ctx) +static const char *get_old_password(pam_handle_t *pamh, int flags,struct pld_ctx *ctx) { int rc; const char *oldpassword; @@ -626,41 +613,15 @@ static const char *get_old_password(pam_handle_t *pamh, int flags,pld_ctx *ctx) password and actually modify the password. */ int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv) { + struct pld_cfg cfg; int rc; const char *username,*service; const char *oldpassword=NULL; const char *newpassword=NULL; - int first_pass=0, no_warn=0, ignore_flags=0; - int i; - pld_ctx *ctx=NULL; - uid_t minimum_uid=0; + struct pld_ctx *ctx=NULL; struct passwd *pwent; /* parse module options */ - for (i=0;i0) + if (cfg.minimum_uid>0) { pwent=pam_modutil_getpwnam(args->pamh,username); - if ((pwent!=NULL)&&(pwent->pw_uidpw_uidauthok; - if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL)) + if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail) rc=PAM_IGNORE; - else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN)) + else if ((rc==PAM_USER_UNKNOWN)&&cfg.ignore_unknown_user) rc=PAM_IGNORE; /* TODO: figure out when to return PAM_TRY_AGAIN */ /* TODO: if password is incorrect (NSLCD_PAM_AUTH_ERR) log that */ @@ -733,11 +694,11 @@ int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv) rc=ctx->authz; else ctx->authzmsg=(char *)pam_strerror(pamh,rc); - if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL)) + if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail) rc=PAM_IGNORE; - else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN)) + else if ((rc==PAM_USER_UNKNOWN)&&cfg.ignore_unknown_user) rc=PAM_IGNORE; - else if (!no_warn) + else if (!cfg.no_warn) pam_error(pamh,"%s",ctx->authzmsg); return rc; } -- cgit v1.2.3