socsvn commit: r238811 - soc2012/gpf/pefs_kmod/sbin/pefs

gpf at FreeBSD.org gpf at FreeBSD.org
Mon Jul 2 15:23:03 UTC 2012


Author: gpf
Date: Mon Jul  2 15:23:00 2012
New Revision: 238811
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=238811

Log:
  - make pefs verify work for unmounted fs or fs without key
  - use a flags variable in all major functions due to different semantics or
  code that should be used according to whether fs is mounted and has a key
  or not.
  
  code is a little crude at some points and requires comments, more testing
  and handling of a few todos that can be seen in xxx comment headers.
  

Modified:
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h
  soc2012/gpf/pefs_kmod/sbin/pefs/pefs_subr.c

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Mon Jul  2 15:19:56 2012	(r238810)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c	Mon Jul  2 15:23:00 2012	(r238811)
@@ -187,34 +187,43 @@
 
 static int
 pefs_compute_symlink_checksum(struct file_header *fhp, const EVP_MD *md,
-	uint8_t hash_len)
+	uint8_t hash_len, int flags)
 {
 	struct pefs_xslink_ctext xsl;
 	EVP_MD_CTX mdctx;
+	char *buf;
 	int error, i, md_len;
+	size_t buf_len;
 	struct checksum *csp;
 
 	TAILQ_INIT(&(fhp->checksums));
 	fhp->nhashes = 0;
 
-	/* feed parent directory to ioctl() */
-	strlcpy(xsl.pxsl_filename, fhp->filename, sizeof(xsl.pxsl_filename));
-	xsl.pxsl_namelen = strnlen(xsl.pxsl_filename, sizeof(xsl.pxsl_filename));
-
-	error = ioctl(fhp->pfd, PEFS_GETSLINKCTEXT, &xsl);
-	if (error != 0) {
-		pefs_warn("error retrieving symlink's ciphertext of %s", fhp->path);
-		return (PEFS_ERR_IO);
+	if ((flags & PEFS_UNMOUNTED) != 0 || (flags & PEFS_NOKEY) != 0) {
+		buf = fhp->target_path;
+		buf_len = strnlen(fhp->target_path, MAXPATHLEN + 1);
+	}
+	else {
+		/* feed parent directory to ioctl() */
+		strlcpy(xsl.pxsl_filename, fhp->filename, sizeof(xsl.pxsl_filename));
+		xsl.pxsl_namelen = strnlen(xsl.pxsl_filename, sizeof(xsl.pxsl_filename));
+	
+		error = ioctl(fhp->pfd, PEFS_GETSLINKCTEXT, &xsl);
+		if (error != 0) {
+			pefs_warn("error retrieving symlink's ciphertext of %s", fhp->path);
+			return (PEFS_ERR_IO);
+		}
+	
+		dprintf(("read %d bytes from kernel\n\n", xsl.pxsl_slink_len));
+		dprintf(("printing contents of buf:"));
+		for (i=0; i < (int)xsl.pxsl_slink_len; i++) dprintf(("%c", xsl.pxsl_slink[i]));
+		dprintf(("!\n"));
+		buf = xsl.pxsl_slink;
+		buf_len = xsl.pxsl_slink_len;
 	}
-
-	dprintf(("read %d bytes from kernel\n\n", xsl.pxsl_slink_len));
-	dprintf(("printing contents of buf:"));
-	for (i=0; i < (int)xsl.pxsl_slink_len; i++) dprintf(("%c", xsl.pxsl_slink[i]));
-	dprintf(("!\n"));
-
 	EVP_MD_CTX_init(&mdctx);
 	EVP_DigestInit_ex(&mdctx, md, NULL);
-	EVP_DigestUpdate(&mdctx, xsl.pxsl_slink, xsl.pxsl_slink_len);
+	EVP_DigestUpdate(&mdctx, buf, buf_len);
 
 	csp = malloc(sizeof(struct checksum));
 	if (csp == NULL) {
@@ -243,18 +252,22 @@
 
 static int
 pefs_compute_file_checksums(struct file_header *fhp, const EVP_MD *md,
-	uint8_t hash_len)
+	uint8_t hash_len, int flags)
 {
 	struct pefs_xsector_ctext xsct;
+	char sector_buf[PEFS_SECTOR_SIZE];
 	EVP_MD_CTX mdctx;
 	struct stat sb;
-	off_t resid;
+	off_t offset, resid;
+	FILE * fp;
+	char *buf;
 	uint32_t bytes_to_read;
+	size_t buf_len;
 	int error, i, md_len;
 	struct checksum *csp;
 
 	if (fhp->target_path != NULL)
-		return (pefs_compute_symlink_checksum(fhp, md, hash_len));
+		return (pefs_compute_symlink_checksum(fhp, md, hash_len, flags));
 
 	TAILQ_INIT(&(fhp->checksums));
 
@@ -267,34 +280,58 @@
 	resid = sb.st_size;
 	if (resid == 0) {
 		pefs_warn("empty files are not allowed: %s", fhp->path);
-		return (PEFS_ERR_INVALID);
+		return (PEFS_ERR_GENERIC);
+	}
+
+	fp = NULL;
+	if ((flags & PEFS_UNMOUNTED) != 0 || (flags & PEFS_NOKEY) != 0) {
+		fp = fdopen(fhp->fd, "r");
+		if (fp == NULL) {
+			pefs_warn("could not open file for reading: %s", fhp->path);
+			return (PEFS_ERR_IO);
+		}
 	}
 
 	fhp->nhashes = 0;
+	offset = 0;
 	xsct.pxsct_offset = 0;
 	while (resid > 0) {
 		if (resid > PEFS_SECTOR_SIZE)
 			bytes_to_read = PEFS_SECTOR_SIZE;
 		else
 			bytes_to_read = resid;
-
-		resid-=bytes_to_read;
-		xsct.pxsct_ctext_len = bytes_to_read;
-		error = ioctl(fhp->fd, PEFS_GETSECTORCTEXT, &xsct);
-		if (error != 0) {
-			pefs_warn("error retrieving ciphertext of %s", fhp->path);
-			return (PEFS_ERR_IO);
+		
+		if ((flags & PEFS_UNMOUNTED) != 0 || (flags & PEFS_NOKEY) != 0) {
+			fread(sector_buf, bytes_to_read, sizeof(char), fp);
+			if (ferror(fp)) {
+				pefs_warn("error reading from file: %s", fhp->path);
+				return (PEFS_ERR_IO);
+			}
+			buf = sector_buf;
+			buf_len = bytes_to_read;
+			resid-=bytes_to_read;
+		}
+		else {
+			resid-=bytes_to_read;
+			xsct.pxsct_ctext_len = bytes_to_read;
+			error = ioctl(fhp->fd, PEFS_GETSECTORCTEXT, &xsct);
+			if (error != 0) {
+				pefs_warn("error retrieving ciphertext of %s", fhp->path);
+				return (PEFS_ERR_IO);
+			}
+			xsct.pxsct_offset+= xsct.pxsct_ctext_len;
+			buf = xsct.pxsct_ctext;
+			buf_len = xsct.pxsct_ctext_len;
 		}
-		xsct.pxsct_offset+= xsct.pxsct_ctext_len;
 
 		EVP_MD_CTX_init(&mdctx);
 		EVP_DigestInit_ex(&mdctx, md, NULL);
-		EVP_DigestUpdate(&mdctx, xsct.pxsct_ctext, xsct.pxsct_ctext_len);
+		EVP_DigestUpdate(&mdctx, buf, buf_len);
 
-		dprintf(("read %d bytes from kernel\n\n", bytes_to_read));
-		dprintf(("printing contents of buffer:"));
-		for (i=0; i < (int)bytes_to_read; i++) dprintf(("%c", xsct.pxsct_ctext[i]));
-		dprintf(("!\n"));
+		//dprintf(("read %d bytes\n\n", buf_len));
+		//dprintf(("printing contents of buffer:"));
+		//for (i=0; i < (int)buf_len; i++) dprintf(("%c", buf[i]));
+		//dprintf(("!\n"));
 
 		csp = malloc(sizeof(struct checksum));
 		if (csp == NULL) {
@@ -320,6 +357,15 @@
 		fhp->nhashes++;
 	}
 
+	/*
+	 * XXXgpf: [TODO] better move the fp into file_header struct and deal with 
+	 * closing it during pefs_file_close.
+	 */
+	if (fp != NULL) {
+		fclose(fp);
+		fhp->fd = -1;
+	}
+	
 	return (0);
 }
 
@@ -333,11 +379,11 @@
 }
 
 static int
-pefs_allocate_hash_table(struct cuckoo_hash_table *chtp, uint32_t nelements, int flags)
+pefs_allocate_hash_table(struct cuckoo_hash_table *chtp, uint32_t nelements, int alloc_flag)
 {
 	uint32_t i;
 
-	if (flags == PEFS_EXTEND) {
+	if (alloc_flag == PEFS_EXTEND) {
 		/*
 		 * spending 15% more space for each table lowers the chance to fall into an
 		 * infinite loop during cuckoo insertion to about 1.5%.
@@ -349,12 +395,12 @@
 			return (PEFS_ERR_GENERIC);
 		}
 	}
-	else if (flags == PEFS_NOEXTEND) {
+	else if (alloc_flag == PEFS_NOEXTEND) {
 		chtp->size = nelements;
 		chtp->nelements = nelements;
 	}
 	/* reallocate the hash tables in case of infinite loop during cuckoo insert */
-	else if (flags == PEFS_REALLOC) {
+	else if (alloc_flag == PEFS_REALLOC) {
 		chtp->size = pefs_next_prime(chtp->size + 1);
 			if (chtp->size < chtp->nelements) {
 			pefs_warn("numeric overflow while computing new hash table size");
@@ -582,11 +628,40 @@
  * file id used is checksum = VMAC(E(tweak || filename))
  */
 static int
-pefs_get_file_id(struct file_header *fhp)
+pefs_get_file_id(struct file_header *fhp, int flags)
 {
 	struct pefs_xnamecsum xncs;
 	uint64_t temp;
-	int error;
+	char *enc, *buf;
+	int error, r;
+	size_t buf_len, enc_len;
+
+	if ((flags & PEFS_NOKEY) != 0 || (flags & PEFS_UNMOUNTED) != 0) {
+		enc = fhp->filename;
+		enc_len = strnlen(fhp->filename, sizeof(fhp->filename));
+		enc++;
+		enc_len--;
+		buf_len = MAXNAMLEN + 1;
+		buf = malloc(buf_len);
+		if (buf == NULL) {
+			pefs_warn("memory allocation error");
+			return (PEFS_ERR_SYS);
+		}
+
+		r = pefs_name_pton(enc, enc_len, buf, buf_len);
+		if (r <= 0) {
+			pefs_warn("failed to extract file id from encrypted filename: %s", fhp->filename);
+			error = PEFS_ERR_GENERIC;
+		}
+		else {
+			memcpy(&temp, buf, sizeof(temp));
+			fhp->file_id = be64toh(temp);
+			error = 0;
+		}
+
+		free(buf);
+		return (error);
+	}
 
 	strlcpy(xncs.pxnc_filename, fhp->filename, sizeof(xncs.pxnc_filename));
 	xncs.pxnc_namelen = strnlen(xncs.pxnc_filename, sizeof(xncs.pxnc_filename));
@@ -600,7 +675,7 @@
 		fhp->file_id = be64toh(temp);
 	}
 	else
-		pefs_warn("failed to fetch file id from kernel");
+		pefs_warn("failed to fetch file id from kernel for filename: %s", fhp->filename);
 
 	return (error);
 }
@@ -662,7 +737,7 @@
 				continue;
 			}
 
-			error = pefs_get_file_id(&targetfh);
+			error = pefs_get_file_id(&targetfh, 0);
 			if (error == 0) {
 				res = pefs_cuckoo_lookup(chtp, &targetfh);
 				if (res == NULL)
@@ -753,7 +828,7 @@
 }
 
 static int
-pefs_open_semantic_checks(struct file_header *fhp, struct statfs *fsp, struct hardlink_head *hlc_headp)
+pefs_open_semantic_checks(struct file_header *fhp, struct statfs *fsp, struct hardlink_head *hlc_headp, int flags)
 {
 	char dirbuf[MAXPATHLEN + 1], namebuf[MAXNAMLEN + 1];
 	char sbuf[MAXPATHLEN + 1];
@@ -840,9 +915,15 @@
 		 * symlink.
 		 * e.g. a directory
 		 */
-		if (lstat(fhp->target_path, &sb) != 0) {
-			warn("cannot stat symlink's target file %s", fhp->target_path);
-			return (PEFS_ERR_SYS);
+		if ((flags & PEFS_NOKEY) == 0 && (flags & PEFS_UNMOUNTED) == 0) {
+			/*
+			 * If target_path is encrypted due to no key or unmounted fs,
+			 * lstat will always fail.
+			 */
+			if (lstat(fhp->target_path, &sb) != 0) {
+				warn("cannot stat symlink's target file %s", fhp->target_path);
+				return (PEFS_ERR_SYS);
+			}
 		}
 
 		/*
@@ -880,16 +961,18 @@
 		return (PEFS_ERR_INVALID);
 	}
 
-	if (fstatfs(fhp->fd, &this_fs) == -1) {
-		pefs_warn("statfs failed: %s: %s", fhp->path, strerror(errno));
-		return (PEFS_ERR_SYS);
-	}
+	if ((flags & PEFS_UNMOUNTED) == 0) {
+		if (fstatfs(fhp->fd, &this_fs) == -1) {
+			pefs_warn("statfs failed: %s: %s", fhp->path, strerror(errno));
+			return (PEFS_ERR_SYS);
+		}
 
-	if ((fsp->f_fsid.val[0] != this_fs.f_fsid.val[0]) ||
-		(fsp->f_fsid.val[1] != this_fs.f_fsid.val[1])) {
-		pefs_warn("filename: %s does not reside in filesystem %s",
-			fhp->path, fsp->f_mntonname);
-		return (PEFS_ERR_INVALID);
+		if ((fsp->f_fsid.val[0] != this_fs.f_fsid.val[0]) ||
+			(fsp->f_fsid.val[1] != this_fs.f_fsid.val[1])) {
+			pefs_warn("filename: %s does not reside in filesystem %s",
+				fhp->path, fsp->f_mntonname);
+			return (PEFS_ERR_INVALID);
+		}
 	}
 
 	/* Keep all hardlink file headers in a rb tree */
@@ -977,19 +1060,19 @@
 	TAILQ_INIT(&fh_head);
 	RB_INIT(&hlc_head);
 	while((fhp = pefs_next_file(fpin, &error, &nfiles)) != NULL) {
-		error = pefs_open_semantic_checks(fhp, &fs, &hlc_head);
+		error = pefs_open_semantic_checks(fhp, &fs, &hlc_head, 0);
 		if (error != 0) {
 			pefs_close_file(fhp);
 			return (error);
 		}
 
-		error = pefs_get_file_id(fhp);
+		error = pefs_get_file_id(fhp, 0);
 		if (error != 0) {
 			pefs_close_file(fhp);
 			return (error);
 		}
 
-		error = pefs_compute_file_checksums(fhp, md, hash_len);
+		error = pefs_compute_file_checksums(fhp, md, hash_len, 0);
 		if (error != 0) {
 			pefs_close_file(fhp);
 			return (error);
@@ -1602,7 +1685,8 @@
  */
 static int
 pefs_traverse_fs(struct cuckoo_hash_table *chtp, const EVP_MD *md, uint8_t hash_len, DIR *dirp,
-	char *path, struct statfs *fsp, struct hardlink_head *hlc_headp, struct file_header_head *fh_headp)
+	char *path, struct statfs *fsp, struct hardlink_head *hlc_headp, struct file_header_head *fh_headp,
+	int flags)
 {
 	char tmpath[MAXPATHLEN];
 	struct stat sb;
@@ -1614,6 +1698,7 @@
 	while (dirp) {
 		sdp = readdir(dirp);
 		if (sdp != NULL) {
+			/* XXXgpf: Need to pay special attention to these files */
 			if (strcmp(sdp->d_name, "..") == 0 || strcmp(sdp->d_name, ".") == 0 ||
 				strcmp(sdp->d_name, ".pefs.db") == 0 || strcmp(sdp->d_name, ".pefs.conf") == 0 ||
 				strcmp(sdp->d_name, ".pefs.checksum") == 0)
@@ -1629,7 +1714,7 @@
 					closedir(dirp);
 					return (PEFS_ERR_SYS);
 				}
-				error = pefs_traverse_fs(chtp, md, hash_len, dirtmp, tmpath, fsp, hlc_headp, fh_headp);
+				error = pefs_traverse_fs(chtp, md, hash_len, dirtmp, tmpath, fsp, hlc_headp, fh_headp, flags);
 				if (error != 0) {
 					closedir(dirp);
 					return (PEFS_ERR_SYS);
@@ -1652,14 +1737,15 @@
 					return (PEFS_ERR_SYS);
 				}
 				strlcpy(fhp->path, tmpath, sizeof(fhp->path));
-				error = pefs_open_semantic_checks(fhp, fsp, NULL);
+
+				error = pefs_open_semantic_checks(fhp, fsp, NULL, flags);
 				if (error != 0) {
 					closedir(dirp);
 					free(fhp);
 					return (error);
 				}
 
-				error = pefs_get_file_id(fhp);
+				error = pefs_get_file_id(fhp, flags);
 				if (error != 0) {
 					pefs_close_file(fhp);
 					free(fhp);
@@ -1674,13 +1760,14 @@
 				}
 				indexfhp->found = 1;
 
-				error = pefs_compute_file_checksums(fhp, md, hash_len);
+				error = pefs_compute_file_checksums(fhp, md, hash_len, flags);
 				if (error != 0) {
 					pefs_close_file(fhp);
 					free(fhp);
 					return (error);
 				}
 
+				/* get sb for pefs_rb_insert */
 				error = lstat(fhp->path, &sb);
 				if (error != 0) {
 					warn("cannot stat file %s", fhp->path);
@@ -1695,17 +1782,13 @@
 					free(fhp);
 					return (error);
 				}
-
+				
 				/*
-				 * XXXgpf: there's a chance of a false positive here.
-				 * When creating .pefs.checksum we only check if there's a file id
-				 * collision between files that need integrity checking, not against
-				 * the entire filesystem. So there's a possibility we will have a
-				 * false positive in case there are 2 files with the same file id
-				 * now that we traverse the entire fs.
-				 *
-				 * So should exit and treat a checksum comparison as an error?
-				 */
+				 * XXXgpf: [TODO] if error encountered during 
+				 * pefs_compare_cehcksums, then store this information
+				 * but keep on traversing the fs to find other errors
+				 * as well.
+				 */ 
 				error = pefs_compare_checksums(fhp, indexfhp, hash_len);
 				//if (error != 0) {
 					//pefs_close_file(fhp);
@@ -1730,6 +1813,7 @@
 	return (PEFS_ERR_SYS);
 }
 
+/* XXXgpf: probably turn this to int */
 static void
 pefs_found_all_entries(struct cuckoo_hash_table *chtp)
 {
@@ -1757,7 +1841,7 @@
  * XXXgpf: [TODO] comments
  */
 int
-pefs_verify_checksum(int fdin, char *fsroot)
+pefs_verify_checksum(int fdin, char *fsroot, int flags)
 {
 	struct statfs fs;
 	struct checksum_file_header cfh;
@@ -1797,25 +1881,27 @@
 
 	//pefs_print_hash_tables(&cht, hash_len);
 
+	RB_INIT(&hlc_head);
+	TAILQ_INIT(&fh_head);
+
 	dirp = opendir(fsroot);
 	if (dirp == NULL) {
 		pefs_warn("failed to open dir %s", fsroot);
 		return (PEFS_ERR_SYS);
 	}
 
-	RB_INIT(&hlc_head);
-	TAILQ_INIT(&fh_head);
-
-	error = pefs_traverse_fs(&cht, md, hash_len, dirp, fsroot, &fs, &hlc_head, &fh_head);
+	error = pefs_traverse_fs(&cht, md, hash_len, dirp, fsroot, &fs, &hlc_head, &fh_head, flags);
 	if (error != 0)
 		return (error);
 
 	//pefs_rb_print(&hlc_head);
 	pefs_rb_warn(&hlc_head);
-	pefs_symlink_warn(&cht, &fh_head);
+	if ((flags & PEFS_UNMOUNTED) == 0 && (flags & PEFS_NOKEY) == 0)
+		pefs_symlink_warn(&cht, &fh_head);
 	pefs_found_all_entries(&cht);
 
 	/* XXXgpf: [TODO] free mem in the end and when error occurs */
+	/* XXXgpf: [TODO] verify action should also use a signature to verify .pefs.checksum */
 	return (0);
 }
 

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c	Mon Jul  2 15:19:56 2012	(r238810)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c	Mon Jul  2 15:23:00 2012	(r238811)
@@ -1102,7 +1102,7 @@
 /*
  * XXXgpf: Instead of a man page entry:
  *
- * pefs verify checksumpath filesystem
+ * pefs verify [-u/-n] checksumpath filesystem
  *
  * $command ...
  *
@@ -1112,12 +1112,27 @@
 static int
 pefs_verify(int argc, char *argv[])
 {
+	struct stat sb;
 	char fsroot[MAXPATHLEN];
-	int error, fdin, i;
+	int error, fdin, flags, i;
 
-	while ((i = getopt(argc, argv, "a:i:p:")) != -1)
+	flags = 0;
+	while ((i = getopt(argc, argv, "nu")) != -1)
 		switch(i) {
-		/* XXXgpf: Should I add an option to tell if it's a mounted or unmounted fs ? */
+		case 'n':
+			flags|= PEFS_NOKEY;
+			if ((flags & PEFS_UNMOUNTED) != 0) {
+				pefs_warn("flags -u and -n are mutually exclusive");
+				return (PEFS_ERR_INVALID);
+			}
+			break;
+		case 'u':
+			flags|= PEFS_UNMOUNTED;
+			if ((flags & PEFS_NOKEY) != 0) {
+				pefs_warn("flags -u and -n are mutually exclusive");
+				return (PEFS_ERR_INVALID);
+			}
+			break;
 		default:
 			pefs_usage();
 		}
@@ -1140,15 +1155,28 @@
 	argc -=1;
 	argv +=1;
 
-	/* XXXgpf: For now, assume that verify works only with a mounted pefs fs */
-	initfsroot(argc, argv, 0, fsroot, sizeof(fsroot));
+	if ((flags & PEFS_UNMOUNTED) == 0)
+		initfsroot(argc, argv, 0, fsroot, sizeof(fsroot));
+	else {
+		strlcpy(fsroot, argv[0], sizeof(fsroot));
+		if (stat(fsroot, &sb) != 0) {
+			warn("cannot stat fs root: %s", fsroot);
+			return (PEFS_ERR_NOENT);
+		}
 
-	error = pefs_verify_checksum(fdin, fsroot);
+		if (S_ISDIR(sb.st_mode) == 0) {
+			pefs_warn("fs root is not a directory: %s", fsroot);
+			return (PEFS_ERR_SYS);
+		}
+	}
+
+	error = pefs_verify_checksum(fdin, fsroot, flags);
 	if (error == 0)
 		printf("everything's ok!\n");
 
 	close(fdin);
 	return (error);
+
 }
 
 static void
@@ -1177,7 +1205,7 @@
 "	pefs showchains [-fp] [-i iterations] [-k keyfile] filesystem\n"
 "	pefs showalgs\n"
 "	pefs addchecksum [-a algo] [-i inputfile] [-p checksumpath] filesystem\n"
-"	pefs verify [checksumpath filesystem]\n"
+"	pefs verify [-n/u] [checksumpath filesystem]\n"
 );
 	exit(PEFS_ERR_USAGE);
 }

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h	Mon Jul  2 15:19:56 2012	(r238810)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.h	Mon Jul  2 15:23:00 2012	(r238811)
@@ -44,6 +44,9 @@
 #define	PEFS_FILE_KEYCONF		".pefs.conf"
 #define PEFS_FILE_CHECKSUM		".pefs.checksum"
 
+#define PEFS_NOKEY				0x0001
+#define PEFS_UNMOUNTED			0x0002
+
 #define	PEFS_KEYCONF_ALG_IND		0
 #define	PEFS_KEYCONF_ITERATIONS_IND	1
 
@@ -95,7 +98,9 @@
 	    const struct pefs_xkey *xk_parent);
 uintmax_t	pefs_keyid_as_int(char *keyid);
 int pefs_create_checksum_file(FILE *fpin, char *fsroot, char *csm_path, const char *algo);
-int pefs_verify_checksum(int fdin, char *fsroot);
+int pefs_verify_checksum(int fdin, char *fsroot, int flags);
+
+int	pefs_name_pton(char const *src, size_t srclen, u_char *target, size_t targsize);
 
 const char *	pefs_alg_name(struct pefs_xkey *xk);
 void	pefs_alg_list(FILE *stream);

Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_subr.c
==============================================================================
--- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_subr.c	Mon Jul  2 15:19:56 2012	(r238810)
+++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_subr.c	Mon Jul  2 15:23:00 2012	(r238811)
@@ -74,3 +74,72 @@
 	return (0);
 }
 
+#define	Assert(Cond)		(void)0
+
+/*
+ * Algorithm is standard base64 with few exceptions:
+ *  - file system friendly alphabet
+ *  - no paddings and whitespace skip
+ */
+static const char Base64[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_";
+int
+pefs_name_pton(char const *src, size_t srclen, u_char *target, size_t targsize)
+{
+	int tarindex, state, ch;
+	char *pos;
+
+	state = 0;
+	tarindex = 0;
+
+	while ((ch = *src++) != '\0' && srclen-- > 0) {
+		if (target && (size_t)tarindex >= targsize)
+			return (-1);
+
+		pos = strchr(Base64, ch);
+		if (pos == 0)		/* A non-base64 character. */
+			return (-1);
+
+		switch (state) {
+		case 0:
+			if (target) {
+				target[tarindex] = (pos - Base64) << 2;
+			}
+			state = 1;
+			break;
+		case 1:
+			if (target) {
+				target[tarindex]   |=  (pos - Base64) >> 4;
+				if ((size_t)tarindex + 1 < targsize)
+					target[tarindex+1] =
+					    ((pos - Base64) & 0x0f) << 4 ;
+			}
+			tarindex++;
+			state = 2;
+			break;
+		case 2:
+			if (target) {
+				target[tarindex]   |=  (pos - Base64) >> 2;
+				if ((size_t)tarindex + 1 < targsize)
+					target[tarindex+1] =
+					    ((pos - Base64) & 0x03) << 6;
+			}
+			tarindex++;
+			state = 3;
+			break;
+		case 3:
+			if (target) {
+				target[tarindex] |= (pos - Base64);
+			}
+			tarindex++;
+			state = 0;
+			break;
+		default:
+			return (-1);
+		}
+	}
+
+	if (tarindex == 0)
+		return (-1);
+	return (tarindex);
+}


More information about the svn-soc-all mailing list