Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2012-09-20 20:34:03 +0200
committerArthur de Jong <arthur@arthurdejong.org>2012-09-20 20:34:03 +0200
commit6d11c9da714700bfc152f1fe79d88cacada8f571 (patch)
tree6e616f6efe7581eccee02469afe723316f71c018
parent927a27faf2a934e615d58bdccbd265490146b90c (diff)
implements proper range checking numeric values returned from LDAP (thanks Jakub Hrozek) (r1523, r1524 and r1528 from 0.8, r1600 from 0.7)
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd-0.7.15+squeeze@1772 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r--AUTHORS1
-rw-r--r--configure.ac7
-rw-r--r--nslcd/cfg.c10
-rw-r--r--nslcd/common.c19
-rw-r--r--nslcd/common.h33
-rw-r--r--nslcd/group.c9
-rw-r--r--nslcd/passwd.c18
-rw-r--r--nslcd/protocol.c9
-rw-r--r--nslcd/rpc.c9
-rw-r--r--nslcd/service.c9
-rw-r--r--nslcd/shadow.c19
11 files changed, 130 insertions, 13 deletions
diff --git a/AUTHORS b/AUTHORS
index 315b5f1..8ec88d9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -79,3 +79,4 @@ Leigh Wedding <lwedding@bigpond.com>
Jan Schampera <jan.schampera@web.de>
Nalin Dahyabhai <nalin@redhat.com>
Daniel Dehennin <daniel.dehennin@baby-gnu.org>
+Jakub Hrozek <jhrozek@redhat.com>
diff --git a/configure.ac b/configure.ac
index 2062647..6ee43ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -222,7 +222,7 @@ AC_C_CONST
AC_CHECK_FUNCS([sigaction snprintf])
AC_CHECK_FUNCS(gethostbyname)
AC_SEARCH_LIBS(socket,socket)
-AC_CHECK_FUNCS([strcasecmp strncasecmp strchr strcspn strspn strtol])
+AC_CHECK_FUNCS([strcasecmp strncasecmp strchr strcspn strspn strtol strtoul strtoull])
AC_CHECK_FUNCS([malloc realloc])
AC_FUNC_FORK
@@ -235,6 +235,11 @@ AC_TYPE_INT32_T
AC_TYPE_UINT8_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
+AC_CHECK_SIZEOF(unsigned int)
+AC_CHECK_SIZEOF(unsigned long int)
+AC_CHECK_SIZEOF(unsigned long long int)
+AC_CHECK_SIZEOF(uid_t)
+AC_CHECK_SIZEOF(gid_t)
# check for support for the __thread keyword
AC_CACHE_CHECK([whether $CC supports '__thread'], [mn_cv_c___thread_supported],
diff --git a/nslcd/cfg.c b/nslcd/cfg.c
index 1653c1a..4992c9a 100644
--- a/nslcd/cfg.c
+++ b/nslcd/cfg.c
@@ -442,8 +442,9 @@ static void get_uid(const char *filename,int lnr,
char *tmp;
check_argumentcount(filename,lnr,keyword,get_token(line,token,sizeof(token))!=NULL);
/* check if it is a valid numerical uid */
- *var=(uid_t)strtol(token,&tmp,0);
- if ((*token!='\0')&&(*tmp=='\0'))
+ errno=0;
+ *var=strtouid(token,&tmp,0);
+ if ((*token!='\0')&&(*tmp=='\0')&&(errno==0))
return;
/* find by name */
pwent=getpwnam(token);
@@ -467,8 +468,9 @@ static void get_gid(const char *filename,int lnr,
char *tmp;
check_argumentcount(filename,lnr,keyword,get_token(line,token,sizeof(token))!=NULL);
/* check if it is a valid numerical gid */
- *var=(gid_t)strtol(token,&tmp,0);
- if ((*token!='\0')&&(*tmp=='\0'))
+ errno=0;
+ *var=strtogid(token,&tmp,0);
+ if ((*token!='\0')&&(*tmp=='\0')&&(errno==0))
return;
/* find by name */
grent=getgrnam(token);
diff --git a/nslcd/common.c b/nslcd/common.c
index d88bb60..3e8b87d 100644
--- a/nslcd/common.c
+++ b/nslcd/common.c
@@ -3,7 +3,7 @@
This file is part of the nss-pam-ldapd library.
Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2009 Arthur de Jong
+ Copyright (C) 2006, 2007, 2008, 2009, 2011 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -176,3 +176,20 @@ int read_address(TFILE *fp,char *addr,int *addrlen,int *af)
/* we're done */
return 0;
}
+
+#ifdef WANT_STRTOUI
+/* provide a strtoui() implementation, similar to strtoul() but returning
+ an range-checked unsigned int instead */
+unsigned int strtoui(const char *nptr,char **endptr,int base)
+{
+ unsigned long val;
+ val=strtoul(nptr,endptr,base);
+ if (val>UINT_MAX)
+ {
+ errno=ERANGE;
+ return UINT_MAX;
+ }
+ /* If errno was set by strtoull, we'll pass it back as-is */
+ return (unsigned int)val;
+}
+#endif /* WANT_STRTOUI */
diff --git a/nslcd/common.h b/nslcd/common.h
index 1b2aa1c..e7710bf 100644
--- a/nslcd/common.h
+++ b/nslcd/common.h
@@ -3,7 +3,7 @@
This file is part of the nss-pam-ldapd library.
Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2008, 2009, 2010 Arthur de Jong
+ Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -94,6 +94,37 @@ MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid);
/* transforms the uid into a DN by doing an LDAP lookup */
MUST_USE char *uid2dn(MYLDAP_SESSION *session,const char *uid,char *buf,size_t buflen);
+/* provide strtouid() function alias */
+#if SIZEOF_UID_T == SIZEOF_UNSIGNED_LONG_INT
+#define strtouid (uid_t)strtoul
+#elif SIZEOF_UID_T == SIZEOF_UNSIGNED_LONG_LONG_INT
+#define strtouid (uid_t)strtoull
+#elif SIZEOF_UID_T == SIZEOF_UNSIGNED_INT
+#define WANT_STRTOUI 1
+#define strtouid (uid_t)strtoui
+#else
+#error unable to find implementation for strtouid()
+#endif
+
+/* provide strtouid() function alias */
+#if SIZEOF_GID_T == SIZEOF_UNSIGNED_LONG_INT
+#define strtogid (gid_t)strtoul
+#elif SIZEOF_GID_T == SIZEOF_UNSIGNED_LONG_LONG_INT
+#define strtogid (gid_t)strtoull
+#elif SIZEOF_GID_T == SIZEOF_UNSIGNED_INT
+#ifndef WANT_STRTOUI
+#define WANT_STRTOUI 1
+#endif
+#define strtogid (uid_t)strtoui
+#else
+#error unable to find implementation for strtogid()
+#endif
+
+#ifdef WANT_STRTOUI
+/* provide a strtoui() if it is needed */
+unsigned int strtoui(const char *nptr,char **endptr,int base);
+#endif /* WANT_STRTOUI */
+
/* these are the functions for initialising the database specific
modules */
void alias_init(void);
diff --git a/nslcd/group.c b/nslcd/group.c
index dfbb8fa..8397fe2 100644
--- a/nslcd/group.c
+++ b/nslcd/group.c
@@ -251,13 +251,20 @@ static int write_group(TFILE *fp,MYLDAP_ENTRY *entry,const char *reqname,
}
for (numgids=0;(gidvalues[numgids]!=NULL)&&(numgids<MAXGIDS_PER_ENTRY);numgids++)
{
- gids[numgids]=(gid_t)strtol(gidvalues[numgids],&tmp,0);
+ errno=0;
+ gids[numgids]=strtogid(gidvalues[numgids],&tmp,0);
if ((*(gidvalues[numgids])=='\0')||(*tmp!='\0'))
{
log_log(LOG_WARNING,"group entry %s contains non-numeric %s value",
myldap_get_dn(entry),attmap_group_gidNumber);
return 0;
}
+ else if (errno!=0)
+ {
+ log_log(LOG_WARNING,"group entry %s contains too large %s value",
+ myldap_get_dn(entry),attmap_group_gidNumber);
+ return 0;
+ }
}
}
/* get group passwd (userPassword) (use only first entry) */
diff --git a/nslcd/passwd.c b/nslcd/passwd.c
index 82c5062..ec2d38b 100644
--- a/nslcd/passwd.c
+++ b/nslcd/passwd.c
@@ -338,13 +338,20 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser,
}
for (numuids=0;(numuids<MAXUIDS_PER_ENTRY)&&(tmpvalues[numuids]!=NULL);numuids++)
{
- uids[numuids]=(uid_t)strtol(tmpvalues[numuids],&tmp,0);
+ errno=0;
+ uids[numuids]=strtouid(tmpvalues[numuids],&tmp,0);
if ((*(tmpvalues[numuids])=='\0')||(*tmp!='\0'))
{
log_log(LOG_WARNING,"passwd entry %s contains non-numeric %s value",
myldap_get_dn(entry),attmap_passwd_uidNumber);
return 0;
}
+ else if (errno!=0)
+ {
+ log_log(LOG_WARNING,"passwd entry %s contains too large %s value",
+ myldap_get_dn(entry),attmap_passwd_uidNumber);
+ return 0;
+ }
}
}
/* get the gid for this entry */
@@ -355,13 +362,20 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser,
myldap_get_dn(entry),attmap_passwd_gidNumber);
return 0;
}
- gid=(gid_t)strtol(gidbuf,&tmp,0);
+ errno=0;
+ gid=strtogid(gidbuf,&tmp,0);
if ((gidbuf[0]=='\0')||(*tmp!='\0'))
{
log_log(LOG_WARNING,"passwd entry %s contains non-numeric %s value",
myldap_get_dn(entry),attmap_passwd_gidNumber);
return 0;
}
+ else if (errno!=0)
+ {
+ log_log(LOG_WARNING,"passwd entry %s contains too large %s value",
+ myldap_get_dn(entry),attmap_passwd_gidNumber);
+ return 0;
+ }
/* get the gecos for this entry */
attmap_get_value(entry,attmap_passwd_gecos,gecos,sizeof(gecos));
/* get the home directory for this entry */
diff --git a/nslcd/protocol.c b/nslcd/protocol.c
index 3760aa9..10cf166 100644
--- a/nslcd/protocol.c
+++ b/nslcd/protocol.c
@@ -5,7 +5,7 @@
Copyright (C) 1997-2005 Luke Howard
Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2009, 2010 Arthur de Jong
+ Copyright (C) 2006, 2007, 2009, 2010, 2011 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -143,6 +143,7 @@ static int write_protocol(TFILE *fp,MYLDAP_ENTRY *entry,const char *reqname)
log_log(LOG_WARNING,"protocol entry %s contains multiple %s values",
myldap_get_dn(entry),attmap_protocol_ipProtocolNumber);
}
+ errno=0;
proto=(int)strtol(protos[0],&tmp,0);
if ((*(protos[0])=='\0')||(*tmp!='\0'))
{
@@ -150,6 +151,12 @@ static int write_protocol(TFILE *fp,MYLDAP_ENTRY *entry,const char *reqname)
myldap_get_dn(entry),attmap_protocol_ipProtocolNumber);
return 0;
}
+ else if (errno!=0)
+ {
+ log_log(LOG_WARNING,"protocol entry %s contains too large %s value",
+ myldap_get_dn(entry),attmap_protocol_ipProtocolNumber);
+ return 0;
+ }
/* write entry */
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
WRITE_STRING(fp,name);
diff --git a/nslcd/rpc.c b/nslcd/rpc.c
index 4ceb9c0..08d6a2c 100644
--- a/nslcd/rpc.c
+++ b/nslcd/rpc.c
@@ -5,7 +5,7 @@
Copyright (C) 1997-2005 Luke Howard
Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2009, 2010 Arthur de Jong
+ Copyright (C) 2006, 2007, 2009, 2010, 2011 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -144,6 +144,7 @@ static int write_rpc(TFILE *fp,MYLDAP_ENTRY *entry,const char *reqname)
log_log(LOG_WARNING,"rpc entry %s contains multiple %s values",
myldap_get_dn(entry),attmap_rpc_oncRpcNumber);
}
+ errno=0;
number=(int)strtol(numbers[0],&tmp,0);
if ((*(numbers[0])=='\0')||(*tmp!='\0'))
{
@@ -151,6 +152,12 @@ static int write_rpc(TFILE *fp,MYLDAP_ENTRY *entry,const char *reqname)
myldap_get_dn(entry),attmap_rpc_oncRpcNumber);
return 0;
}
+ else if (errno!=0)
+ {
+ log_log(LOG_WARNING,"rpc entry %s contains too large %s value",
+ myldap_get_dn(entry),attmap_rpc_oncRpcNumber);
+ return 0;
+ }
/* write the entry */
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
WRITE_STRING(fp,name);
diff --git a/nslcd/service.c b/nslcd/service.c
index d55647b..be1a10c 100644
--- a/nslcd/service.c
+++ b/nslcd/service.c
@@ -5,7 +5,7 @@
Copyright (C) 1997-2005 Luke Howard
Copyright (C) 2006 West Consulting
- Copyright (C) 2006, 2007, 2009, 2010 Arthur de Jong
+ Copyright (C) 2006, 2007, 2009, 2010, 2011 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -172,6 +172,7 @@ static int write_service(TFILE *fp,MYLDAP_ENTRY *entry,
log_log(LOG_WARNING,"service entry %s contains multiple %s values",
myldap_get_dn(entry),attmap_service_ipServicePort);
}
+ errno=0;
port=(int)strtol(ports[0],&tmp,0);
if ((*(ports[0])=='\0')||(*tmp!='\0'))
{
@@ -179,6 +180,12 @@ static int write_service(TFILE *fp,MYLDAP_ENTRY *entry,
myldap_get_dn(entry),attmap_service_ipServicePort);
return 0;
}
+ else if (errno!=0)
+ {
+ log_log(LOG_WARNING,"service entry %s contains too large %s value",
+ myldap_get_dn(entry),attmap_service_ipServicePort);
+ return 0;
+ }
/* get protocols */
protocols=myldap_get_values(entry,attmap_service_ipServiceProtocol);
if ((protocols==NULL)||(protocols[0]==NULL))
diff --git a/nslcd/shadow.c b/nslcd/shadow.c
index c91165d..1e3f15a 100644
--- a/nslcd/shadow.c
+++ b/nslcd/shadow.c
@@ -128,22 +128,34 @@ static long to_date(const char *date,const char *attr)
return 0; /* error */
strncpy(buffer,date,l);
buffer[l]='\0';
+ errno=0;
value=strtol(date,&tmp,0);
if ((*date=='\0')||(*tmp!='\0'))
{
log_log(LOG_WARNING,"shadow entry contains non-numeric %s value",attr);
return 0;
}
+ else if (errno!=0)
+ {
+ log_log(LOG_WARNING,"shadow entry contains too large %s value",attr);
+ return -1;
+ }
return value/864-134774;
/* note that AD does not have expiry dates but a lastchangeddate
and some value that needs to be added */
}
+ errno=0;
value=strtol(date,&tmp,0);
if ((*date=='\0')||(*tmp!='\0'))
{
log_log(LOG_WARNING,"shadow entry contains non-numeric %s value",attr);
return 0;
}
+ else if (errno!=0)
+ {
+ log_log(LOG_WARNING,"shadow entry contains too large %s value",attr);
+ return -1;
+ }
return value;
}
@@ -155,12 +167,19 @@ static long to_date(const char *date,const char *attr)
tmpvalue=attmap_get_value(entry,attmap_shadow_##att,buffer,sizeof(buffer)); \
if (tmpvalue==NULL) \
tmpvalue=""; \
+ errno=0; \
var=strtol(tmpvalue,&tmp,0); \
if ((*(tmpvalue)=='\0')||(*tmp!='\0')) \
{ \
log_log(LOG_WARNING,"shadow entry %s contains non-numeric %s value", \
myldap_get_dn(entry),attmap_shadow_##att); \
return 0; \
+ } \
+ else if (errno!=0) \
+ { \
+ log_log(LOG_WARNING,"shadow entry %s contains too large %s value", \
+ myldap_get_dn(entry),attmap_shadow_##att); \
+ return 0; \
}
#define GET_OPTIONAL_DATE(var,att) \