sbase

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

crypt.c (3700B)


      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 		if (!(file = strstr(line, "  "))) {
     53 			(*formatsucks)++;
     54 			continue;
     55 		}
     56 		if ((file - line) / 2 != sz) {
     57 			(*formatsucks)++; /* checksum length mismatch */
     58 			continue;
     59 		}
     60 		*file = '\0';
     61 		file += 2;
     62 		for (p = file; *p && *p != '\n' && *p != '\r'; p++); /* strip newline */
     63 		*p = '\0';
     64 		if ((fd = open(file, O_RDONLY)) < 0) {
     65 			weprintf("open %s:", file);
     66 			(*noread)++;
     67 			continue;
     68 		}
     69 		if (cryptsum(ops, fd, file, md)) {
     70 			(*noread)++;
     71 			continue;
     72 		}
     73 		r = mdcheckline(line, md, sz);
     74 		if (r == 1) {
     75 			printf("%s: OK\n", file);
     76 		} else if (r == 0) {
     77 			printf("%s: FAILED\n", file);
     78 			(*nonmatch)++;
     79 		} else {
     80 			(*formatsucks)++;
     81 		}
     82 		close(fd);
     83 	}
     84 	free(line);
     85 }
     86 
     87 int
     88 cryptcheck(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz)
     89 {
     90 	FILE *fp;
     91 	int formatsucks = 0, noread = 0, nonmatch = 0, ret = 0;
     92 
     93 	if (argc == 0) {
     94 		mdchecklist(stdin, ops, md, sz, &formatsucks, &noread, &nonmatch);
     95 	} else {
     96 		for (; *argv; argc--, argv++) {
     97 			if ((*argv)[0] == '-' && !(*argv)[1]) {
     98 				fp = stdin;
     99 			} else if (!(fp = fopen(*argv, "r"))) {
    100 				weprintf("fopen %s:", *argv);
    101 				ret = 1;
    102 				continue;
    103 			}
    104 			mdchecklist(fp, ops, md, sz, &formatsucks, &noread, &nonmatch);
    105 			if (fp != stdin)
    106 				fclose(fp);
    107 		}
    108 	}
    109 
    110 	if (formatsucks) {
    111 		weprintf("%d lines are improperly formatted\n", formatsucks);
    112 		ret = 1;
    113 	}
    114 	if (noread) {
    115 		weprintf("%d listed file could not be read\n", noread);
    116 		ret = 1;
    117 	}
    118 	if (nonmatch) {
    119 		weprintf("%d computed checksums did NOT match\n", nonmatch);
    120 		ret = 1;
    121 	}
    122 
    123 	return ret;
    124 }
    125 
    126 int
    127 cryptmain(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz)
    128 {
    129 	int fd;
    130 	int ret = 0;
    131 
    132 	if (argc == 0) {
    133 		if (cryptsum(ops, 0, "<stdin>", md))
    134 			ret = 1;
    135 		else
    136 			mdprint(md, "<stdin>", sz);
    137 	} else {
    138 		for (; *argv; argc--, argv++) {
    139 			if ((*argv)[0] == '-' && !(*argv)[1]) {
    140 				*argv = "<stdin>";
    141 				fd = 0;
    142 			} else if ((fd = open(*argv, O_RDONLY)) < 0) {
    143 				weprintf("open %s:", *argv);
    144 				ret = 1;
    145 				continue;
    146 			}
    147 			if (cryptsum(ops, fd, *argv, md))
    148 				ret = 1;
    149 			else
    150 				mdprint(md, *argv, sz);
    151 			if (fd != 0)
    152 				close(fd);
    153 		}
    154 	}
    155 
    156 	return ret;
    157 }
    158 
    159 int
    160 cryptsum(struct crypt_ops *ops, int fd, const char *f, uint8_t *md)
    161 {
    162 	uint8_t buf[BUFSIZ];
    163 	ssize_t n;
    164 
    165 	ops->init(ops->s);
    166 	while ((n = read(fd, buf, sizeof(buf))) > 0)
    167 		ops->update(ops->s, buf, n);
    168 	if (n < 0) {
    169 		weprintf("%s: read error:", f);
    170 		return 1;
    171 	}
    172 	ops->sum(ops->s, md);
    173 	return 0;
    174 }
    175 
    176 void
    177 mdprint(const uint8_t *md, const char *f, size_t len)
    178 {
    179 	size_t i;
    180 
    181 	for (i = 0; i < len; i++)
    182 		printf("%02x", md[i]);
    183 	printf("  %s\n", f);
    184 }