645f93a
diff --exclude-from=exclude -N -u -r nsalibselinux/include/selinux/selinux.h libselinux-1.30.15/include/selinux/selinux.h
645f93a
--- nsalibselinux/include/selinux/selinux.h	2006-06-16 15:08:24.000000000 -0400
d8849af
+++ libselinux-1.30.15/include/selinux/selinux.h	2006-06-21 15:26:36.000000000 -0400
d8849af
@@ -429,8 +429,19 @@
645f93a
    Caller must free the returned strings via free. */
645f93a
 extern int getseuserbyname(const char *linuxuser, char **seuser, char **level);
8f927c4
 
d8849af
+/* This function compares two file context, ignoring the user component */
d8849af
+int selinux_file_context_cmp(const security_context_t a, const security_context_t b);
645f93a
+
645f93a
+/* This function looks at the file context on disk and compares it to the 
d8849af
+system defaults, it returns 0 on match non 0 on failure */
d8849af
+int selinux_file_context_verify(const char *path, mode_t mode);
f3cb9dc
+
645f93a
+/* This function sets the file context on to the system defaults returns 0 on success */
645f93a
+int selinux_lsetfilecon_default(const char *path);
645f93a
+
645f93a
 #ifdef __cplusplus
8389437
 }
645f93a
 #endif
8f927c4
 
645f93a
 #endif
8f927c4
+
645f93a
diff --exclude-from=exclude -N -u -r nsalibselinux/man/man8/matchpathcon.8 libselinux-1.30.15/man/man8/matchpathcon.8
645f93a
--- nsalibselinux/man/man8/matchpathcon.8	2006-05-15 09:43:24.000000000 -0400
d8849af
+++ libselinux-1.30.15/man/man8/matchpathcon.8	2006-06-21 15:26:36.000000000 -0400
645f93a
@@ -3,13 +3,25 @@
645f93a
 matchpathcon \- get the default security context for the specified path from the file contexts configuration.
8f927c4
 
645f93a
 .SH "SYNOPSIS"
645f93a
-.B matchpathcon [-n] filepath...
645f93a
-
645f93a
+.B matchpathcon [-V] [-N] [-n] [-f file_contexts_file ] [-p prefix ] filepath...
645f93a
 .SH "DESCRIPTION"
645f93a
 .B matchpathcon
645f93a
 Prints the file path and the default security context associated with it.
645f93a
+.SH OPTIONS
645f93a
+.B \-n
645f93a
+Do not display path.
645f93a
+.br
645f93a
+.B \-N
645f93a
+Do not use translations.
645f93a
+.br
645f93a
+.B \-f file_context_file
645f93a
+Use alternate file_context file
645f93a
+.br
645f93a
+.B \-p prefix
645f93a
+Use prefix to speed translations
645f93a
 .br
645f93a
-If the -n option is given, do not display path.
645f93a
+.B \-V
645f93a
+Verify file context on disk matches defaults
8f927c4
 
645f93a
 .SH AUTHOR	
645f93a
 This manual page was written by Dan Walsh <dwalsh@redhat.com>.
645f93a
diff --exclude-from=exclude -N -u -r nsalibselinux/src/matchpathcon.c libselinux-1.30.15/src/matchpathcon.c
645f93a
--- nsalibselinux/src/matchpathcon.c	2006-05-18 12:11:17.000000000 -0400
d8849af
+++ libselinux-1.30.15/src/matchpathcon.c	2006-06-21 15:37:18.000000000 -0400
d8849af
@@ -20,10 +20,12 @@
f4b45dd
 #endif
f4b45dd
 default_printf(const char *fmt, ...) 
f4b45dd
 {
f4b45dd
+#ifdef DEBUG
f4b45dd
 	va_list ap;
f4b45dd
 	va_start(ap, fmt);
f4b45dd
 	vfprintf(stderr, fmt, ap);
645f93a
 	va_end(ap);
f4b45dd
+#endif
8389437
 }
645f93a
 
645f93a
 static void 
d8849af
@@ -50,7 +52,7 @@
645f93a
 static int default_canoncon(const char *path, unsigned lineno, char **context)
645f93a
 {
645f93a
 	char *tmpcon;
645f93a
-	if (security_canonicalize_context(*context, &tmpcon) < 0) {
d8849af
+	if (security_canonicalize_context_raw(*context, &tmpcon) < 0) {
645f93a
 		if (errno == ENOENT)
645f93a
 			return 0;
645f93a
 		if (lineno)
d8849af
@@ -74,7 +76,7 @@
645f93a
 		mycanoncon = &default_canoncon;
8389437
 }
8f927c4
 
645f93a
-static unsigned int myflags;
d8849af
+static __thread unsigned int myflags;
d8849af
 
645f93a
 void set_matchpathcon_flags(unsigned int flags)
645f93a
 {
d8849af
@@ -552,21 +554,6 @@
645f93a
 		
d8849af
 	skip_type:
d8849af
 		if (strcmp(context, "<<none>>")) {
d8849af
-			char *tmpcon = NULL;
d8849af
-
d8849af
-			if (myflags & MATCHPATHCON_NOTRANS)
d8849af
-				goto skip_trans;
645f93a
-
d8849af
-			if (selinux_raw_to_trans_context(context, &tmpcon)) {
d8849af
-				myprintf("%s: line %u has invalid "
d8849af
-					 "context %s\n",
d8849af
-					 path, lineno, context);
d8849af
-				return 0;
d8849af
-			}
d8849af
-			free(context);
d8849af
-			context = tmpcon;
d8849af
-
d8849af
-skip_trans:
d8849af
 			if (myflags & MATCHPATHCON_VALIDATE) {
d8849af
 				if (myinvalidcon) {
d8849af
 					/* Old-style validation of context. */
d8849af
@@ -831,7 +818,12 @@
d8849af
 		spec_arr[i].context_valid = 1;
d8849af
 	}
d8849af
 
d8849af
-	*con = strdup(spec_arr[i].context);
d8849af
+	if (myflags & MATCHPATHCON_NOTRANS) {
d8849af
+		*con = strdup(spec_arr[i].context);
d8849af
+	} else {
d8849af
+		if (selinux_raw_to_trans_context(spec_arr[i].context, con)) 
d8849af
+			return -1;
d8849af
+	}
d8849af
 	if (!(*con))
d8849af
 		return -1;
8f927c4
 
d8849af
@@ -877,3 +869,72 @@
645f93a
 		}
645f93a
 	}
645f93a
 }
645f93a
+
645f93a
+/* Compare two contexts to see if their differences are "significant",
645f93a
+ * or whether the only difference is in the user. */
d8849af
+int selinux_file_context_cmp(const security_context_t a, const security_context_t b)
645f93a
+{
645f93a
+	char *rest_a, *rest_b; /* Rest of the context after the user */
645f93a
+	if (!a && !b) return 0;
645f93a
+	if (!a && b) return -1;
645f93a
+	if (a && !b) return 1;
645f93a
+	rest_a = strchr((char *)a, ':');
645f93a
+	rest_b = strchr((char *)b, ':');
645f93a
+	if (!rest_a && !rest_b) return 0;
645f93a
+	if (!rest_a && rest_b) return -1;
645f93a
+	if (rest_a && !rest_b) return 1;
645f93a
+	return  strcmp(rest_a, rest_b);
8389437
+}
f3cb9dc
+
d8849af
+int selinux_file_context_verify(const char *path, mode_t mode)
645f93a
+{
645f93a
+ 	security_context_t con = NULL;
645f93a
+ 	security_context_t fcontext = NULL;
d8849af
+	unsigned int localflags=myflags;
645f93a
+	int rc=0;
f3cb9dc
+
d8849af
+	rc = lgetfilecon_raw(path, &con);
645f93a
+	if (rc == -1) {
645f93a
+		if (errno != ENOTSUP)
645f93a
+			return 1;
645f93a
+	        else
645f93a
+			return 0;
645f93a
+	}
c923175
+
d8849af
+	set_matchpathcon_flags(myflags | MATCHPATHCON_NOTRANS);
645f93a
+	if (matchpathcon(path,mode,&fcontext) != 0)  {
d8849af
+		if (errno != ENOENT) 
645f93a
+			rc = 1;
645f93a
+		else
645f93a
+			rc = 0;
645f93a
+	} 
645f93a
+	else 
d8849af
+		rc = (selinux_file_context_cmp(fcontext, con) == 0);
d8849af
+	set_matchpathcon_flags(localflags);
645f93a
+	freecon(con);
645f93a
+	freecon(fcontext); 
645f93a
+	return rc;
645f93a
+}
c923175
+
c923175
+
645f93a
+int selinux_lsetfilecon_default(const char *path) {
645f93a
+	struct stat st;
645f93a
+	int rc = -1;
645f93a
+	security_context_t scontext=NULL;
645f93a
+	unsigned int localflags=myflags;
645f93a
+	if (lstat(path, &st) != 0)
645f93a
+		return rc;
645f93a
+
645f93a
+	set_matchpathcon_flags(myflags | MATCHPATHCON_NOTRANS);
645f93a
+
645f93a
+	/* If there's an error determining the context, or it has none, 
645f93a
+	   return to allow default context */
645f93a
+	if (matchpathcon(path, st.st_mode, &scontext)) {
d8849af
+		if (errno == ENOENT) rc = 0;
645f93a
+	} else 	{
645f93a
+		rc = lsetfilecon_raw(path, scontext);
645f93a
+		freecon(scontext);
645f93a
+	}
645f93a
+	set_matchpathcon_flags(localflags);
645f93a
+	return rc;
645f93a
+}
645f93a
diff --exclude-from=exclude -N -u -r nsalibselinux/utils/matchpathcon.c libselinux-1.30.15/utils/matchpathcon.c
645f93a
--- nsalibselinux/utils/matchpathcon.c	2006-05-18 12:11:17.000000000 -0400
d8849af
+++ libselinux-1.30.15/utils/matchpathcon.c	2006-06-21 15:26:36.000000000 -0400
2d9b36b
@@ -12,19 +12,44 @@
645f93a
 	exit(1);
645f93a
 }
c923175
 
645f93a
+int printmatchpathcon(char *path, int header) {
645f93a
+	char *buf;
645f93a
+	int rc = matchpathcon(path, 0, &buf;;
645f93a
+	if (rc < 0) {
2d9b36b
+		fprintf(stderr, "matchpathcon(%s) failed: %s\n", path, strerror(errno));
2d9b36b
+		return 1;
c923175
+	}
645f93a
+	if (header)
645f93a
+		printf("%s\t%s\n", path, buf);
645f93a
+	else
645f93a
+		printf("%s\n", buf);
645f93a
+	
645f93a
+	freecon(buf);
645f93a
+	return 0;
645f93a
+}
c923175
+
645f93a
 int main(int argc, char **argv) 
645f93a
 {
645f93a
-	char *buf;
645f93a
-	int rc, i, init = 0;
645f93a
+	int i, init = 0;
645f93a
 	int header=1, opt;
645f93a
+	int verify=0;
645f93a
+	int notrans=0;
2d9b36b
+	int error=0;
645f93a
 
645f93a
 	if (argc < 2) usage(argv[0]);
645f93a
 
645f93a
-	while ((opt = getopt(argc, argv, "nf:p:")) > 0) {
645f93a
+	while ((opt = getopt(argc, argv, "Nnf:p:V")) > 0) {
645f93a
 		switch (opt) {
645f93a
 		case 'n':
645f93a
 			header=0;
645f93a
 			break;
645f93a
+		case 'V':
645f93a
+			verify=1;
645f93a
+			break;
645f93a
+		case 'N':
645f93a
+			notrans=1;
645f93a
+			set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
645f93a
+			break;
645f93a
 		case 'f':
645f93a
 			if (init) {
645f93a
 				fprintf(stderr, "%s:  -f and -p are exclusive\n", argv[0]);
2d9b36b
@@ -54,18 +79,30 @@
645f93a
 		}
645f93a
 	}
645f93a
 	for (i = optind; i < argc; i++) {
645f93a
-		rc = matchpathcon(argv[i], 0, &buf;;
645f93a
-		if (rc < 0) {
645f93a
-			fprintf(stderr, "%s:  matchpathcon(%s) failed\n", argv[0], argv[i]);
645f93a
-			return 2;
645f93a
-		}
645f93a
-		if (header)
645f93a
-			printf("%s\t%s\n", argv[i], buf);
645f93a
-		else
645f93a
-			printf("%s\n", buf);
645f93a
+		if (verify) {
d8849af
+			if (selinux_file_context_verify(argv[i], 0)) {
645f93a
+				printf("%s verified.\n", argv[i]);
645f93a
+			} else {
645f93a
+				security_context_t con;
645f93a
+				int rc;
645f93a
+				if (notrans) 
645f93a
+					rc = lgetfilecon_raw(argv[i], &con);
645f93a
+				else
645f93a
+					rc = lgetfilecon(argv[i], &con);
645f93a
 
645f93a
-		freecon(buf);
645f93a
+				if (rc >= 0) {
645f93a
+					printf("%s has context %s, should be ", argv[i], con);
2d9b36b
+					error += printmatchpathcon(argv[i], 0);
645f93a
+					freecon(con);
645f93a
+				} else {
645f93a
+					printf("actual context unknown: %s, should be ", strerror(errno));
2d9b36b
+					error += printmatchpathcon(argv[i], 0);
645f93a
+				}
645f93a
+			}
645f93a
+		} else {
2d9b36b
+			error += printmatchpathcon(argv[i], header);
645f93a
+		}
645f93a
 	}
645f93a
 	matchpathcon_fini();
2d9b36b
-	return 0;
2d9b36b
+	return error;
2d9b36b
 }