[PATCH] ecryptfs.mount_private.c: check_username, add newlines

This patch adds a check_username() function, that painstakingly compares
each character in a username against a whitelist of acceptable
characters.  Previously, we had only blacklisted commas.  This
implementation is far more comprehensive.

Additionally, this patch adds a newline character at the end of each
fputs() error messages.  (Although puts() adds a newline character,
fputs() does not!)

Signed-off-by: Dustin Kirkland <[EMAIL PROTECTED]>

-- 
:-Dustin

Dustin Kirkland
Ubuntu Server Developer
Canonical, LTD
[EMAIL PROTECTED]
GPG: 1024D/83A61194
diff --git a/src/utils/mount.ecryptfs_private.c b/src/utils/mount.ecryptfs_private.c
index aaaaf14..108fd3f 100644
--- a/src/utils/mount.ecryptfs_private.c
+++ b/src/utils/mount.ecryptfs_private.c
@@ -47,6 +47,38 @@
 #define FSTYPE "ecryptfs"
 
 
+int check_username(char *u) {
+/* We follow the username guidelines used by the adduser program.  Quoting its
+ * error message:
+ *   adduser: To avoid problems, the username should consist only of
+ *   letters, digits, underscores, periods, at signs and dashes, and not start
+ *   with a dash (as defined by IEEE Std 1003.1-2001). For compatibility with 
+ *   Samba machine accounts $ is also supported at the end of the username
+ */
+	int i;
+	char c;
+	int len;
+	len = strlen(u);
+	if (u == NULL || len == 0) {
+		fputs("Username is empty\n", stderr);
+		return 1;
+	}
+	for (i=0; i<len; i++) {
+		c = u[i];
+		if ( 	!(c>='a' && c<='z') && !(c>='A' && c<='Z') &&
+			!(c>='0' && c<='9') && 
+			!(c=='_') && !(c=='.') && !(c=='@') && 
+			!(c=='-' && i!=0) && 
+			!(c=='$' && i==(len-1))
+		) {
+			fputs("Username has unsupported characters\n", stderr);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
 char *fetch_sig(char *pw_dir) {
 /* Read ecryptfs signature from file and validate 
  * Return signature as a string, or NULL on failure
@@ -79,14 +111,14 @@ char *fetch_sig(char *pw_dir) {
 			sig[i] = c;
 			i++;
 		} else {
-			fputs("Invalid hex signature", stderr);
+			fputs("Invalid hex signature\n", stderr);
 			return NULL;
 		}
 	}
 	fclose(fh);
 	/* Check signature length */
 	if (i != KEY_BYTES) {
-		fputs("Invalid hex signature length", stderr);
+		fputs("Invalid hex signature length\n", stderr);
 		return NULL;
 	}
 	sig[KEY_BYTES] = '\0';
@@ -107,23 +139,23 @@ int check_ownerships(int uid, char *dev, char *mnt) {
  */
 	struct stat s;
 	if (stat(dev, &s) != 0) {
-		fputs("Cannot examine encrypted directory", stderr);
+		fputs("Cannot examine encrypted directory\n", stderr);
 		return 1;
 	}
 	if (!S_ISDIR(s.st_mode)) {
-		fputs("Device or mountpoint is not a directory", stderr);
+		fputs("Device or mountpoint is not a directory\n", stderr);
 		return 1;
 	}
 	if (s.st_uid != uid) {
-		fputs("You do not own that encrypted directory", stderr);
+		fputs("You do not own that encrypted directory\n", stderr);
 		return 1;
 	}
 	if (stat(mnt, &s) != 0) {
-		fputs("Cannot examine mount directory", stderr);
+		fputs("Cannot examine mount directory\n", stderr);
 		return 1;
 	}
 	if (s.st_uid != uid) {
-		fputs("You do not own that mount directory", stderr);
+		fputs("You do not own that mount directory\n", stderr);
 		return 1;
 	}
 	return 0;
@@ -277,12 +309,10 @@ int main(int argc, char *argv[]) {
 		return 1;
 	}
 
-	if (strstr(pwd->pw_name, ",") != NULL) {
+	if (check_username(pwd->pw_name) != 0) {
 		/* Must protect against a crafted user=john,suid from entering
 		 * filesystem options
 		 */
-		fputs("A username with a comma cannot perform mounts/unmounts",
-		      stderr);
 		return 1;
 	}
 
@@ -327,7 +357,7 @@ int main(int argc, char *argv[]) {
 	if (mounting == 1) {
 		/* Mounting, so exit if already mounted */
 		if (is_mounted(dev, mnt, sig, mounting) == 1) {
-			fputs("Already mounted", stderr);
+			fputs("Already mounted\n", stderr);
 			return 1;
 		}
 		/* We must maintain our real uid as the user who called this
@@ -352,7 +382,7 @@ int main(int argc, char *argv[]) {
 	} else {
 		/* Unmounting, so exit if not mounted */
 		if (is_mounted(dev, mnt, sig, mounting) == 0) {
-			fputs("Not currently mounted", stderr);
+			fputs("Not currently mounted\n", stderr);
 			return 1;
 		}
 		/* The key is not needed for unmounting, so we set res=0.

Attachment: signature.asc
Description: This is a digitally signed message part

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
eCryptfs-devel mailing list
eCryptfs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel

Reply via email to