sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | LICENSE

crypt.c (3857B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <fcntl.h>
      3 #include <stdint.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <unistd.h>
      8 
      9 #include "../crypt.h"
     10 #include "../text.h"
     11 #include "../util.h"
     12 
     13 static int
     14 hexdec(int c)
     15 {
     16 	if (c >= '0' && c <= '9')
     17 		return c - '0';
     18 	else if (c >= 'A' && c <= 'F')
     19 		return c - 'A' + 10;
     20 	else if (c >= 'a' && c <= 'f')
     21 		return c - 'a' + 10;
     22 	return -1; /* unknown character */
     23 }
     24 
     25 static int
     26 mdcheckline(const char *s, uint8_t *md, size_t sz)
     27 {
     28 	size_t i;
     29 	int b1, b2;
     30 
     31 	for (i = 0; i < sz; i++) {
     32 		if (!*s || (b1 = hexdec(*s++)) < 0)
     33 			return -1; /* invalid format */
     34 		if (!*s || (b2 = hexdec(*s++)) < 0)
     35 			return -1; /* invalid format */
     36 		if ((uint8_t)((b1 << 4) | b2) != md[i])
     37 			return 0; /* value mismatch */
     38 	}
     39 	return (i == sz) ? 1 : 0;
     40 }
     41 
     42 static void
     43 mdchecklist(FILE *listfp, struct crypt_ops *ops, uint8_t *md, size_t sz,
     44             int *formatsucks, int *noread, int *nonmatch)
     45 {
     46 	int fd;
     47 	size_t bufsiz = 0;
     48 	int r;
     49 	char *line = NULL, *file, *p;
     50 
     51 	while (getline(&line, &bufsiz, listfp) > 0) {
     52 		file = strchr(line, ' ');
     53 		if (file == NULL || (file[1] != ' ' && file[1] != '*')) {
     54 			(*formatsucks)++;
     55 			continue;
     56 		}
     57 		if (file - line != sz * 2) {
     58 			(*formatsucks)++; /* checksum length mismatch */
     59 			continue;
     60 		}
     61 		*file = '\0';
     62 		file += 2;
     63 		for (p = file; *p && *p != '\n' && *p != '\r'; p++); /* strip newline */
     64 		*p = '\0';
     65 		if ((fd = open(file, O_RDONLY)) < 0) {
     66 			weprintf("open %s:", file);
     67 			(*noread)++;
     68 			continue;
     69 		}
     70 		if (cryptsum(ops, fd, file, md)) {
     71 			(*noread)++;
     72 			continue;
     73 		}
     74 		r = mdcheckline(line, md, sz);
     75 		if (r == 1) {
     76 			printf("%s: OK\n", file);
     77 		} else if (r == 0) {
     78 			printf("%s: FAILED\n", file);
     79 			(*nonmatch)++;
     80 		} else {
     81 			(*formatsucks)++;
     82 		}
     83 		close(fd);
     84 	}
     85 	free(line);
     86 }
     87 
     88 int
     89 cryptcheck(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz)
     90 {
     91 	FILE *fp;
     92 	int formatsucks = 0, noread = 0, nonmatch = 0, ret = 0;
     93 
     94 	if (argc == 0) {
     95 		mdchecklist(stdin, ops, md, sz, &formatsucks, &noread, &nonmatch);
     96 	} else {
     97 		for (; *argv; argc--, argv++) {
     98 			if ((*argv)[0] == '-' && !(*argv)[1]) {
     99 				fp = stdin;
    100 			} else if (!(fp = fopen(*argv, "r"))) {
    101 				weprintf("fopen %s:", *argv);
    102 				ret = 1;
    103 				continue;
    104 			}
    105 			mdchecklist(fp, ops, md, sz, &formatsucks, &noread, &nonmatch);
    106 			if (fp != stdin)
    107 				fclose(fp);
    108 		}
    109 	}
    110 
    111 	if (formatsucks) {
    112 		weprintf("%d improperly formatted line%s\n",
    113 		         formatsucks, formatsucks > 1 ? "s" : "");
    114 		ret = 1;
    115 	}
    116 	if (noread) {
    117 		weprintf("%d listed file%s could not be read\n",
    118 		         noread, noread > 1 ? "s" : "");
    119 		ret = 1;
    120 	}
    121 	if (nonmatch) {
    122 		weprintf("%d computed checksum%s did NOT match\n",
    123 		         nonmatch, nonmatch > 1 ? "s" : "");
    124 		ret = 1;
    125 	}
    126 
    127 	return ret;
    128 }
    129 
    130 int
    131 cryptmain(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz)
    132 {
    133 	int fd;
    134 	int ret = 0;
    135 
    136 	if (argc == 0) {
    137 		if (cryptsum(ops, 0, "<stdin>", md))
    138 			ret = 1;
    139 		else
    140 			mdprint(md, "<stdin>", sz);
    141 	} else {
    142 		for (; *argv; argc--, argv++) {
    143 			if ((*argv)[0] == '-' && !(*argv)[1]) {
    144 				*argv = "<stdin>";
    145 				fd = 0;
    146 			} else if ((fd = open(*argv, O_RDONLY)) < 0) {
    147 				weprintf("open %s:", *argv);
    148 				ret = 1;
    149 				continue;
    150 			}
    151 			if (cryptsum(ops, fd, *argv, md))
    152 				ret = 1;
    153 			else
    154 				mdprint(md, *argv, sz);
    155 			if (fd != 0)
    156 				close(fd);
    157 		}
    158 	}
    159 
    160 	return ret;
    161 }
    162 
    163 int
    164 cryptsum(struct crypt_ops *ops, int fd, const char *f, uint8_t *md)
    165 {
    166 	uint8_t buf[BUFSIZ];
    167 	ssize_t n;
    168 
    169 	ops->init(ops->s);
    170 	while ((n = read(fd, buf, sizeof(buf))) > 0)
    171 		ops->update(ops->s, buf, n);
    172 	if (n < 0) {
    173 		weprintf("%s: read error:", f);
    174 		return 1;
    175 	}
    176 	ops->sum(ops->s, md);
    177 	return 0;
    178 }
    179 
    180 void
    181 mdprint(const uint8_t *md, const char *f, size_t len)
    182 {
    183 	size_t i;
    184 
    185 	for (i = 0; i < len; i++)
    186 		printf("%02x", md[i]);
    187 	printf("  %s\n", f);
    188 }