From db932574059069ddb8b3fe2b8c06ca854fff7342 Mon Sep 17 00:00:00 2001 From: Arthur de Jong Date: Sat, 27 Aug 2011 20:57:18 +0000 Subject: check errno after calls to strtol() to ensure that numbers that are too large for type will be reported (thanks Jakub Hrozek) git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@1523 ef36b2f9-881f-0410-afb5-c4e39611909c --- nslcd/cfg.c | 6 ++++-- nslcd/group.c | 7 +++++++ nslcd/passwd.c | 21 +++++++++++++++++++++ nslcd/protocol.c | 9 ++++++++- nslcd/rpc.c | 9 ++++++++- nslcd/service.c | 9 ++++++++- nslcd/shadow.c | 19 +++++++++++++++++++ 7 files changed, 75 insertions(+), 5 deletions(-) diff --git a/nslcd/cfg.c b/nslcd/cfg.c index 1b8a31d..5c249c5 100644 --- a/nslcd/cfg.c +++ b/nslcd/cfg.c @@ -430,8 +430,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 */ + errno=0; *var=(uid_t)strtol(token,&tmp,0); - if ((*token!='\0')&&(*tmp=='\0')) + if ((*token!='\0')&&(*tmp=='\0')&&(errno==0)) return; /* find by name */ pwent=getpwnam(token); @@ -455,8 +456,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 */ + errno=0; *var=(gid_t)strtol(token,&tmp,0); - if ((*token!='\0')&&(*tmp=='\0')) + if ((*token!='\0')&&(*tmp=='\0')&&(errno==0)) return; /* find by name */ grent=getgrnam(token); diff --git a/nslcd/group.c b/nslcd/group.c index 4274842..7ee22e8 100644 --- a/nslcd/group.c +++ b/nslcd/group.c @@ -280,6 +280,7 @@ static int write_group(TFILE *fp,MYLDAP_ENTRY *entry,const char *reqname, gids[numgids]=(gid_t)binsid2id(gidvalues[numgids]); else { + errno=0; gids[numgids]=(gid_t)strtol(gidvalues[numgids],&tmp,0); if ((*(gidvalues[numgids])=='\0')||(*tmp!='\0')) { @@ -287,6 +288,12 @@ static int write_group(TFILE *fp,MYLDAP_ENTRY *entry,const char *reqname, 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; + } } } } diff --git a/nslcd/passwd.c b/nslcd/passwd.c index 035d0e8..d20531d 100644 --- a/nslcd/passwd.c +++ b/nslcd/passwd.c @@ -194,6 +194,7 @@ static int entry_has_valid_uid(MYLDAP_ENTRY *entry) uid=(uid_t)binsid2id(values[i]); else { + errno=0; uid=(uid_t)strtol(values[i],&tmp,0); if ((*(values[i])=='\0')||(*tmp!='\0')) { @@ -201,6 +202,12 @@ static int entry_has_valid_uid(MYLDAP_ENTRY *entry) myldap_get_dn(entry),attmap_passwd_uidNumber); continue; } + else if (errno!=0) + { + log_log(LOG_WARNING,"passwd entry %s contains too large %s value", + myldap_get_dn(entry),attmap_passwd_uidNumber); + continue; + } } if (uid>=nslcd_cfg->ldc_nss_min_uid) return 1; @@ -481,6 +488,7 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser, uids[numuids]=(uid_t)binsid2id(tmpvalues[numuids]); else { + errno=0; uids[numuids]=(uid_t)strtol(tmpvalues[numuids],&tmp,0); if ((*(tmpvalues[numuids])=='\0')||(*tmp!='\0')) { @@ -488,6 +496,12 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser, 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; + } } } } @@ -512,6 +526,7 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser, myldap_get_dn(entry),attmap_passwd_gidNumber); return 0; } + errno=0; gid=(gid_t)strtol(gidbuf,&tmp,0); if ((gidbuf[0]=='\0')||(*tmp!='\0')) { @@ -519,6 +534,12 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser, 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)); diff --git a/nslcd/protocol.c b/nslcd/protocol.c index ae6fd8e..520f69d 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 25f2fb9..ae79a90 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 3c487f7..4a43022 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 5d6dae7..61d9019 100644 --- a/nslcd/shadow.c +++ b/nslcd/shadow.c @@ -129,22 +129,34 @@ static long to_date(const char *date,const char *attr) return -1; /* 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 -1; } + 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 -1; } + else if (errno!=0) + { + log_log(LOG_WARNING,"shadow entry contains too large %s value",attr); + return -1; + } return value; } @@ -156,12 +168,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); \ var=fallback; \ + } \ + else if (errno!=0) \ + { \ + log_log(LOG_WARNING,"shadow entry %s contains too large %s value", \ + myldap_get_dn(entry),attmap_shadow_##att); \ + var=fallback; \ } void get_shadow_properties(MYLDAP_ENTRY *entry,long *lastchangedate, -- cgit v1.2.3