2
2
pam.c - pam module functions
4
4
Copyright (C) 2009 Howard Chu
5
Copyright (C) 2009, 2010 Arthur de Jong
5
Copyright (C) 2009, 2010, 2011 Arthur de Jong
7
7
This library is free software; you can redistribute it and/or
8
8
modify it under the terms of the GNU Lesser General Public
94
94
/* free the context (this is installed as handler into PAM) */
95
static void ctx_free(pam_handle_t *UNUSED(pamh),void *data,int UNUSED(err))
95
static void ctx_free(pam_handle_t UNUSED(*pamh),void *data,int UNUSED(err))
97
97
struct pld_ctx *ctx=data;
146
146
uid_t minimum_uid;
149
static int init(pam_handle_t *pamh,int flags,int argc,const char **argv,
150
struct pld_cfg *cfg,struct pld_ctx **ctx,const char **username,
151
const char **service)
149
static void cfg_init(pam_handle_t *pamh,int flags,int argc,const char **argv,
155
struct passwd *pwent;
156
153
/* initialise config with defaults */
187
184
/* check flags */
188
185
if (flags&PAM_SILENT)
189
static int init(pam_handle_t *pamh,struct pld_cfg *cfg,struct pld_ctx **ctx,
190
const char **username,const char **service)
193
struct passwd *pwent;
190
194
/* get user name */
191
195
rc=pam_get_user(pamh,username,NULL);
192
196
if (rc!=PAM_SUCCESS)
239
243
map(PAM_NEW_AUTHTOK_REQD);
240
244
map(PAM_ACCT_EXPIRED);
241
245
map(PAM_SESSION_ERR);
246
map(PAM_AUTHTOK_ERR);
242
247
map(PAM_AUTHTOK_DISABLE_AGING);
245
default: return PAM_ABORT;
250
map(PAM_AUTHTOK_EXPIRED);
252
pam_syslog(pamh,LOG_ERR,"unknown NSLCD_PAM_* code returned: %d",rc);
257
/* check whether the specified user is handled by nslcd */
258
static int nslcd_request_exists(pam_handle_t *pamh,struct pld_ctx *ctx,struct pld_cfg *cfg,
259
const char *username)
263
PAM_REQUEST(NSLCD_ACTION_PASSWD_BYNAME,
264
/* log debug message */
265
pam_syslog(pamh,LOG_DEBUG,"nslcd account check; user=%s",username),
266
/* write the request parameters */
267
WRITE_STRING(fp,username),
268
/* read the result entry */
269
SKIP_STRING(fp); /* user name */
270
SKIP_STRING(fp); /* passwd entry */
271
READ_TYPE(fp,dummy_uid,uid_t);
272
READ_TYPE(fp,dummy_gid,gid_t);
273
SKIP_STRING(fp); /* gecos */
274
SKIP_STRING(fp); /* home dir */
275
SKIP_STRING(fp); /* shell */
249
279
/* perform an authentication call over nslcd */
250
280
static int nslcd_request_authc(pam_handle_t *pamh,struct pld_ctx *ctx,struct pld_cfg *cfg,
251
281
const char *username,const char *service,
352
382
const char *username,*service;
353
383
char *passwd=NULL;
354
384
/* set up configuration */
355
rc=init(pamh,flags,argc,argv,&cfg,&ctx,&username,&service);
385
cfg_init(pamh,flags,argc,argv,&cfg);
386
rc=init(pamh,&cfg,&ctx,&username,&service);
356
387
if (rc!=PAM_SUCCESS)
388
return remap_pam_rc(rc,&cfg);
358
389
/* get the password */
359
390
rc=pam_get_authtok(pamh,PAM_AUTHTOK,(const char **)&passwd,NULL);
360
391
if (rc!=PAM_SUCCESS)
415
446
const char *username,*service;
416
447
const char *ruser=NULL,*rhost=NULL,*tty=NULL;
417
448
/* set up configuration */
418
rc=init(pamh,flags,argc,argv,&cfg,&ctx,&username,&service);
449
cfg_init(pamh,flags,argc,argv,&cfg);
450
rc=init(pamh,&cfg,&ctx,&username,&service);
419
451
if (rc!=PAM_SUCCESS)
452
return remap_pam_rc(rc,&cfg);
421
453
/* get more PAM information */
422
454
pam_get_item(pamh,PAM_RUSER,(const void **)&ruser);
423
455
pam_get_item(pamh,PAM_RHOST,(const void **)&rhost);
433
465
/* check the returned authorisation value */
434
466
if (ctx2.authz!=PAM_SUCCESS)
468
/* turn in to generic PAM error message if message is empty */
469
if ((ctx2.authzmsg==NULL)||(ctx2.authzmsg[0]=='\0'))
470
ctx2.authzmsg=(char *)pam_strerror(pamh,ctx2.authz);
436
471
pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",ctx2.authzmsg,username);
437
472
rc=remap_pam_rc(ctx2.authz,&cfg);
438
473
if ((rc!=PAM_IGNORE)&&(!cfg.no_warn))
442
477
/* check the original authorisation check from authentication */
443
478
if (ctx->authz!=PAM_SUCCESS)
480
if ((ctx->authzmsg==NULL)||(ctx->authzmsg[0]=='\0'))
481
ctx->authzmsg=(char *)pam_strerror(pamh,ctx->authz);
445
482
pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",ctx->authzmsg,username);
446
483
rc=remap_pam_rc(ctx->authz,&cfg);
447
484
if ((rc!=PAM_IGNORE)&&(!cfg.no_warn))
468
505
const char *username,*service;
469
506
const char *tty=NULL,*rhost=NULL,*ruser=NULL;
470
507
/* set up configuration */
471
rc=init(pamh,flags,argc,argv,&cfg,&ctx,&username,&service);
508
cfg_init(pamh,flags,argc,argv,&cfg);
509
rc=init(pamh,&cfg,&ctx,&username,&service);
472
510
if (rc!=PAM_SUCCESS)
511
return remap_pam_rc(rc,&cfg);
474
512
/* get more PAM information */
475
513
pam_get_item(pamh,PAM_TTY,(const void **)&tty);
476
514
pam_get_item(pamh,PAM_RHOST,(const void **)&rhost);
513
551
const char *username,*service;
514
552
const char *oldpassword=NULL,*newpassword=NULL;
515
553
struct passwd *pwent;
516
555
/* set up configuration */
517
rc=init(pamh,flags,argc,argv,&cfg,&ctx,&username,&service);
556
cfg_init(pamh,flags,argc,argv,&cfg);
557
rc=init(pamh,&cfg,&ctx,&username,&service);
518
558
if (rc!=PAM_SUCCESS)
559
return remap_pam_rc(rc,&cfg);
560
/* see if we are dealing with an LDAP user first */
563
rc=nslcd_request_exists(pamh,ctx,&cfg,username);
565
return remap_pam_rc(rc,&cfg);
520
567
/* prelimenary check, just see if we can connect to the LDAP server
521
568
and authenticate with the current password */
522
569
if (flags&PAM_PRELIM_CHECK)
524
571
/* see if the user is trying to modify another user's password */
525
572
pwent=getpwnam(username);
526
if ((pwent!=NULL)&&(pwent->pw_uid!=getuid()))
574
if ((pwent!=NULL)&&(pwent->pw_uid!=myuid)&&(!(flags&PAM_CHANGE_EXPIRED_AUTHTOK)))
576
/* we are root so we can test if nslcd will allow us to change the
577
user's password without the admin password */
580
rc=nslcd_request_authc(pamh,ctx,&cfg,"",service,"");
581
if ((rc==PAM_SUCCESS)&&(ctx->authok==PAM_SUCCESS))
582
return pam_set_item(pamh,PAM_OLDAUTHTOK,"");
528
584
/* try to authenticate with the LDAP administrator password by passing
529
585
an empty username to the authc request */
530
586
rc=pam_get_authtok(pamh,PAM_OLDAUTHTOK,&oldpassword,"LDAP administrator password: ");
558
614
pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",pam_strerror(pamh,ctx->authok),username);
559
615
else if (cfg.debug)
560
616
pam_syslog(pamh,LOG_DEBUG,"authentication succeeded");
617
/* store password (needed if oldpassword was retreived from context) */
619
return pam_set_item(pamh,PAM_OLDAUTHTOK,oldpassword);
561
620
/* remap error code */
562
621
return remap_pam_rc(ctx->authok,&cfg);