diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2012-09-20 20:34:03 +0200 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2012-09-20 20:34:03 +0200 |
commit | 6d11c9da714700bfc152f1fe79d88cacada8f571 (patch) | |
tree | 6e616f6efe7581eccee02469afe723316f71c018 | |
parent | 927a27faf2a934e615d58bdccbd265490146b90c (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-- | AUTHORS | 1 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | nslcd/cfg.c | 10 | ||||
-rw-r--r-- | nslcd/common.c | 19 | ||||
-rw-r--r-- | nslcd/common.h | 33 | ||||
-rw-r--r-- | nslcd/group.c | 9 | ||||
-rw-r--r-- | nslcd/passwd.c | 18 | ||||
-rw-r--r-- | nslcd/protocol.c | 9 | ||||
-rw-r--r-- | nslcd/rpc.c | 9 | ||||
-rw-r--r-- | nslcd/service.c | 9 | ||||
-rw-r--r-- | nslcd/shadow.c | 19 |
11 files changed, 130 insertions, 13 deletions
@@ -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) \ |