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

« back to all changes in this revision

Viewing changes to nslcd/common.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:
3
3
   This file is part of the nss-pam-ldapd library.
4
4
 
5
5
   Copyright (C) 2006 West Consulting
6
 
   Copyright (C) 2006, 2007, 2008, 2009 Arthur de Jong
 
6
   Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Arthur de Jong
7
7
 
8
8
   This library is free software; you can redistribute it and/or
9
9
   modify it under the terms of the GNU Lesser General Public
31
31
#include <arpa/inet.h>
32
32
#include <strings.h>
33
33
#include <limits.h>
 
34
#include <netdb.h>
 
35
#include <string.h>
 
36
#include <regex.h>
 
37
#include <stdlib.h>
34
38
 
35
39
#include "nslcd.h"
36
40
#include "common.h"
37
41
#include "log.h"
 
42
#include "attmap.h"
 
43
#include "cfg.h"
38
44
 
39
45
/* simple wrapper around snptintf() to return non-0 in case
40
46
   of any failure (but always keep string 0-terminated) */
51
57
  return ((res<0)||(((size_t)res)>=buflen));
52
58
}
53
59
 
54
 
const char *get_userpassword(MYLDAP_ENTRY *entry,const char *attr)
 
60
/* return the fully qualified domain name of the current host */
 
61
const char *getfqdn(void)
55
62
{
56
 
  const char **values;
 
63
  static char *fqdn=NULL;
 
64
  char hostname[HOST_NAME_MAX+1];
 
65
  int hostnamelen;
57
66
  int i;
58
 
  /* get the entries */
59
 
  values=myldap_get_values(entry,attr);
60
 
  if ((values==NULL)||(values[0]==NULL))
 
67
  struct hostent *host=NULL;
 
68
  /* if we already have a fqdn return that */
 
69
  if (fqdn!=NULL)
 
70
    return fqdn;
 
71
  /* get system hostname */
 
72
  if (gethostname(hostname,sizeof(hostname))<0)
 
73
  {
 
74
    log_log(LOG_ERR,"gethostname() failed: %s",strerror(errno));
 
75
    return NULL;
 
76
  }
 
77
  hostnamelen=strlen(hostname);
 
78
  /* lookup hostent */
 
79
  host=gethostbyname(hostname);
 
80
  if (host==NULL)
 
81
  {
 
82
    log_log(LOG_ERR,"gethostbyname(%s): %s",hostname,hstrerror(h_errno));
 
83
    /* fall back to hostname */
 
84
    fqdn=strdup(hostname);
 
85
    return fqdn;
 
86
  }
 
87
  /* check h_name for fqdn starting with our hostname */
 
88
  if ((strncasecmp(hostname,host->h_name,hostnamelen)==0)&&
 
89
      (host->h_name[hostnamelen]=='.')&&
 
90
      (host->h_name[hostnamelen+1]!='\0'))
 
91
  {
 
92
    fqdn=strdup(host->h_name);
 
93
    return fqdn;
 
94
  }
 
95
  /* also check h_aliases */
 
96
  for (i=0;host->h_aliases[i]!=NULL;i++)
 
97
  {
 
98
    if ((strncasecmp(hostname,host->h_aliases[i],hostnamelen)==0)&&
 
99
        (host->h_aliases[i][hostnamelen]=='.')&&
 
100
        (host->h_aliases[i][hostnamelen+1]!='\0'))
 
101
    {
 
102
      fqdn=strdup(host->h_aliases[i]);
 
103
      return fqdn;
 
104
    }
 
105
  }
 
106
  /* fall back to h_name if it has a dot in it */
 
107
  if (strchr(host->h_name,'.')!=NULL)
 
108
  {
 
109
    fqdn=strdup(host->h_name);
 
110
    return fqdn;
 
111
  }
 
112
  /* also check h_aliases */
 
113
  for (i=0;host->h_aliases[i]!=NULL;i++)
 
114
  {
 
115
    if (strchr(host->h_aliases[i],'.')!=NULL)
 
116
    {
 
117
      fqdn=strdup(host->h_aliases[i]);
 
118
      return fqdn;
 
119
    }
 
120
  }
 
121
  /* nothing found, fall back to hostname */
 
122
  fqdn=strdup(hostname);
 
123
  return fqdn;
 
124
}
 
125
 
 
126
const char *get_userpassword(MYLDAP_ENTRY *entry,const char *attr,char *buffer,size_t buflen)
 
127
{
 
128
  const char *tmpvalue;
 
129
  /* get the value */
 
130
  tmpvalue=attmap_get_value(entry,attr,buffer,buflen);
 
131
  if (tmpvalue==NULL)
61
132
    return NULL;
62
133
  /* go over the entries and return the remainder of the value if it
63
134
     starts with {crypt} or crypt$ */
64
 
  for (i=0;values[i]!=NULL;i++)
65
 
  {
66
 
    if (strncasecmp(values[i],"{crypt}",7)==0)
67
 
      return values[i]+7;
68
 
    if (strncasecmp(values[i],"crypt$",6)==0)
69
 
      return values[i]+6;
70
 
  }
 
135
  if (strncasecmp(tmpvalue,"{crypt}",7)==0)
 
136
    return tmpvalue+7;
 
137
  if (strncasecmp(tmpvalue,"crypt$",6)==0)
 
138
    return tmpvalue+6;
71
139
  /* just return the first value completely */
72
 
  return values[0];
 
140
  return tmpvalue;
73
141
  /* TODO: support more password formats e.g. SMD5
74
142
    (which is $1$ but in a different format)
75
143
    (any code for this is more than welcome) */
76
144
}
77
145
 
78
 
/*
79
 
   Checks to see if the specified name seems to be a valid user or group name.
80
 
 
81
 
   This test is based on the definition from POSIX (IEEE Std 1003.1, 2004,
82
 
   3.426 User Name, 3.189 Group Name and 3.276 Portable Filename Character Set):
83
 
   http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_426
84
 
   http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_189
85
 
   http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276
86
 
 
87
 
   The standard defines user names valid if they contain characters from
88
 
   the set [A-Za-z0-9._-] where the hyphen should not be used as first
89
 
   character. As an extension this test allows some more characters.
90
 
*/
 
146
/* Checks if the specified name seems to be a valid user or group name. */
91
147
int isvalidname(const char *name)
92
148
{
93
 
  int i;
94
 
  if ((name==NULL)||(name[0]=='\0'))
95
 
    return 0;
96
 
  /* check characters */
97
 
  for (i=0;name[i]!='\0';i++)
98
 
  {
99
 
#ifdef LOGIN_NAME_MAX
100
 
    if (i>=LOGIN_NAME_MAX)
101
 
      return 0;
102
 
#endif /* LOGIN_NAME_MAX */
103
 
    if ( ! ( ( (i!=0) && (name[i]=='-') ) ||
104
 
             ( (i!=0) && (name[i]=='\\') && name[i+1]!='\0' ) ||
105
 
             (name[i]>='@' && name[i] <= 'Z') ||
106
 
             (name[i]>='a' && name[i] <= 'z') ||
107
 
             (name[i]>='0' && name[i] <= '9') ||
108
 
             name[i]=='.' || name[i]=='_'  || name[i]=='$' || name[i]==' ') )
109
 
      return 0;
110
 
  }
111
 
  /* no test failed so it must be good */
112
 
  return -1;
 
149
  return regexec(&nslcd_cfg->validnames,name,0,NULL,0)==0;
113
150
}
114
151
 
115
152
/* this writes a single address to the stream */
176
213
  /* we're done */
177
214
  return 0;
178
215
}
 
216
 
 
217
/* convert the provided string representation of a sid
 
218
   (e.g. S-1-5-21-1936905831-823966427-12391542-23578)
 
219
   to a format that can be used to search the objectSid property with */
 
220
char *sid2search(const char *sid)
 
221
{
 
222
  const char *tmpsid=sid;
 
223
  char *res,*tmp;
 
224
  int i=0;
 
225
  long int l;
 
226
  /* check the beginning of the string */
 
227
  if (strncasecmp(sid,"S-",2)!=0)
 
228
  {
 
229
    log_log(LOG_ERR,"error in SID %s",sid);
 
230
    exit(EXIT_FAILURE);
 
231
  }
 
232
  /* count the number of dashes in the sid */
 
233
  while (tmpsid!=NULL)
 
234
  {
 
235
    i++;
 
236
    tmpsid=strchr(tmpsid+1,'-');
 
237
  }
 
238
  i-=2; /* number of security ids plus one because we add the uid later */
 
239
  /* allocate memory */
 
240
  res=malloc(3+3+6*3+i*4*3+1);
 
241
  if (res==NULL)
 
242
  {
 
243
    log_log(LOG_CRIT,"malloc() failed to allocate memory");
 
244
    exit(1);
 
245
  }
 
246
  /* build the first part */
 
247
  l=strtol(sid+2,&tmp,10);
 
248
  sprintf(res,"\\%02x\\%02x",(int)l&0xff,(int)i);
 
249
  /* build authority part (we only handle 32 of the 48 bits) */
 
250
  l=strtol(tmp+1,&tmp,10);
 
251
  sprintf(res+strlen(res),"\\00\\00\\%02x\\%02x\\%02x\\%02x",
 
252
          (int)((l>>24)&0xff),(int)((l>>16)&0xff),(int)((l>>8)&0xff),(int)(l&0xff));
 
253
  /* go over the rest of the bits */
 
254
  while (*tmp!='\0')
 
255
  {
 
256
    l=strtol(tmp+1,&tmp,10);
 
257
    sprintf(res+strlen(res),"\\%02x\\%02x\\%02x\\%02x",
 
258
            (int)(l&0xff),(int)((l>>8)&0xff),(int)((l>>16)&0xff),(int)((l>>24)&0xff));
 
259
  }
 
260
  return res;
 
261
}
 
262
 
 
263
/* return the last security identifier of the binary sid */
 
264
long int binsid2id(const char *binsid)
 
265
{
 
266
  int i;
 
267
  /* find the position of the last security id */
 
268
  i=2+6+((((int)binsid[1])&0xff)-1)*4;
 
269
  return (((long int)binsid[i])&0xff)|((((long int)binsid[i+1])&0xff)<<8)|
 
270
         ((((long int)binsid[i+2])&0xff)<<16)|((((long int)binsid[i+3])&0xff)<<24);
 
271
}
 
272
 
 
273
#ifdef WANT_STRTOUI
 
274
/* provide a strtoui() implementation, similar to strtoul() but returning
 
275
   an range-checked unsigned int instead */
 
276
unsigned int strtoui(const char *nptr,char **endptr,int base)
 
277
{
 
278
  unsigned long val;
 
279
  val=strtoul(nptr,endptr,base);
 
280
  if (val>UINT_MAX)
 
281
  {
 
282
    errno=ERANGE;
 
283
    return UINT_MAX;
 
284
  }
 
285
  /* If errno was set by strtoull, we'll pass it back as-is */
 
286
  return (unsigned int)val;
 
287
}
 
288
#endif /* WANT_STRTOUI */