X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/ba6e6b64033b1f9de49feccb5c9cd438354481f7..0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a:/cc-enc.c diff --git a/cc-enc.c b/cc-enc.c deleted file mode 100644 index 2b8b0fd..0000000 --- a/cc-enc.c +++ /dev/null @@ -1,530 +0,0 @@ -/* -*-c-*- - * - * $Id$ - * - * Catcrypt data encoding - * - * (c) 2004 Straylight/Edgeware - */ - -/*----- Licensing notice --------------------------------------------------* - * - * This file is part of Catacomb. - * - * Catacomb is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * Catacomb is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with Catacomb; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - */ - -/*----- Header files ------------------------------------------------------*/ - -#define _FILE_OFFSET_BITS 64 - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "cc.h" - -typedef int encbdryp(const char *, void *); - -/*----- Main code ---------------------------------------------------------*/ - -/* --- Binary --- */ - -static enc *bin_encinit(FILE *fp, const char *msg) - { enc *e = CREATE(enc); return (e); } -static enc *bin_decinit(FILE *fp, encbdryp *func, void *p) - { enc *e = CREATE(enc); return (e); } - -static int bin_read(enc *e, void *p, size_t sz) -{ - size_t n; - - if (!sz) return (0); - n = fread(p, 1, sz, e->fp); - if (!n || ferror(e->fp)) return (-1); - return (n); -} - -static int bin_write(enc *e, const void *p, size_t sz) - { if (sz && fwrite(p, 1, sz, e->fp) < sz) return (-1); return (0); } - -static int bin_done(enc *e) { return (0); } - -static void bin_destroy(enc *e) { DESTROY(e); } - -/* --- PEM --- */ - -typedef struct pem_encctx { - enc e; - char *msg; - unsigned f; - base64_ctx b; - dstr d; - size_t n; -#define PEMF_NL 1u -#define PEMF_EOF 2u -} pem_encctx; - -static enc *pem_encinit(FILE *fp, const char *msg) -{ - pem_encctx *pe = CREATE(pem_encctx); - base64_init(&pe->b); - fprintf(fp, "-----BEGIN %s-----\n", msg); - pe->msg = xstrdup(msg); - dstr_create(&pe->d); - pe->n = 0; - pe->f = 0; - return (&pe->e); -} - -int checkbdry(const char *b, void *p) { return (!p || strcmp(b, p) == 0); } - -static enc *pem_decinit(FILE *fp, encbdryp *func, void *p) -{ - char buf[128]; - int i, d; - pem_encctx *pe; - int ch; - - /* --- Go until I find a newline and `-----' --- */ - -top: - d = 0; - for (;;) { - if ((ch = getc(fp)) == EOF) goto fail; - switch (ch) { - case '\n': d = 0; break; - case '-': if (d >= 0) { d++; if (d == 5) goto banner; }; break; - default: d = -1; break; - } - } - - /* --- See what the banner looks like --- */ - -banner: - i = d = 0; - for (;;) { - if ((ch = getc(fp)) == EOF) goto fail; - if (ch == '-') { d++; continue; } - if (ch == '\n') break; - if (i + d + 1 >= sizeof(buf)) goto top; - while (d) { buf[i++] = '-'; d--; } - buf[i++] = ch; - } - buf[i] = 0; - - /* --- Check we have the right framing --- */ - - if (d != 5) goto top; - if (strncmp(buf, "BEGIN ", 6) != 0 || (func && !func(buf + 6, p))) - goto top; - - /* --- Ready --- */ - - pe = CREATE(pem_encctx); - base64_init(&pe->b); - pe->msg = xstrdup(buf + 6); - dstr_create(&pe->d); - pe->n = 0; - pe->f = PEMF_NL; - return (&pe->e); - - /* --- Failed --- */ - -fail: - die(EXIT_FAILURE, "initial encapsulation boundary not found"); - return (0); -} - -#define PEM_CHUNKSZ 4096 - -static int pem_read(enc *e, void *p, size_t sz) -{ - pem_encctx *pe = (pem_encctx *)e; - char buf[PEM_CHUNKSZ]; - char *pp = p; - int ch; - size_t n; - int rc = 0; - - for (;;) { - n = pe->d.len - pe->n; - if (n > sz) n = sz; - memcpy(pp, pe->d.buf + pe->n, n); - pe->n += n; - pp += n; - rc += n; - sz -= n; - if (!sz) break; - if (pe->f & PEMF_EOF) return (rc ? rc : -1); - dstr_reset(&pe->d); - n = 0; - for (;;) { - if ((ch = getc(pe->e.fp)) == EOF) return (-1); - if ((pe->f & PEMF_NL) && ch == '-') { - ungetc(ch, pe->e.fp); - pe->f |= PEMF_EOF; - break; - } - if (ch == '\n') { pe->f |= PEMF_NL; continue; } - pe->f &= ~PEMF_NL; - buf[n++] = ch; - if (n >= PEM_CHUNKSZ) break; - } - if (n) - base64_decode(&pe->b, buf, n, &pe->d); - if (pe->f & PEMF_EOF) - base64_decode(&pe->b, 0, 0, &pe->d); - pe->n = 0; - } - return (rc); -} - -static int pem_write(enc *e, const void *p, size_t sz) -{ - pem_encctx *pe = (pem_encctx *)e; - const char *pp = p; - size_t n; - - while (sz) { - n = PEM_CHUNKSZ; - if (n > sz) n = sz; - dstr_reset(&pe->d); - base64_encode(&pe->b, pp, n, &pe->d); - if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len) - return (-1); - pp += n; - sz -= n; - } - return (0); -} - -static int pem_encdone(enc *e) -{ - pem_encctx *pe = (pem_encctx *)e; - dstr_reset(&pe->d); - base64_encode(&pe->b, 0, 0, &pe->d); - if (fwrite(pe->d.buf, 1, pe->d.len, pe->e.fp) < pe->d.len) - return (-1); - if (pe->b.lnlen) fputc('\n', pe->e.fp); - fprintf(pe->e.fp, "-----END %s-----\n", pe->msg); - return (0); -} - -static int pem_decdone(enc *e) -{ - pem_encctx *pe = (pem_encctx *)e; - char buf[128]; - int i, d; - int ch; - - for (d = 0; d < 5; d++) - if ((ch = getc(pe->e.fp)) != '-') goto fail; - i = d = 0; - for (;;) { - if ((ch = getc(pe->e.fp)) == EOF) goto fail; - if (ch == '-') { d++; continue; } - if (ch == '\n') break; - if (i + d + 1 >= sizeof(buf)) goto fail; - while (d) { buf[i++] = '-'; d--; } - buf[i++] = ch; - } - if (d != 5) goto fail; - buf[i] = 0; - if (strncmp(buf, "END ", 4) != 0 || strcmp(buf + 4, pe->msg) != 0) - goto fail; - return (0); - -fail: - die(EXIT_FAILURE, "final encapsulation boundary not found"); - return (-1); -} - -static void pem_destroy(enc *e) -{ - pem_encctx *pe = (pem_encctx *)e; - dstr_destroy(&pe->d); - xfree(pe->msg); - DESTROY(pe); -} - -/* --- Encoder table --- */ - -const encops enctab[] = { - { "binary", "rb", "wb", 1, 1, - bin_encinit, bin_decinit, - bin_read, bin_write, - bin_done, bin_done, - bin_destroy }, - { "pem", "r", "w", 3, 4, - pem_encinit, pem_decinit, - pem_read, pem_write, - pem_encdone, pem_decdone, - pem_destroy }, - { 0 } -}; - -/* --- @getenc@ --- * - * - * Arguments: @const char *enc@ = name of wanted encoding - * - * Returns: Pointer to encoder operations. - * - * Use: Finds a named encoder or decoder. - */ - -const encops *getenc(const char *enc) -{ - const encops *eo; - - for (eo = enctab; eo->name; eo++) { - if (strcmp(eo->name, enc) == 0) - goto e_found; - } - die(EXIT_FAILURE, "couldn't find encoding `%s'", enc); -e_found: - return (eo); -} - -/* --- @initenc@ --- * - * - * Arguments: @const encops *eo@ = operations (from @getenc@) - * @FILE *fp@ = file handle to attach - * @const char *msg@ = banner message - * - * Returns: The encoder object. - * - * Use: Initializes an encoder. - */ - -enc *initenc(const encops *eo, FILE *fp, const char *msg) -{ - enc *e = eo->initenc(fp, msg); - e->ops = eo; - e->fp = fp; - return (e); -} - -/* --- @initdec@ --- * - * - * Arguments: @const encops *eo@ = operations (from @getenc@) - * @FILE *fp@ = file handle to attach - * @int (*func)(const char *, void *)@ = banner check function - * @void *p@ = argument for @func@ - * - * Returns: The encoder object. - * - * Use: Initializes an encoder. - */ - -enc *initdec(const encops *eo, FILE *fp, - int (*func)(const char *, void *), void *p) -{ - enc *e = eo->initdec(fp, func, p); - e->ops = eo; - e->fp = fp; - return (e); -} - -/* --- @freeenc@ --- * - * - * Arguments: @enc *e@ = encoder object - * - * Returns: --- - * - * Use: Frees an encoder object. - */ - -void freeenc(enc *e) { e->ops->destroy(e); } - -/*----- Encoding and decoding commands ------------------------------------*/ - -int cmd_encode(int argc, char *argv[]) -{ - const char *fn, *of = 0; - FILE *ofp = 0; - FILE *fp = 0; - const char *ef = "binary"; - const char *bd = "MESSAGE"; - fprogress ff; - int i; - size_t n; - char buf[4096]; - unsigned f = 0; - const encops *eo; - enc *e; - -#define f_bogus 1u -#define f_progress 2u - - for (;;) { - static const struct option opt[] = { - { "format", OPTF_ARGREQ, 0, 'f' }, - { "boundary", OPTF_ARGREQ, 0, 'b' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'f': ef = optarg; break; - case 'b': bd = optarg; break; - case 'o': of = optarg; break; - case 'p': f |= f_progress; break; - default: f |= f_bogus; break; - } - } - if (argc - optind > 1 || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: encode [-OPTIONS] [FILE]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - fn = optind < argc ? argv[optind++] : "-"; - if (strcmp(fn, "-") == 0) - fp = stdin; - else if ((fp = fopen(fn, "rb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - fn, strerror(errno)); - } - - if (!of || strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, eo->wmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - - e = initenc(eo, ofp, bd); - - if (f & f_progress) { - if (fprogress_init(&ff, fn, fp)) { - die(EXIT_FAILURE, "failed to initialize progress display: %s", - strerror(errno)); - } - } - - do { - n = fread(buf, 1, sizeof(buf), fp); - if (f & f_progress) fprogress_update(&ff, n); - if (e->ops->write(e, buf, n)) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - } - } while (n == sizeof(buf)); - if (f & f_progress) fprogress_done(&ff); - e->ops->encdone(e); - freeenc(e); - return (0); - -#undef f_bogus -#undef f_progress -} - -int cmd_decode(int argc, char *argv[]) -{ - const char *fn, *of = 0; - FILE *ofp = 0; - FILE *fp = 0; - const char *ef = "binary"; - const char *bd = 0; - fprogress ff; - int i; - char buf[4096]; - unsigned f = 0; - const encops *eo; - enc *e; - -#define f_bogus 1u -#define f_progress 2u - - for (;;) { - static const struct option opt[] = { - { "format", OPTF_ARGREQ, 0, 'f' }, - { "boundary", OPTF_ARGREQ, 0, 'b' }, - { "output", OPTF_ARGREQ, 0, 'o' }, - { "progress", 0, 0, 'p' }, - { 0, 0, 0, 0 } - }; - i = mdwopt(argc, argv, "f:b:o:p", opt, 0, 0, 0); - if (i < 0) break; - switch (i) { - case 'f': ef = optarg; break; - case 'b': bd = optarg; break; - case 'o': of = optarg; break; - case 'p': f |= f_progress; break; - default: f |= f_bogus; break; - } - } - if (argc - optind > 1 || (f & f_bogus)) - die(EXIT_FAILURE, "Usage: decode [-OPTIONS] [FILE]"); - - if ((eo = getenc(ef)) == 0) - die(EXIT_FAILURE, "encoding `%s' not found", ef); - - fn = optind < argc ? argv[optind++] : "-"; - if (strcmp(fn, "-") == 0) - fp = stdin; - else if ((fp = fopen(fn, eo->rmode)) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s': %s", - fn, strerror(errno)); - } - - if (!of || strcmp(of, "-") == 0) - ofp = stdout; - else if ((ofp = fopen(of, "wb")) == 0) { - die(EXIT_FAILURE, "couldn't open file `%s' for output: %s", - ofp, strerror(errno)); - } - - e = initdec(eo, fp, checkbdry, (/*unconst*/ void *)bd); - - if (f & f_progress) { - if (fprogress_init(&ff, fn, fp)) { - die(EXIT_FAILURE, "failed to initialize progress display: %s", - strerror(errno)); - } - } - - do { - if ((i = e->ops->read(e, buf, sizeof(buf))) < 0) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "error reading input: %s", strerror(errno)); - } - if (f & f_progress) - fprogress_update(&ff, i*e->ops->ncook/e->ops->nraw); - if (fwrite(buf, 1, i, ofp) < i) { - if (f & f_progress) fprogress_done(&ff); - die(EXIT_FAILURE, "error writing output: %s", strerror(errno)); - } - } while (i == sizeof(buf)); - e->ops->decdone(e); - if (f & f_progress) fprogress_done(&ff); - freeenc(e); - return (0); - -#undef f_bogus -#undef f_progress -} - -/*----- That's all, folks -------------------------------------------------*/