From 358c8e8512054ac9b3f956ff5a057d8cd7b84bb4 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Sat, 29 Mar 2003 11:36:23 +0000
Subject: [PATCH] Added lots of pointer argument validation.

---
 src/sbbs3/userdat.c | 189 ++++++++++++++++++++++++++++++++------------
 1 file changed, 139 insertions(+), 50 deletions(-)

diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c
index 2ee280131c..980b6b7a40 100644
--- a/src/sbbs3/userdat.c
+++ b/src/sbbs3/userdat.c
@@ -44,6 +44,8 @@ char* nulstr="";
 
 #define REPLACE_CHARS(str,ch1,ch2)	for(c=0;str[c];c++)	if(str[c]==ch1) str[c]=ch2;
 
+#define VALID_CFG(cfg)	(cfg!=NULL && cfg->size==sizeof(scfg_t))
+
 /****************************************************************************/
 /* Looks for a perfect match amoung all usernames (not deleted users)		*/
 /* Makes dots and underscores synomynous with spaces for comparisions		*/
@@ -57,6 +59,9 @@ uint DLLCALL matchuser(scfg_t* cfg, char *name, BOOL sysop_alias)
 	ulong l,length;
 	FILE *stream;
 
+	if(!VALID_CFG(cfg) || name==NULL)
+		return(0);
+
 	if(sysop_alias &&
 		(!stricmp(name,"SYSOP") || !stricmp(name,"POSTMASTER") || !stricmp(name,cfg->sys_id)))
 		return(1);
@@ -119,6 +124,9 @@ uint DLLCALL lastuser(scfg_t* cfg)
 	char str[256];
 	long length;
 
+	if(!VALID_CFG(cfg))
+		return(0);
+
 	sprintf(str,"%suser/user.dat", cfg->data_dir);
 	if((length=flength(str))>0)
 		return((uint)(length/U_LEN));
@@ -134,6 +142,9 @@ BOOL DLLCALL del_lastuser(scfg_t* cfg)
 	int		file;
 	long	length;
 
+	if(!VALID_CFG(cfg))
+		return(FALSE);
+
 	sprintf(str,"%suser/user.dat", cfg->data_dir);
 	if((file=nopen(str,O_RDWR|O_DENYNONE))==-1)
 		return(FALSE);
@@ -157,7 +168,10 @@ int DLLCALL getuserdat(scfg_t* cfg, user_t *user)
 	char userdat[U_LEN+1],str[U_LEN+1],tmp[64];
 	int i,file;
 
-	if(!user->number) {
+	if(user==NULL)
+		return(-1);
+
+	if(!VALID_CFG(cfg) || user->number<1) {
 		memset(user,0,sizeof(user_t));
 		return(-1); 
 	}
@@ -286,7 +300,8 @@ int DLLCALL getuserdat(scfg_t* cfg, user_t *user)
 		if(user->rest&FLAG('Q'))
 			user->qwk=(QWK_RETCTLA);
 		else
-			user->qwk=(QWK_FILES|QWK_ATTACH|QWK_EMAIL|QWK_DELMAIL); }
+			user->qwk=(QWK_FILES|QWK_ATTACH|QWK_EMAIL|QWK_DELMAIL); 
+	}
 	else
 		user->qwk=ahtoul(str);
 
@@ -316,8 +331,10 @@ int DLLCALL getuserdat(scfg_t* cfg, user_t *user)
 	#endif
 			if(user->misc&AUTOTERM) {			// was useron.misc (01/19/00)
 				user->misc&=~(ANSI|RIP|WIP|HTML);
-				user->misc|=autoterm; }
-		} }
+				user->misc|=autoterm; 
+			}
+		} 
+	}
 #endif
 	return(0);
 }
@@ -332,7 +349,10 @@ int DLLCALL putuserdat(scfg_t* cfg, user_t* user)
     char	userdat[U_LEN],str[MAX_PATH+1];
     node_t	node;
 
-	if(!user->number) 
+	if(user==NULL)
+		return(-1);
+
+	if(!VALID_CFG(cfg) || user->number<1)
 		return(-1); 
 
 	memset(userdat,ETX,U_LEN);
@@ -483,26 +503,33 @@ int DLLCALL putuserdat(scfg_t* cfg, user_t* user)
 /* Returns the username in 'str' that corresponds to the 'usernumber'       */
 /* Called from functions everywhere                                         */
 /****************************************************************************/
-char* DLLCALL username(scfg_t* cfg, int usernumber,char *strin)
+char* DLLCALL username(scfg_t* cfg, int usernumber, char *strin)
 {
     char	str[256];
     int		c;
     int		file;
 
-	if(usernumber<1) {
+	if(strin==NULL)
+		return(NULL);
+
+	if(!VALID_CFG(cfg) || usernumber<1) {
 		strin[0]=0;
-		return(strin); }
+		return(strin); 
+	}
 	sprintf(str,"%suser/name.dat",cfg->data_dir);
 	if(flength(str)<1L) {
 		strin[0]=0;
-		return(strin); }
+		return(strin); 
+	}
 	if((file=nopen(str,O_RDONLY))==-1) {
 		strin[0]=0;
-		return(strin); }
+		return(strin); 
+	}
 	if(filelength(file)<(long)((long)usernumber*(LEN_ALIAS+2))) {
 		close(file);
 		strin[0]=0;
-		return(strin); }
+		return(strin); 
+	}
 	lseek(file,(long)((long)(usernumber-1)*(LEN_ALIAS+2)),SEEK_SET);
 	read(file,strin,LEN_ALIAS);
 	close(file);
@@ -525,7 +552,7 @@ int DLLCALL putusername(scfg_t* cfg, int number, char *name)
 	long length;
 	uint total_users;
 
-	if (number<1) 
+	if(!VALID_CFG(cfg) || name==NULL || number<1) 
 		return(-1);
 
 	sprintf(str,"%suser/name.dat", cfg->data_dir);
@@ -563,8 +590,6 @@ int DLLCALL putusername(scfg_t* cfg, int number, char *name)
 
 /****************************************************************************/
 /* Returns the age derived from the string 'birth' in the format MM/DD/YY	*/
-/* Called from functions statusline, main_sec, xfer_sec, useredit and 		*/
-/* text files																*/
 /****************************************************************************/
 char DLLCALL getage(scfg_t* cfg, char *birth)
 {
@@ -572,6 +597,9 @@ char DLLCALL getage(scfg_t* cfg, char *birth)
 	struct	tm tm;
 	time_t	now;
 
+	if(!VALID_CFG(cfg) || birth==NULL)
+		return(0);
+
 	if(!atoi(birth) || !atoi(birth+3))	/* Invalid */
 		return(0);
 
@@ -588,14 +616,15 @@ char DLLCALL getage(scfg_t* cfg, char *birth)
 		if(((birth[3]&0xf)*10)+(birth[4]&0xf)>tm.tm_mon ||
 			(((birth[3]&0xf)*10)+(birth[4]&0xf)==tm.tm_mon &&
 			((birth[0]&0xf)*10)+(birth[1]&0xf)>tm.tm_mday))
-			age--; }
-	else {							/* MM/DD/YY format */
+			age--; 
+	} else {							/* MM/DD/YY format */
 		if(atoi(birth)>12 || atoi(birth+3)>31)
 			return(0);
 		if(((birth[0]&0xf)*10)+(birth[1]&0xf)>tm.tm_mon ||
 			(((birth[0]&0xf)*10)+(birth[1]&0xf)==tm.tm_mon &&
 			((birth[3]&0xf)*10)+(birth[4]&0xf)>tm.tm_mday))
-			age--; }
+			age--; 
+	}
 	if(age<0)
 		return(0);
 	return(age);
@@ -613,7 +642,8 @@ int DLLCALL getnodedat(scfg_t* cfg, uint number, node_t *node, int* fp)
 	int		count=0;
 	int		file;
 
-	if(!number || number>cfg->sys_nodes)
+	if(!VALID_CFG(cfg) 
+		|| node==NULL || number<1 || number>cfg->sys_nodes)
 		return(-1);
 
 	sprintf(str,"%snode.dab",cfg->ctrl_dir);
@@ -658,7 +688,8 @@ int DLLCALL putnodedat(scfg_t* cfg, uint number, node_t* node, int file)
 	int		wrerr=0;
 	int		attempts;
 
-	if(!number || number>cfg->sys_nodes || file<0) {
+	if(!VALID_CFG(cfg) 
+		|| node==NULL || number<1 || number>cfg->sys_nodes || file<0) {
 		close(file);
 		return(-1);
 	}
@@ -688,6 +719,9 @@ void DLLCALL packchatpass(char *pass, node_t *node)
 	char	bits;
 	int		i,j;
 
+	if(pass==NULL || node==NULL)
+		return;
+
 	node->aux&=~0xff00;		/* clear the password */
 	node->extaux=0L;
 	if((j=strlen(pass))==0) /* there isn't a password */
@@ -713,6 +747,9 @@ char* DLLCALL unpackchatpass(char *pass, node_t* node)
 	char 	bits;
 	int 	i;
 
+	if(pass==NULL || node==NULL)
+		return(NULL);
+
 	pass[0]=(node->aux&0x1f00)>>8;
 	pass[1]=(char)(((node->aux&0xe000)>>13)|((node->extaux&0x3)<<3));
 	bits=2;
@@ -737,6 +774,10 @@ void DLLCALL printnodedat(scfg_t* cfg, uint number, node_t* node)
     int		hour;
 
 	printf("Node %2d: ",number);
+	if(node==NULL) {
+		printf("(null)");
+		return;
+	}
 	switch(node->status) {
 		case NODE_WFC:
 			printf("Waiting for call");
@@ -835,8 +876,9 @@ void DLLCALL printnodedat(scfg_t* cfg, uint number, node_t* node)
 						printf("in multinode chat channel %d",node->aux&0xff);
 						if(node->aux&0x1f00) { /* password */
 							putchar('*');
-							printf(" %s",unpackchatpass(tmp,node)); } }
-					else
+							printf(" %s",unpackchatpass(tmp,node)); 
+						}
+					} else
 						printf("in multinode global chat channel");
 					break;
 				case NODE_PAGE:
@@ -872,15 +914,18 @@ void DLLCALL printnodedat(scfg_t* cfg, uint number, node_t* node)
 						hour=12;
 					else
 						hour=(node->aux/60)-12;
-					strcpy(mer,"pm"); }
-				else {
+					strcpy(mer,"pm"); 
+				} else {
 					if((node->aux/60)==0)    /* 12 midnite */
 						hour=12;
 					else hour=node->aux/60;
-					strcpy(mer,"am"); }
+					strcpy(mer,"am"); 
+				}
 				printf(" ETA %02d:%02d %s"
-					,hour,node->aux-((node->aux/60)*60),mer); }
-			break; }
+					,hour,node->aux-((node->aux/60)*60),mer); 
+			}
+			break; 
+}
 	if(node->misc&(NODE_LOCK|NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG)) {
 		printf(" (");
 		if(node->misc&NODE_AOFF)
@@ -891,7 +936,8 @@ void DLLCALL printnodedat(scfg_t* cfg, uint number, node_t* node)
 			putchar('M');
 		if(node->misc&NODE_POFF)
 			putchar('P');
-		putchar(')'); }
+		putchar(')'); 
+	}
 	if(((node->misc
 		&(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
 		|| node->status==NODE_QUIET)) {
@@ -912,21 +958,25 @@ void DLLCALL printnodedat(scfg_t* cfg, uint number, node_t* node)
 			putchar('D');
 		if(node->misc&NODE_LCHAT)
 			putchar('C');
-		putchar(']'); }
+		putchar(']'); 
+	}
 	if(node->errors)
 		printf(" %d error%c",node->errors, node->errors>1 ? 's' : '\0' );
 	printf("\n");
 }
 
 /****************************************************************************/
-uint DLLCALL userdatdupe(scfg_t* cfg, uint usernumber, uint offset, uint datlen, char *dat
-    ,BOOL del)
+uint DLLCALL userdatdupe(scfg_t* cfg, uint usernumber, uint offset, uint datlen
+						 ,char *dat, BOOL del)
 {
     char	str[MAX_PATH+1];
     uint	i;
 	int		file;
     long	l,length;
 
+	if(!VALID_CFG(cfg) || dat==NULL)
+		return(0);
+
 	truncsp(dat);
 	sprintf(str,"%suser/user.dat", cfg->data_dir);
 	if((file=nopen(str,O_RDONLY|O_DENYNONE))==-1)
@@ -960,12 +1010,15 @@ uint DLLCALL userdatdupe(scfg_t* cfg, uint usernumber, uint offset, uint datlen,
 				getrec(str,0,8,str);
 				if(ahtoul(str)&(DELETED|INACTIVE)) {
 					unlock(file,l,U_LEN);
-					continue; } }
+					continue; 
+				} 
+			}
 			unlock(file,l,U_LEN);
 			close(file);
-			return((l/U_LEN)+1); }
-		else
-			unlock(file,l,U_LEN); }
+			return((l/U_LEN)+1); 
+		} else
+			unlock(file,l,U_LEN); 
+	}
 	close(file);
 	return(0);
 }
@@ -979,6 +1032,9 @@ int DLLCALL putsmsg(scfg_t* cfg, int usernumber, char *strin)
     int file,i;
     node_t node;
 
+	if(!VALID_CFG(cfg) || usernumber<1 || strin==NULL)
+		return(-1);
+
 	sprintf(str,"%smsgs/%4.4u.msg",cfg->data_dir,usernumber);
 	if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
 		return(errno); 
@@ -1013,6 +1069,9 @@ char* DLLCALL getsmsg(scfg_t* cfg, int usernumber)
     long	length;
 	node_t	node;
 
+	if(!VALID_CFG(cfg) || usernumber<1)
+		return(NULL);
+
 	sprintf(str,"%smsgs/%4.4u.msg",cfg->data_dir,usernumber);
 	if(flength(str)<1L)
 		return(NULL);
@@ -1054,6 +1113,9 @@ char* DLLCALL getnmsg(scfg_t* cfg, int node_num)
 	long	length;
 	node_t	node;
 
+	if(!VALID_CFG(cfg) || node_num<1)
+		return(NULL);
+
 	getnodedat(cfg,node_num,&node,&file);
 	node.misc&=~NODE_NMSG;          /* clear the NMSG flag */
 	putnodedat(cfg,node_num,&node,file);
@@ -1093,6 +1155,9 @@ int DLLCALL putnmsg(scfg_t* cfg, int num, char *strin)
     int file,i;
     node_t node;
 
+	if(!VALID_CFG(cfg) || num<1 || strin==NULL)
+		return(-1);
+
 	sprintf(str,"%smsgs/n%3.3u.msg",cfg->data_dir,num);
 	if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
 		return(errno); 
@@ -1133,15 +1198,18 @@ static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user)
 
 		if((**ptrptr)==AR_OR) {
 			or=1;
-			(*ptrptr)++; }
+			(*ptrptr)++; 
+		}
 		
 		if((**ptrptr)==AR_NOT) {
 			not=1;
-			(*ptrptr)++; }
+			(*ptrptr)++; 
+		}
 
 		if((**ptrptr)==AR_EQUAL) {
 			equal=1;
-			(*ptrptr)++; }
+			(*ptrptr)++; 
+		}
 
 		if((result && or) || (!result && !or))
 			break;
@@ -1156,7 +1224,8 @@ static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user)
 				(*ptrptr)++;
 			if(!(**ptrptr))
 				break;
-			continue; }
+			continue; 
+		}
 
 		artype=(**ptrptr);
 		switch(artype) {
@@ -1172,7 +1241,8 @@ static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user)
 				break;
 			default:
 				(*ptrptr)++;
-				break; }
+				break; 
+		}
 
 		n=(**ptrptr);
 		i=(*(short *)*ptrptr);
@@ -1464,6 +1534,8 @@ BOOL DLLCALL chk_ar(scfg_t* cfg, uchar *ar, user_t* user)
 
 	if(ar==NULL)
 		return(TRUE);
+	if(!VALID_CFG(cfg) || user==NULL)
+		return(FALSE);
 	p=ar;
 	return(ar_exp(cfg,&p,user));
 }
@@ -1477,7 +1549,7 @@ int DLLCALL getuserrec(scfg_t* cfg, int usernumber,int start, int length, char *
 	char	path[256];
 	int		i,c,file;
 
-	if(!usernumber)
+	if(!VALID_CFG(cfg) || usernumber<1 || str==NULL)
 		return(-1);
 	sprintf(path,"%suser/user.dat",cfg->data_dir);
 	if((file=nopen(path,O_RDONLY|O_DENYNONE))==-1) 
@@ -1531,7 +1603,7 @@ int DLLCALL putuserrec(scfg_t* cfg, int usernumber,int start, uint length, char
 	uint	c,i;
 	node_t	node;
 
-	if(usernumber<1)
+	if(!VALID_CFG(cfg) || usernumber<1 || str==NULL)
 		return(-1);
 
 	sprintf(str2,"%suser/user.dat",cfg->data_dir);
@@ -1596,12 +1668,12 @@ ulong DLLCALL adjustuserrec(scfg_t* cfg, int usernumber, int start, int length,
 	long val;
 	node_t node;
 
-	if(usernumber<1) 
-		return(0UL); 
+	if(!VALID_CFG(cfg) || usernumber<1) 
+		return(0); 
 
 	sprintf(path,"%suser/user.dat",cfg->data_dir);
 	if((file=nopen(path,O_RDWR|O_DENYNONE))==-1)
-		return(0UL); 
+		return(0); 
 
 	if(filelength(file)<((long)usernumber-1)*U_LEN) {
 		close(file);
@@ -1629,14 +1701,14 @@ ulong DLLCALL adjustuserrec(scfg_t* cfg, int usernumber, int start, int length,
 	if(read(file,str,length)!=length) {
 		unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
 		close(file);
-		return(0UL); 
+		return(0); 
 	}
 	for(c=0;c<length;c++)
 		if(str[c]==ETX || str[c]==CR) break;
 	str[c]=0;
 	val=atol(str);
 	if(adj<0L && val<-adj)		/* don't go negative */
-		val=0UL;
+		val=0;
 	else val+=adj;
 	lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
 	putrec(str,0,length,ultoa(val,tmp,10));
@@ -1671,18 +1743,20 @@ void DLLCALL subtract_cdt(scfg_t* cfg, user_t* user, long amt)
 	char tmp[64];
     long mod;
 
-	if(!amt)
+	if(!amt || user==NULL)
 		return;
 	if(user->freecdt) {
 		if((ulong)amt>user->freecdt) {      /* subtract both credits and */
 			mod=amt-user->freecdt;   /* free credits */
 			putuserrec(cfg, user->number,U_FREECDT,10,"0");
 			user->freecdt=0;
-			user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-mod); }
-		else {                          /* subtract just free credits */
+			user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-mod); 
+		} else {                          /* subtract just free credits */
 			user->freecdt-=amt;
 			putuserrec(cfg, user->number,U_FREECDT,10
-				,ultoa(user->freecdt,tmp,10)); } }
+				,ultoa(user->freecdt,tmp,10)); 
+		} 
+	}
 	else    /* no free credits */
 		user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-amt);
 }
@@ -1694,6 +1768,9 @@ BOOL DLLCALL logoutuserdat(scfg_t* cfg, user_t* user, time_t now, time_t logonti
 	char str[128];
 	struct tm tm, tm_now;
 
+	if(user==NULL)
+		return(FALSE);
+
 	user->tlast=(now-logontime)/60;
 
 	putuserrec(cfg,user->number,U_LASTON,8,ultoa(now,str,16));
@@ -1721,6 +1798,9 @@ void DLLCALL resetdailyuserdat(scfg_t* cfg, user_t* user)
 {
 	char str[128];
 
+	if(!VALID_CFG(cfg) || user==NULL)
+		return;
+
 	/* logons today */
 	user->ltoday=0;	
 	putuserrec(cfg,user->number,U_LTODAY,5,"0");
@@ -1748,6 +1828,9 @@ char* DLLCALL usermailaddr(scfg_t* cfg, char* addr, char* name)
 {
 	int i;
 
+	if(!VALID_CFG(cfg) || addr==NULL || name==NULL)
+		return(NULL);
+
 	if(strchr(name,'@')!=NULL) { /* Avoid double-@ */
 		strcpy(addr,name);
 		return(addr);
@@ -1778,6 +1861,9 @@ char* DLLCALL alias(scfg_t* cfg, char* name, char* buf)
 	size_t	cmplen;
 	FILE*	fp;
 
+	if(!VALID_CFG(cfg) || name==NULL || buf==NULL)
+		return(NULL);
+
 	p=name;
 
 	sprintf(fname,"%salias.cfg",cfg->ctrl_dir);
@@ -1844,6 +1930,9 @@ int DLLCALL newuserdat(scfg_t* cfg, user_t* user)
 	FILE*	stream;
 	stats_t	stats;
 
+	if(!VALID_CFG(cfg) || user==NULL)
+		return(-1);
+
 	sprintf(str,"%suser/name.dat",cfg->data_dir);
 	if(fexist(str)) {
 		if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
-- 
GitLab