From owner-svn-soc-all@FreeBSD.ORG Mon Jul 23 16:05:40 2012 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from socsvn.FreeBSD.org (unknown [IPv6:2001:4f8:fff6::2f]) by hub.freebsd.org (Postfix) with SMTP id CB337106564A for ; Mon, 23 Jul 2012 16:05:38 +0000 (UTC) (envelope-from gpf@FreeBSD.org) Received: by socsvn.FreeBSD.org (sSMTP sendmail emulation); Mon, 23 Jul 2012 16:05:38 +0000 Date: Mon, 23 Jul 2012 16:05:38 +0000 From: gpf@FreeBSD.org To: svn-soc-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <20120723160538.CB337106564A@hub.freebsd.org> Cc: Subject: socsvn commit: r239699 - in soc2012/gpf/pefs_kmod: sbin/pefs sys/fs/pefs X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 23 Jul 2012 16:05:40 -0000 Author: gpf Date: Mon Jul 23 16:05:38 2012 New Revision: 239699 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=239699 Log: minor changes to supplement the last svn commit Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_checksum.c Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c ============================================================================== --- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c Mon Jul 23 15:20:52 2012 (r239698) +++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_checksum.c Mon Jul 23 16:05:38 2012 (r239699) @@ -97,7 +97,10 @@ /* on disk size of a single file header (also a bucket in cuckoo hashing) */ #define PEFS_FH_SIZE 16 -/* this struct is used to check if all hardlinks for a given inode are supplied by the user */ +/* + * This struct is used to check if all hardlinks for a given inode are supplied + * by the user + */ struct hardlink_counter { ino_t inode; /* inode number for the file in question */ uint32_t total_links; /* total hardlinks of the file */ @@ -1428,6 +1431,7 @@ strlcpy(cfhp->hash_algo, algo, sizeof(cfhp->hash_algo)); } +/* generate dsa keys & write public key to a file */ static EVP_PKEY * pefs_generate_dsa(FILE *pkfp) { @@ -1476,6 +1480,7 @@ return (pkey); } +/* Sign .pefs.checksum. Signature is placed in a different file. */ static int pefs_sign_file(int fd, FILE *pkfp, FILE *signfp) { @@ -1487,6 +1492,8 @@ unsigned int sign_len; int bytes, error, rval; + /* XXXgpf: [TODO] offer option of DSA/RSA & appropriate digests */ + /* generate keys */ pkey = pefs_generate_dsa(pkfp); if (pkey == NULL) return (PEFS_ERR_SYS); @@ -1498,6 +1505,7 @@ return (PEFS_ERR_GENERIC); } + /* generate digital signature */ EVP_SignInit(&ctx, md); error = lseek(fd, 0, SEEK_SET); @@ -1537,6 +1545,7 @@ return (PEFS_ERR_SYS); } + /* write digital signature to .pefs.signature */ if (fwrite(sign, sizeof(char), sign_len, signfp) < sign_len) { pefs_warn("error writing signature"); free(sign); @@ -1550,6 +1559,7 @@ return (0); } +/* read dsa pubkey from file */ static EVP_PKEY * pefs_read_dsa(FILE *pk_fp) { @@ -1581,6 +1591,7 @@ return (pkey); } +/* verify digital signature of .pefs.checksum */ static int pefs_verify_signature(int fd, FILE *pk_fp, FILE *sign_fp) { @@ -1592,6 +1603,7 @@ unsigned int sign_len; int bytes, error, rval; + /* read public key from .pefs.pkey */ pkey = pefs_read_dsa(pk_fp); if (pkey == NULL) return (PEFS_ERR_SYS); @@ -1603,6 +1615,7 @@ return (PEFS_ERR_SYS); } + /* read signature from .pefs.signature */ sign_len = fread(sign, sizeof(char), EVP_PKEY_size(pkey), sign_fp); if (ferror(sign_fp)) { pefs_warn("error reading from signature file"); @@ -1617,6 +1630,8 @@ EVP_PKEY_free(pkey); return (PEFS_ERR_GENERIC); } + + /* process .pefs.checksum & verify the signature */ EVP_VerifyInit(&ctx, md); error = lseek(fd, 0, SEEK_SET); @@ -1658,6 +1673,9 @@ return (PEFS_ERR_GENERIC); } + free(sign); + EVP_PKEY_free(pkey); + return (0); } @@ -1730,7 +1748,9 @@ * An in memory database is created from entries in fpin. This database is * later written to file ".pefs.checksum" which is created under csm_path. * algo is used as a cryptographic hash function that produces checksums - * for 4k blocks of each file. + * for 4k blocks of each file. When we are done with .pefs.checksum, we + * sign it and place the signature in .pefs.signature. The public key is placed + * in .pefs.pkey. */ int pefs_create_checksum_file(FILE *fpin, char *fsroot, char *csm_path, @@ -2081,7 +2101,9 @@ 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) + strcmp(sdp->d_name, ".pefs.checksum") == 0 || + strcmp(sdp->d_name, ".pefs.signature") == 0 || + strcmp(sdp->d_name, ".pefs.pkey") == 0) continue; dprintf(("dirent: %s\n", sdp->d_name)); @@ -2232,8 +2254,9 @@ * Verify the contents of a .pefs.checksum file. * A) .pefs.checksum is read into memory. * B) The entire filesystem is traversed in order to check each and every file. - * C) warning messages are produces for hardlinks and symbolic links. + * C) warning messages are produced for hardlinks and symbolic links. * D) check that every file in .pefs.checksum was actually found in filesystem. + * E) verify .pefs.signature from public key found in .pefs.pkey */ int pefs_verify_checksum(int fdin, FILE *pk_fp, FILE *sign_fp, Modified: soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c ============================================================================== --- soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c Mon Jul 23 15:20:52 2012 (r239698) +++ soc2012/gpf/pefs_kmod/sbin/pefs/pefs_ctl.c Mon Jul 23 16:05:38 2012 (r239699) @@ -1021,14 +1021,17 @@ * .pefs.checksum is created under $PWD. path should be a directory, * outside of target pefs filesystem. * + * Alongside .pefs.checksum, two other files are created: .pefs.signature & + * .pefs.pkey. The first one contains the digital signature of .pefs.checksum + * and the other one the public key that is used for signature verification. + * They are created under the same parent directory as .pefs.checksum. + * * -f symbolizes that $command should set immutable flag schg for every file * in inputlist if the flag is not already set. * * When $command is run, filesystem must be mounted with pefs, and * user must have supplied the necessary key(s). * - * [TODO] a flag that allows $command to turn on immutable flags for - * every file that requires integrity checking. */ static int pefs_addchecksum(int argc, char *argv[]) @@ -1045,7 +1048,7 @@ fpin = stdin; /* by default use sha256 */ algo = supported_digests[0]; - /* by default create checksum file under $PWD */ + /* by default create checksum files under $PWD */ snprintf(csm_path, sizeof(csm_path), "./%s", PEFS_FILE_CHECKSUM); snprintf(pk_path, sizeof(pk_path), "./%s", PEFS_FILE_PKEY); snprintf(sign_path, sizeof(sign_path), "./%s", PEFS_FILE_SIGNATURE); @@ -1135,10 +1138,17 @@ * * flags -u and -n are mutually exclusive. * + * pkey_file is the file containing the public key that is used to verify + * .pefs.checksum's signature. + * + * sign_file contains the public signature that is used to verify + * .pefs.checksum's digital signature. + * + * If pkey_file or sign_file are not supplied, $command expects to find the + * respective files under the same parent directory as .pefs.checksum. + * * By default, pefs will assume that filesystem is mounted and user * has provided key. - * - * [TODO] Verify the integrity of the checksum file itself via a signature. */ static int pefs_verify(int argc, char *argv[]) @@ -1150,6 +1160,7 @@ FILE *pk_fp, *sign_fp; int error, fdin, flags, i; + fdin = -1; flags = PEFS_VERIFY; pk_fp = NULL; sign_fp = NULL; @@ -1159,7 +1170,8 @@ pk_fp = fopen(optarg, "r"); if (pk_fp == NULL) { warn("error opening pkey file %s", optarg); - return (PEFS_ERR_SYS); + error = PEFS_ERR_SYS; + goto out; } break; case 'n': @@ -1173,7 +1185,8 @@ sign_fp = fopen(optarg, "r"); if (sign_fp == NULL) { warn("error opening signature file %s", optarg); - return (PEFS_ERR_SYS); + error = PEFS_ERR_SYS; + goto out; } break; case 'u': @@ -1197,11 +1210,11 @@ pefs_usage(); } - /* XXXgpf: [TODO] close files if error */ fdin = open(argv[0], O_RDONLY); if (fdin == -1) { warn("cannot open %s file: %s", PEFS_FILE_CHECKSUM, argv[0]); - return (PEFS_ERR_INVALID); + error = PEFS_ERR_INVALID; + goto out; } dirnamep = dirname(argv[0]); if (pk_fp == NULL) { @@ -1209,7 +1222,8 @@ pk_fp = fopen(pk_path, "r"); if (pk_fp == NULL) { warn("error opening pkey file %s", pk_path); - return (PEFS_ERR_SYS); + error = PEFS_ERR_SYS; + goto out; } } if (sign_fp == NULL) { @@ -1218,7 +1232,8 @@ sign_fp = fopen(sign_path, "r"); if (sign_fp == NULL) { warn("error opening signature file %s", sign_path); - return (PEFS_ERR_SYS); + error = PEFS_ERR_SYS; + goto out; } } @@ -1235,14 +1250,14 @@ strlcpy(fsroot, argv[0], sizeof(fsroot)); if (stat(fsroot, &sb) != 0) { warn("cannot stat fs root: %s", fsroot); - close(fdin); - return (PEFS_ERR_NOENT); + error = PEFS_ERR_NOENT; + goto out; } if (S_ISDIR(sb.st_mode) == 0) { pefs_warn("fs root is not a directory: %s", fsroot); - close(fdin); - return (PEFS_ERR_SYS); + error = PEFS_ERR_SYS; + goto out; } } @@ -1252,9 +1267,13 @@ else pefs_warn("integrity verification encountered error(s)"); - close(fdin); - fclose(pk_fp); - fclose(sign_fp); +out: + if (fdin >= 0) + close(fdin); + if (pk_fp != NULL) + fclose(pk_fp); + if (sign_fp != NULL) + fclose(sign_fp); return (error); } @@ -1286,7 +1305,7 @@ " pefs showchains [-fp] [-i iterations] [-k keyfile] filesystem\n" " pefs showalgs\n" " pefs addchecksum [-f] [-a algo] [-i inputfile] [-p checksumpath] filesystem\n" -" pefs verify [-n/u] [checksumpath filesystem]\n" +" pefs verify [-n/u] [-k pkey_file] [-s sign_file] [checksumpath filesystem]\n" ); exit(PEFS_ERR_USAGE); } Modified: soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_checksum.c ============================================================================== --- soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_checksum.c Mon Jul 23 15:20:52 2012 (r239698) +++ soc2012/gpf/pefs_kmod/sys/fs/pefs/pefs_checksum.c Mon Jul 23 16:05:38 2012 (r239699) @@ -256,7 +256,9 @@ /* XXXgpf: What if user wants integrity checking for .pefs.db or .conf? */ if (strncmp(enc_name, ".pefs.db", enc_name_len) == 0 || strncmp(enc_name, ".pefs.conf", enc_name_len) == 0 || - strncmp(enc_name, ".pefs.checksum", enc_name_len) == 0) + strncmp(enc_name, ".pefs.checksum", enc_name_len) == 0 || + strncmp(enc_name, ".pefs.signature", enc_name_len) == 0 || + strncmp(enc_name, ".pefs.pkey", enc_name_len) == 0) goto not_found; enc_name++;