Browse Source

- cfg.lex: hex & octal numbers are supported now (fifo_mode e.g. 0xab or 0777)
- fifo fixes: check for fifo (normal files will not be allowed for reply
fifo), check for hardlinks (hardlinked fifos will not be allowed),
check for softlink (a softlink to a fifo will not be allowed)
[still missing: * ser fifo dir (e.g. /tmp/.ser)]

Andrei Pelinescu-Onciul 22 years ago
parent
commit
584812784b
3 changed files with 79 additions and 13 deletions
  1. 1 1
      Makefile.defs
  2. 8 1
      cfg.lex
  3. 70 11
      fifo_server.c

+ 1 - 1
Makefile.defs

@@ -43,7 +43,7 @@ export makefile_defs
 VERSION = 0
 PATCHLEVEL = 8
 SUBLEVEL =   12
-EXTRAVERSION = dev-17-cristian
+EXTRAVERSION = dev-18-fifo
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")

+ 8 - 1
cfg.lex

@@ -39,6 +39,7 @@
  *               require_certificate added (andrei)
  *  2003-07-06  more tls config. vars added: tls_method, tls_port_no (andrei)
  *  2003-10-02  added {,set_}advertised_{address,port} (andrei)
+ *  2003-10-07  added hex and octal numbers support (andrei)
  */
 
 
@@ -197,9 +198,11 @@ TLSv1			"tlsv1"|"TLSv1"|"TLSV1"
 LETTER		[a-zA-Z]
 DIGIT		[0-9]
 ALPHANUM	{LETTER}|{DIGIT}|[_]
-NUMBER		{DIGIT}+
+NUMBER		0|([1-9]{DIGIT}*)
 ID			{LETTER}{ALPHANUM}*
 HEX			[0-9a-fA-F]
+HEXNUMBER	0x{HEX}+
+OCTNUMBER	0[0-7]+
 HEX4		{HEX}{1,4}
 IPV6ADDR	({HEX4}":"){7}{HEX4}|({HEX4}":"){1,7}(":"{HEX4}){1,7}|":"(":"{HEX4}){1,7}|({HEX4}":"){1,7}":"|"::"
 QUOTES		\"
@@ -342,6 +345,10 @@ EAT_ABLE	[\ \t\b\r]
 
 <INITIAL>{IPV6ADDR}		{ count(); yylval.strval=yytext; return IPV6ADDR; }
 <INITIAL>{NUMBER}		{ count(); yylval.intval=atoi(yytext);return NUMBER; }
+<INITIAL>{HEXNUMBER}	{ count(); yylval.intval=(int)strtol(yytext, 0, 16);
+							return NUMBER; }
+<INITIAL>{OCTNUMBER}	{ count(); yylval.intval=(int)strtol(yytext, 0, 8);
+							return NUMBER; }
 <INITIAL>{YES}			{ count(); yylval.intval=1; return NUMBER; }
 <INITIAL>{NO}			{ count(); yylval.intval=0; return NUMBER; }
 <INITIAL>{TCP}			{ count(); yylval.intval=PROTO_TCP; return NUMBER; }

+ 70 - 11
fifo_server.c

@@ -56,6 +56,8 @@
  *  2003-03-29  destroy pkg mem introduced (jiri)
  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
  *  2003-01-29  new built-in fifo commands: arg and pwd (jiri)
+ *  2003-10-07  fifo security fixes: permissions, always delete old fifo,
+ *               reply fifo checks -- added fifo_check (andrei)
  */
 
 
@@ -87,8 +89,7 @@
 
 /* FIFO server vars */
 char *fifo=0; /* FIFO name */
-int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP | 
-	S_IWGRP | S_IROTH | S_IWOTH;
+int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ;
 pid_t fifo_pid;
 /* file descriptors */
 static int fifo_read=0;
@@ -299,6 +300,60 @@ static char *trim_filename( char * file )
 	return new_fn;
 }
 
+
+
+/* reply fifo security checks:
+ * checks if fd is a fifo, is not hardlinked and it's not a softlink
+ * opened file descriptor + file name (for soft link check)
+ * returns 0 if ok, <0 if not */
+static int fifo_check(int fd, char* fname)
+{
+	struct stat fst;
+	struct stat lst;
+	
+	if (fstat(fd, &fst)<0){
+		LOG(L_ERR, "ERROR: fifo_check: fstat failed: %s\n",
+				strerror(errno));
+		return -1;
+	}
+	/* check if fifo */
+	if (!S_ISFIFO(fst.st_mode)){
+		LOG(L_ERR, "ERROR: fifo_check: %s is not a fifo\n", fname);
+		return -1;
+	}
+	/* check if hard-linked */
+	if (fst.st_nlink>1){
+		LOG(L_ERR, "ERROR: security: fifo_check: %s is hard-linked %d times\n",
+				fname, fst.st_nlink);
+		return -1;
+	}
+	
+	/* lstat to check for soft links */
+	if (lstat(fname, &lst)<0){
+		LOG(L_ERR, "ERROR: fifo_check: lstat failed: %s\n",
+				strerror(errno));
+		return -1;
+	}
+	if (S_ISLNK(lst.st_mode)){
+		LOG(L_ERR, "ERROR: security: fifo_check: %s is a soft link\n",
+				fname);
+		return -1;
+	}
+	/* if this is not a symbolic link, check to see if the inode didn't
+	 * change to avoid possible sym.link, rm sym.link & replace w/ fifo race
+	 */
+	if ((lst.st_dev!=fst.st_dev)||(lst.st_ino!=fst.st_ino)){
+		LOG(L_ERR, "ERROR: security: fifo_check: inode/dev number differ"
+				": %ld %ld (%s)\n",
+				 fst.st_ino, lst.st_ino, fname);
+		return -1;
+	}
+	/* success */
+	return 0;
+}
+
+
+
 /* tell FIFO client what happened via reply pipe */
 void fifo_reply( char *reply_fifo, char *reply_fmt, ... )
 {
@@ -367,6 +422,10 @@ tryagain:
 			pipe_name, strerror(errno));
 		return 0;
 	}
+	/* security checks: is this really a fifo?, is 
+	 * it hardlinked? is it a soft link? */
+	if (fifo_check(fifofd, pipe_name)<0) goto error;
+	
 	/* we want server blocking for big writes */
 	if ( (flags=fcntl(fifofd, F_GETFL, 0))<0) {
 		LOG(L_ERR, "ERROR: open_reply_pipe (%s): getfl failed: %s\n",
@@ -484,7 +543,15 @@ int open_fifo_server()
 		return 1;
 	}
 	DBG("DBG: open_uac_fifo: opening fifo...\n");
-	if (stat(fifo, &filestat)==-1) { /* FIFO doesn't exist yet ... */
+	if (stat(fifo, &filestat)==0){
+		/* FIFO exist, delete it (safer) */
+		if (unlink(fifo)<0){
+			LOG(L_ERR, "ERROR: open_fifo_server: cannot delete old fifo (%s):"
+					" %s\n", fifo, strerror(errno));
+			return -1;
+		}
+	}
+	 /* create FIFO ... */
 		LOG(L_DBG, "DEBUG: open_fifo_server: FIFO stat failed: %s\n",
 			strerror(errno));
 		if ((mkfifo(fifo, fifo_mode)<0)) {
@@ -500,14 +567,6 @@ int open_fifo_server()
 					strerror(errno), fifo_mode);
 			return -1;
 		}
-	} else { /* file can be stat-ed, check if it is really a FIFO */
-		if (!(S_ISFIFO(filestat.st_mode))) {
-			LOG(L_ERR, "ERROR: open_fifo_server: "
-				"the file is not a FIFO: %s\n",
-				fifo );
-			return -1;
-		}
-	}
 	DBG("DEBUG: fifo %s opened, mode=%d\n", fifo, fifo_mode );
 	time(&up_since);
 	t=ctime(&up_since);