Browse code

- fifo security checks backported from unstable - minor cfg.y cleanup (eliminates some reduce/reduce conflicts)

Andrei Pelinescu-Onciul authored on 16/10/2003 18:32:55
Showing 6 changed files
... ...
@@ -40,7 +40,7 @@ export makefile_defs
40 40
 VERSION = 0
41 41
 PATCHLEVEL = 8
42 42
 SUBLEVEL =   11
43
-EXTRAVERSION = 
43
+EXTRAVERSION = -r1
44 44
 
45 45
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
46 46
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
... ...
@@ -150,6 +150,7 @@ MEMLOG	memlog
150 150
 SIP_WARNING sip_warning
151 151
 FIFO fifo
152 152
 FIFO_MODE fifo_mode
153
+FIFO_DIR  fifo_dir
153 154
 SERVER_SIGNATURE server_signature
154 155
 REPLY_TO_VIA reply_to_via
155 156
 USER		"user"|"uid"
... ...
@@ -280,6 +281,7 @@ EAT_ABLE	[\ \t\b\r]
280 281
 <INITIAL>{DISABLE_TCP}	{ count(); yylval.strval=yytext; return DISABLE_TCP; }
281 282
 <INITIAL>{TCP_CHILDREN}	{ count(); yylval.strval=yytext; return TCP_CHILDREN; }
282 283
 <INITIAL>{FIFO}	{ count(); yylval.strval=yytext; return FIFO; }
284
+<INITIAL>{FIFO_DIR}    { count(); yylval.strval=yytext; return FIFO_DIR; }
283 285
 <INITIAL>{FIFO_MODE}	{ count(); yylval.strval=yytext; return FIFO_MODE; }
284 286
 <INITIAL>{SERVER_SIGNATURE}	{ count(); yylval.strval=yytext; return SERVER_SIGNATURE; }
285 287
 <INITIAL>{REPLY_TO_VIA}	{ count(); yylval.strval=yytext; return REPLY_TO_VIA; }
... ...
@@ -160,6 +160,7 @@ int rt;  /* Type of route block for find_export */
160 160
 %token MEMLOG
161 161
 %token SIP_WARNING
162 162
 %token FIFO
163
+%token FIFO_DIR
163 164
 %token FIFO_MODE
164 165
 %token SERVER_SIGNATURE
165 166
 %token REPLY_TO_VIA
... ...
@@ -254,14 +255,6 @@ listen_id:	ip			{	tmp=ip_addr2a($1);
254 255
 								}
255 256
 							}
256 257
 						}
257
-		 |	ID			{	$$=pkg_malloc(strlen($1)+1);
258
-		 					if ($$==0){
259
-									LOG(L_CRIT, "ERROR: cfg. parser: out of "
260
-											"memory.\n");
261
-							}else{
262
-									strncpy($$, $1, strlen($1)+1);
263
-							}
264
-						}
265 258
 		 |	STRING			{	$$=pkg_malloc(strlen($1)+1);
266 259
 		 					if ($$==0){
267 260
 									LOG(L_CRIT, "ERROR: cfg. parser: out of "
... ...
@@ -334,6 +327,8 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
334 327
 		| SIP_WARNING EQUAL error { yyerror("boolean value expected"); }
335 328
 		| FIFO EQUAL STRING { fifo=$3; }
336 329
 		| FIFO EQUAL error { yyerror("string value expected"); }
330
+		| FIFO_DIR EQUAL STRING { fifo_dir=$3; }
331
+		| FIFO_DIR EQUAL error { yyerror("string value expected"); }
337 332
 		| FIFO_MODE EQUAL NUMBER { fifo_mode=$3; }
338 333
 		| FIFO_MODE EQUAL error { yyerror("int value expected"); }
339 334
 		| USER EQUAL STRING     { user=$3; }
... ...
@@ -141,8 +141,7 @@
141 141
 /* buffer dimensions for FIFO server */
142 142
 #define MAX_CONSUME_BUFFER 1024
143 143
 /* where reply pipes may be opened */
144
-#define FIFO_DIR "/tmp/"
145
-#define FIFO_DIR_LEN 5
144
+#define DEFAULT_FIFO_DIR "/tmp/"
146 145
 /* max length of the text of fifo 'print' command */
147 146
 #define MAX_PRINT_TEXT 256
148 147
 
... ...
@@ -56,6 +56,9 @@
56 56
  *  2003-03-29  destroy pkg mem introduced (jiri)
57 57
  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
58 58
  *  2003-01-29  new built-in fifo commands: arg and pwd (jiri)
59
+ *  2003-10-07  fifo security fixes: permissions, always delete old fifo,
60
+ *               reply fifo checks -- added fifo_check (andrei)
61
+ *  2003-10-13  addef fifo_dir for reply fifos (andrei)
59 62
  */
60 63
 
61 64
 
... ...
@@ -87,8 +90,8 @@
87 90
 
88 91
 /* FIFO server vars */
89 92
 char *fifo=0; /* FIFO name */
90
-int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP | 
91
-	S_IWGRP | S_IROTH | S_IWOTH;
93
+char* fifo_dir=DEFAULT_FIFO_DIR; /* dir where reply fifos are allowed */
94
+int fifo_mode=S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ;
92 95
 pid_t fifo_pid;
93 96
 /* file descriptors */
94 97
 static int fifo_read=0;
... ...
@@ -285,20 +288,74 @@ static char *trim_filename( char * file )
285 288
 			, file);
286 289
 		return 0;
287 290
 	}
288
-	prefix_len=strlen(FIFO_DIR); fn_len=strlen(file);
291
+	prefix_len=strlen(fifo_dir); fn_len=strlen(file);
289 292
 	new_fn=pkg_malloc(prefix_len+fn_len+1);
290 293
 	if (new_fn==0) {
291 294
 		LOG(L_ERR, "ERROR: trim_filename: no mem\n");
292 295
 		return 0;
293 296
 	}
294 297
 
295
-	memcpy(new_fn, FIFO_DIR, prefix_len);
298
+	memcpy(new_fn, fifo_dir, prefix_len);
296 299
 	memcpy(new_fn+prefix_len, file, fn_len );
297 300
 	new_fn[prefix_len+fn_len]=0;
298 301
 
299 302
 	return new_fn;
300 303
 }
301 304
 
305
+
306
+
307
+/* reply fifo security checks:
308
+ * checks if fd is a fifo, is not hardlinked and it's not a softlink
309
+ * opened file descriptor + file name (for soft link check)
310
+ * returns 0 if ok, <0 if not */
311
+static int fifo_check(int fd, char* fname)
312
+{
313
+	struct stat fst;
314
+	struct stat lst;
315
+	
316
+	if (fstat(fd, &fst)<0){
317
+		LOG(L_ERR, "ERROR: fifo_check: fstat failed: %s\n",
318
+				strerror(errno));
319
+		return -1;
320
+	}
321
+	/* check if fifo */
322
+	if (!S_ISFIFO(fst.st_mode)){
323
+		LOG(L_ERR, "ERROR: fifo_check: %s is not a fifo\n", fname);
324
+		return -1;
325
+	}
326
+	/* check if hard-linked */
327
+	if (fst.st_nlink>1){
328
+		LOG(L_ERR, "ERROR: security: fifo_check: %s is hard-linked %d times\n",
329
+				fname, fst.st_nlink);
330
+		return -1;
331
+	}
332
+	
333
+	/* lstat to check for soft links */
334
+	if (lstat(fname, &lst)<0){
335
+		LOG(L_ERR, "ERROR: fifo_check: lstat failed: %s\n",
336
+				strerror(errno));
337
+		return -1;
338
+	}
339
+	if (S_ISLNK(lst.st_mode)){
340
+		LOG(L_ERR, "ERROR: security: fifo_check: %s is a soft link\n",
341
+				fname);
342
+		return -1;
343
+	}
344
+	/* if this is not a symbolic link, check to see if the inode didn't
345
+	 * change to avoid possible sym.link, rm sym.link & replace w/ fifo race
346
+	 */
347
+	if ((lst.st_dev!=fst.st_dev)||(lst.st_ino!=fst.st_ino)){
348
+		LOG(L_ERR, "ERROR: security: fifo_check: inode/dev number differ"
349
+				": %ld %ld (%s)\n",
350
+				 fst.st_ino, lst.st_ino, fname);
351
+		return -1;
352
+	}
353
+	/* success */
354
+	return 0;
355
+}
356
+
357
+
358
+
302 359
 /* tell FIFO client what happened via reply pipe */
303 360
 void fifo_reply( char *reply_fifo, char *reply_fmt, ... )
304 361
 {
... ...
@@ -367,6 +424,10 @@ tryagain:
367 424
 			pipe_name, strerror(errno));
368 425
 		return 0;
369 426
 	}
427
+	/* security checks: is this really a fifo?, is 
428
+	 * it hardlinked? is it a soft link? */
429
+	if (fifo_check(fifofd, pipe_name)<0) goto error;
430
+	
370 431
 	/* we want server blocking for big writes */
371 432
 	if ( (flags=fcntl(fifofd, F_GETFL, 0))<0) {
372 433
 		LOG(L_ERR, "ERROR: open_reply_pipe (%s): getfl failed: %s\n",
... ...
@@ -484,7 +545,15 @@ int open_fifo_server()
484 545
 		return 1;
485 546
 	}
486 547
 	DBG("DBG: open_uac_fifo: opening fifo...\n");
487
-	if (stat(fifo, &filestat)==-1) { /* FIFO doesn't exist yet ... */
548
+	if (stat(fifo, &filestat)==0){
549
+		/* FIFO exist, delete it (safer) */
550
+		if (unlink(fifo)<0){
551
+			LOG(L_ERR, "ERROR: open_fifo_server: cannot delete old fifo (%s):"
552
+					" %s\n", fifo, strerror(errno));
553
+			return -1;
554
+		}
555
+	}
556
+	 /* create FIFO ... */
488 557
 		LOG(L_DBG, "DEBUG: open_fifo_server: FIFO stat failed: %s\n",
489 558
 			strerror(errno));
490 559
 		if ((mkfifo(fifo, fifo_mode)<0)) {
... ...
@@ -500,14 +569,6 @@ int open_fifo_server()
500 569
 					strerror(errno), fifo_mode);
501 570
 			return -1;
502 571
 		}
503
-	} else { /* file can be stat-ed, check if it is really a FIFO */
504
-		if (!(S_ISFIFO(filestat.st_mode))) {
505
-			LOG(L_ERR, "ERROR: open_fifo_server: "
506
-				"the file is not a FIFO: %s\n",
507
-				fifo );
508
-			return -1;
509
-		}
510
-	}
511 572
 	DBG("DEBUG: fifo %s opened, mode=%d\n", fifo, fifo_mode );
512 573
 	time(&up_since);
513 574
 	t=ctime(&up_since);
... ...
@@ -95,6 +95,7 @@ extern unsigned int shm_mem_size;
95 95
 /* FIFO server config */
96 96
 char extern *fifo; /* FIFO name */
97 97
 extern int fifo_mode;
98
+char extern *fifo_dir; /* dir. where  reply fifos are allowed */
98 99
 
99 100
 /* moved to pt.h
100 101
 extern int *pids;