~ubuntu-branches/ubuntu/precise/nss-pam-ldapd/precise-security

« back to all changes in this revision

Viewing changes to pam/pam.c

  • Committer: Package Import Robot
  • Author(s): Arthur de Jong
  • Date: 2011-09-04 21:00:00 UTC
  • mfrom: (14.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20110904210000-pe3u91iga88vtr16
Tags: 0.8.4
* Upload to unstable
* switch to using the member attribute by default instead of
  uniqueMember (backwards incompatible change)
* only return "x" as a password hash when the object has the shadowAccount
  objectClass and nsswitch.conf is configured to do shadow lookups using
  LDAP (this avoids some problems with pam_unix)
* fix problem with partial attribute name matches in DN (thanks Timothy
  White)
* fix a problem with objectSid mappings with recent versions of OpenLDAP
  (patch by Wesley Mason)
* set the socket timeout in a connection callback to avoid timeout
  issues during the SSL handshake (patch by Stefan Völkel)
* check for unknown variables in pam_authz_search
* only check password expiration when authenticating, only check account
  expiration when doing authorisation
* make buffer sizes consistent and grow all buffers holding string
  representations of numbers to be able to hold 64-bit numbers
* update AX_PTHREAD from autoconf-archive
* support querying DNS SRV records from a different domain than the current
  one (based on a patch by James M. Leddy)
* fix a problem with uninitialised memory while parsing the tls_ciphers
  option (closes: #638872) (but doesn't work yet due to #640384)
* implement bounds checking of numeric values read from LDAP (patch by
  Jakub Hrozek)
* correctly support large uid and gid values from LDAP (patch by Jakub
  Hrozek)
* improvements to the configure script (patch by Jakub Hrozek)
* switch to dh for debian/rules and bump debhelper compatibility to 8
* build Debian packages with multiarch support
* ship shlibs (but still no symbol files) for libnss-ldapd since that was
  the easiest way to support multiarch
* fix output in init script when restarting nslcd (closes: #637132)
* correctly handle leading and trailing spaces in preseeded debconf uri
  option (patch by Andreas B. Mundt) (closes: #637863)
* support spaces around database names in /etc/nsswitch.conf while
  configuring package (closes: #640185)
* updated Russian debconf translation by Yuri Kozlov (closes: #637751)
* updated French debconf translation by Christian Perrier (closes: #637756)
* added Slovak debconf translation by Slavko (closes: #637759)
* updated Danish debconf translation by Joe Hansen (closes :#637763)
* updated Brazilian Portuguese debconf translation by Denis Doria
* updated Portuguese debconf translation by Américo Monteiro
* updated Japanese debconf translation by Kenshi Muto (closes: #638195)
* updated Czech debconf translation by Miroslav Kure (closes: #639026)
* updated German debconf translation by Chris Leick (closes: #639107)
* updated Spanish debconf translation by Francisco Javier Cuadrado
  (closes: #639236)
* updated Dutch debconf translation by Arthur de Jong with help from Paul
  Gevers and Jeroen Schot

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
   pam.c - pam module functions
3
3
 
4
4
   Copyright (C) 2009 Howard Chu
5
 
   Copyright (C) 2009, 2010 Arthur de Jong
 
5
   Copyright (C) 2009, 2010, 2011 Arthur de Jong
6
6
 
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
92
92
}
93
93
 
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))
96
96
{
97
97
  struct pld_ctx *ctx=data;
98
98
  ctx_clear(ctx);
146
146
  uid_t minimum_uid;
147
147
};
148
148
 
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,
 
150
                     struct pld_cfg *cfg)
152
151
{
153
152
  int i;
154
 
  int rc;
155
 
  struct passwd *pwent;
156
153
  /* initialise config with defaults */
157
154
  cfg->nullok=0;
158
155
  cfg->no_warn=0;
187
184
  /* check flags */
188
185
  if (flags&PAM_SILENT)
189
186
    cfg->no_warn=1;
 
187
}
 
188
 
 
189
static int init(pam_handle_t *pamh,struct pld_cfg *cfg,struct pld_ctx **ctx,
 
190
                const char **username,const char **service)
 
191
{
 
192
  int rc;
 
193
  struct passwd *pwent;
190
194
  /* get user name */
191
195
  rc=pam_get_user(pamh,username,NULL);
192
196
  if (rc!=PAM_SUCCESS)
225
229
}
226
230
 
227
231
/* map a NSLCD PAM status code to a PAM status code */
228
 
static int nslcd2pam_rc(int rc)
 
232
static int nslcd2pam_rc(pam_handle_t *pamh,int rc)
229
233
{
230
234
#define map(i) case NSLCD_##i: return i;
231
235
  switch(rc) {
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);
243
248
    map(PAM_IGNORE);
244
249
    map(PAM_ABORT);
245
 
    default: return PAM_ABORT;
 
250
    map(PAM_AUTHTOK_EXPIRED);
 
251
    default:
 
252
      pam_syslog(pamh,LOG_ERR,"unknown NSLCD_PAM_* code returned: %d",rc);
 
253
      return PAM_ABORT;
246
254
  }
247
255
}
248
256
 
 
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)
 
260
{
 
261
  uid_t dummy_uid;
 
262
  gid_t dummy_gid;
 
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 */
 
276
  )
 
277
}
 
278
 
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)
357
 
    return rc;
 
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)
420
 
    return rc;
 
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)
435
467
  {
 
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)
444
479
  {
 
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)
473
 
    return rc;
 
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;
 
554
  uid_t myuid;
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)
519
 
    return rc;
 
559
    return remap_pam_rc(rc,&cfg);
 
560
  /* see if we are dealing with an LDAP user first */
 
561
  if (ctx->dn==NULL)
 
562
  {
 
563
    rc=nslcd_request_exists(pamh,ctx,&cfg,username);
 
564
    if (rc!=PAM_SUCCESS)
 
565
      return remap_pam_rc(rc,&cfg);
 
566
  }
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)
523
570
  {
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()))
 
573
    myuid=getuid();
 
574
    if ((pwent!=NULL)&&(pwent->pw_uid!=myuid)&&(!(flags&PAM_CHANGE_EXPIRED_AUTHTOK)))
527
575
    {
 
576
      /* we are root so we can test if nslcd will allow us to change the
 
577
         user's password without the admin password */
 
578
      if (myuid==0)
 
579
      {
 
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,"");
 
583
      }
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) */
 
618
    if (rc==PAM_SUCCESS)
 
619
      return pam_set_item(pamh,PAM_OLDAUTHTOK,oldpassword);
561
620
    /* remap error code */
562
621
    return remap_pam_rc(ctx->authok,&cfg);
563
622
  }