221
230
/* perform an authentication call over nslcd */
222
static int nslcd_request_authc(pld_ctx *ctx,const char *username,const char *svc,const char *passwd)
231
static int nslcd_request_authc(pld_ctx *ctx,const char *username,
232
const char *service,const char *passwd)
224
234
PAM_REQUEST(NSLCD_ACTION_PAM_AUTHC,
225
235
/* write the request parameters */
226
236
WRITE_STRING(fp,username);
227
237
WRITE_STRING(fp,ctx->dn);
228
WRITE_STRING(fp,svc);
238
WRITE_STRING(fp,service);
229
239
WRITE_STRING(fp,passwd),
230
240
/* read the result entry */
231
241
READ_BUF_STRING(fp,ctx->tmpluser);
322
332
/* called to update the authentication credentials */
323
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc,const char **argv)
333
int pam_sm_setcred(pam_handle_t UNUSED(*pamh),int UNUSED(flags),
334
int UNUSED(argc),const char UNUSED(**argv))
325
336
/* we don't need to do anything here */
326
337
return PAM_SUCCESS;
340
static int my_pam_warn(
330
341
struct pam_conv *aconv, const char *message, int style, int no_warn)
332
343
struct pam_message msg, *pmsg;
349
360
/* perform an authorisation call over nslcd */
350
361
static int nslcd_request_authz(pld_ctx *ctx,const char *username,
351
const char *svc,const char *ruser,const char *rhost,const char *tty)
362
const char *service,const char *ruser,
363
const char *rhost,const char *tty)
353
365
PAM_REQUEST(NSLCD_ACTION_PAM_AUTHZ,
354
366
/* write the request parameters */
355
367
WRITE_STRING(fp,username);
356
368
WRITE_STRING(fp,ctx->dn);
357
WRITE_STRING(fp,svc);
369
WRITE_STRING(fp,service);
358
370
WRITE_STRING(fp,ruser);
359
371
WRITE_STRING(fp,rhost);
360
372
WRITE_STRING(fp,tty),
436
448
if (rc!=PAM_SUCCESS)
438
450
if (rc!=PAM_IGNORE)
439
pam_warn(appconv,"LDAP authorization failed",PAM_ERROR_MSG,no_warn);
451
my_pam_warn(appconv,"LDAP authorization failed",PAM_ERROR_MSG,no_warn);
443
456
if (ctx2.authzmsg && ctx2.authzmsg[0])
444
pam_warn(appconv,ctx2.authzmsg,PAM_TEXT_INFO,no_warn);
457
my_pam_warn(appconv,ctx2.authzmsg,PAM_TEXT_INFO,no_warn);
445
458
if (ctx2.authz==PAM_SUCCESS)
448
461
if (ctx->authzmsg && ctx->authzmsg[0])
449
pam_warn(appconv,ctx->authzmsg,PAM_TEXT_INFO,no_warn);
462
my_pam_warn(appconv,ctx->authzmsg,PAM_TEXT_INFO,no_warn);
461
474
/* do a session nslcd request (open or close) */
462
static int nslcd_request_sess(pam_handle_t *pamh,pld_ctx *ctx,int action)
475
static int nslcd_request_sess(pld_ctx *ctx,int action,const char *service,
476
const char *tty, const char *rhost,
464
const char *svc=NULL,*tty=NULL,*rhost=NULL,*ruser=NULL;
465
479
PAM_REQUEST(action,
466
/* get information for request (ignore errors) */
467
pam_get_item(pamh,PAM_SERVICE,(const void **)&svc);
468
pam_get_item(pamh,PAM_TTY,(const void **)&tty);
469
pam_get_item(pamh,PAM_RHOST,(const void **)&rhost);
470
pam_get_item(pamh,PAM_RUSER,(const void **)&ruser);
471
480
/* write the request parameters */
472
481
WRITE_STRING(fp,ctx->user);
473
482
WRITE_STRING(fp,ctx->dn);
474
WRITE_STRING(fp,svc);
483
WRITE_STRING(fp,service);
475
484
WRITE_STRING(fp,tty);
476
485
WRITE_STRING(fp,rhost);
477
486
WRITE_STRING(fp,ruser);
521
531
rc=ctx_get(pamh,username,&ctx);
522
532
if (rc!=PAM_SUCCESS)
525
rc=nslcd_request_sess(pamh,ctx,action);
534
/* read PAM information */
535
pam_get_item(pamh,PAM_SERVICE,(const void **)&service);
536
pam_get_item(pamh,PAM_TTY,(const void **)&tty);
537
pam_get_item(pamh,PAM_RHOST,(const void **)&rhost);
538
pam_get_item(pamh,PAM_RUSER,(const void **)&ruser);
539
/* do the nslcd request */
540
rc=nslcd_request_sess(ctx,action,service,tty,rhost,ruser);
526
541
if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL))
528
543
else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN))
543
558
rc=pam_sm_session(pamh,flags,argc,argv,NSLCD_ACTION_PAM_SESS_O,&no_warn);
544
559
if ((rc!=PAM_SUCCESS)&&(rc!=PAM_IGNORE))
545
pam_warn(appconv,"LDAP open_session failed",PAM_ERROR_MSG,no_warn);
560
my_pam_warn(appconv,"LDAP open_session failed",PAM_ERROR_MSG,no_warn);
549
564
int pam_sm_close_session(
550
565
pam_handle_t *pamh, int flags, int argc, const char **argv)
553
568
struct pam_conv *appconv;
555
570
rc=pam_get_item(pamh,PAM_CONV,(const void **)&appconv);
559
574
rc=pam_sm_session(pamh,flags,argc,argv,NSLCD_ACTION_PAM_SESS_C,&no_warn);
560
575
if ((rc!=PAM_SUCCESS)&&(rc!=PAM_IGNORE))
561
pam_warn(appconv,"LDAP close_session failed",PAM_ERROR_MSG,no_warn);
576
my_pam_warn(appconv,"LDAP close_session failed",PAM_ERROR_MSG,no_warn);
565
580
/* do a password modification nslcd call */
566
static int nslcd_request_pwmod(pld_ctx *ctx,const char *username,const char *svc,
567
const char *oldpw,const char *newpw)
581
static int nslcd_request_pwmod(pld_ctx *ctx,const char *username,
582
const char *service,const char *oldpasswd,
583
const char *newpasswd)
569
PAM_REQUEST(NSLCD_ACTION_PAM_AUTHZ,
585
PAM_REQUEST(NSLCD_ACTION_PAM_PWMOD,
570
586
/* write the request parameters */
571
587
WRITE_STRING(fp,username);
572
588
WRITE_STRING(fp,ctx->dn);
573
WRITE_STRING(fp,svc);
574
WRITE_STRING(fp,oldpw);
575
WRITE_STRING(fp,newpw),
589
WRITE_STRING(fp,service);
590
WRITE_STRING(fp,oldpasswd);
591
WRITE_STRING(fp,newpasswd),
576
592
/* read the result entry */
577
593
READ_BUF_STRING(fp,ctx->tmpluser);
578
594
READ_BUF_STRING(fp,ctx->dn);
580
596
READ_BUF_STRING(fp,ctx->authzmsg);)
583
int pam_sm_chauthtok(
584
pam_handle_t *pamh, int flags, int argc, const char **argv)
587
const char *username, *p=NULL, *q=NULL, *svc;
599
/* ensure that the context includes and oldpassword field */
600
static const char *get_old_password(pam_handle_t *pamh, int flags,pld_ctx *ctx)
603
const char *oldpassword;
604
/* if we already have an old password we are done */
605
if ((ctx->oldpassword!=NULL)&&(*ctx->oldpassword!='\0'))
606
return ctx->oldpassword;
607
/* try to get the old password from the PAM stack */
608
rc=pam_get_item(pamh,PAM_OLDAUTHTOK,(const void **)&oldpassword);
609
if ((rc==PAM_SUCCESS)&&(oldpassword!=NULL)&&(*oldpassword!='\0'))
611
/* otherwise prompt for it */
612
rc=my_pam_get_authtok(pamh,flags,"(current) LDAP Password: ",NULL,
613
(const char **)&oldpassword);
614
if ((rc==PAM_SUCCESS)&&(oldpassword!=NULL)&&(*oldpassword!='\0'))
616
/* save the password */
617
pam_set_item(pamh,PAM_OLDAUTHTOK,oldpassword);
623
/* Change the password of the user. This function is first called with
624
PAM_PRELIM_CHECK set in the flags and then without the flag. In the first
625
pass it is determined whether we can contact the LDAP server and the
626
provided old password is valid. In the second pass we get the new
627
password and actually modify the password. */
628
int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv)
631
const char *username,*service;
632
const char *oldpassword=NULL;
633
const char *newpassword=NULL;
588
634
int first_pass=0, no_warn=0, ignore_flags=0;
589
int i, success=PAM_SUCCESS;
590
636
struct pam_conv *appconv;
591
637
pld_ctx *ctx=NULL;
628
674
if (rc!=PAM_SUCCESS)
631
rc=pam_get_item(pamh,PAM_SERVICE,(const void **)&svc);
677
rc=pam_get_item(pamh,PAM_SERVICE,(const void **)&service);
632
678
if (rc!=PAM_SUCCESS)
635
if (flags & PAM_PRELIM_CHECK) {
638
rc=pam_get_authtok(pamh,flags,"(current) LDAP Password: ",NULL,&p);
639
if (rc==PAM_SUCCESS) {
640
pam_set_item(pamh,PAM_OLDAUTHTOK,p);
641
memset(p,0,strlen(p));
645
rc=pam_get_item(pamh,PAM_OLDAUTHTOK,&p);
653
rc=nslcd_request_pwmod(ctx,username,svc,p,NULL);
654
if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL))
656
else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN))
662
rc=pam_get_item(pamh,PAM_OLDAUTHTOK,&p);
671
rc=pam_get_item(pamh,PAM_AUTHTOK,&q);
672
if ((rc!=PAM_SUCCESS || !q) && (first_pass & (USE_FIRST|USE_TOKEN))) {
674
rc=PAM_AUTHTOK_RECOVERY_ERR;
680
rc=pam_get_authtok(pamh, flags, "Enter new LDAP Password: ",
681
"Retype new LDAP Password: ", &q);
680
/* TODO: if we are root we may want to authenticate with the LDAP
681
administrator password (this shouldn't be a problem because
682
root is unlikely to be in LDAP anyway but perhaps we can check
683
the requested username and only use the administrator if that
685
/* prelimenary check, just see if we can connect to the LDAP server
686
and authenticate with the current password */
687
if (flags&PAM_PRELIM_CHECK)
689
/* get old (current) password */
690
oldpassword=get_old_password(pamh,flags,ctx);
691
/* check the old password */
692
rc=nslcd_request_authc(ctx,username,service,oldpassword);
682
693
if (rc==PAM_SUCCESS)
684
pam_set_item(pamh,PAM_AUTHTOK,q);
685
memset(q,0,strlen(q));
687
rc=pam_get_item(pamh,PAM_AUTHTOK,&q);
695
if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL))
697
else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN))
699
/* TODO: figure out when to return PAM_TRY_AGAIN */
700
/* TODO: if password is incorrect (NSLCD_PAM_AUTH_ERR) log that */
692
rc=nslcd_request_pwmod(ctx,username,svc,p,q);
693
if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL))
695
else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN))
703
/* get the old password (from the previous call) */
704
rc=pam_get_item(pamh,PAM_OLDAUTHTOK,(const void **)&oldpassword);
707
/* get the new password */
708
rc=pam_get_authtok(pamh,PAM_AUTHTOK,&newpassword,NULL);
711
/* perform the password modification */
712
rc=nslcd_request_pwmod(ctx,username,service,oldpassword,newpassword);
698
713
if (rc==PAM_SUCCESS)
702
pam_warn(appconv, ctx->authzmsg, PAM_ERROR_MSG, no_warn);
704
else if (rc!=PAM_IGNORE)
705
pam_warn(appconv, "LDAP pwmod failed", PAM_ERROR_MSG, no_warn);
716
ctx->authzmsg=(char *)pam_strerror(pamh,rc);
717
if ((rc==PAM_AUTHINFO_UNAVAIL)&&(ignore_flags&IGNORE_UNAVAIL))
719
else if ((rc==PAM_USER_UNKNOWN)&&(ignore_flags&IGNORE_UNKNOWN))
722
my_pam_warn(appconv,ctx->authzmsg,PAM_ERROR_MSG,no_warn);