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