crypt.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }