On Tue, Nov 05, 2019 at 01:57:09PM -0300, Alexandre Hamada wrote:
> Hi Claudio.
>
> FYI, I've added some support for https. Not sure if this might be useful,
> but here is the code for ta_parse_buffer.
>
> I´ve also modified tal_parse to display a warn message instead of exiting on
> invalid basename.
I decided to currently ignore https URI and just print a warn message.
The code needs some major change so that multiple URI are correclty
supported (which is currently not the case) and that https:// would be
preferred. First of all the process responsible for fetching repos needs
to learn about https://. Then I think rsync_uri_parse() needs to be
reworked. At that point it may be possible to add https:// support to that
function and make it a generic URI parser.
Thanks for the diff anyway.
--
:wq Claudio
> Regards,
> Alexandre Hamada
>
> static int
> https_uri_parse(const char **hostp, size_t *hostsz,
> const char **pathp, size_t *pathsz,
> enum rtype *rtypep, const char *uri)
> {
> const char *host, *path;
> size_t sz;
>
> /* Initialise all output values to NULL or 0. */
>
> if (hostsz != NULL)
> *hostsz = 0;
> if (pathsz != NULL)
> *pathsz = 0;
> if (hostp != NULL)
> *hostp = 0;
> if (pathp != NULL)
> *pathp = 0;
> if (rtypep != NULL)
> *rtypep = RTYPE_EOF;
>
> /* Case-insensitive https URI. */
> if (strncasecmp(uri, "https://", 8)) {
> warnx("%s: not using https schema", uri);
> return 0;
> }
>
> /* Parse the non-zero-length hostname. */
>
> host = uri + 8;
>
> if ((path = strchr(host, '/')) == NULL) {
> warnx("%s: missing https path", uri);
> return 0;
> } else if (path == host) {
> warnx("%s: zero-length https path", uri);
> return 0;
> }
>
> if (hostp != NULL)
> *hostp = host;
> if (hostsz != NULL)
> *hostsz = path - host;
>
> path++;
> sz = strlen(path);
>
> if (pathp != NULL)
> *pathp = path;
> if (pathsz != NULL)
> *pathsz = sz;
>
> if (rtypep != NULL && sz > 4) {
> if (strcasecmp(path + sz - 4, ".roa") == 0)
> *rtypep = RTYPE_ROA;
> else if (strcasecmp(path + sz - 4, ".mft") == 0)
> *rtypep = RTYPE_MFT;
> else if (strcasecmp(path + sz - 4, ".cer") == 0)
> *rtypep = RTYPE_CER;
> else if (strcasecmp(path + sz - 4, ".crl") == 0)
> *rtypep = RTYPE_CRL;
> }
>
> return 1;
> }
>
> /*
> * Inner function for parsing RFC 7730 from a buffer.
> * Returns a valid pointer on success, NULL otherwise.
> * The pointer must be freed with tal_free().
> */
> static struct tal *
> tal_parse_buffer(const char *fn, char *buf)
> {
> char *nl, *line;
> unsigned char *b64 = NULL;
> size_t sz;
> int rc = 0, b64sz;
> struct tal *tal = NULL;
> enum rtype rp;
> EVP_PKEY *pkey = NULL;
>
> if ((tal = calloc(1, sizeof(struct tal))) == NULL)
> err(EXIT_FAILURE, NULL);
>
> /* Begin with the URI section, comment section already removed. */
> while ((nl = strchr(buf, '\n')) != NULL) {
> line = buf;
> *nl = '\0';
>
> /* advance buffer to next line */
> buf = nl + 1;
>
> /* Zero-length line is end of section. */
> if (*line == '\0')
> break;
>
> /* Append to list of URIs. */
> tal->uri = reallocarray(tal->uri,
> tal->urisz + 1, sizeof(char *));
> if (tal->uri == NULL)
> err(EXIT_FAILURE, NULL);
>
> tal->uri[tal->urisz] = strdup(line);
> if (tal->uri[tal->urisz] == NULL)
> err(EXIT_FAILURE, NULL);
> tal->urisz++;
>
> /* Make sure we're a proper rsync/https URI. */
> if (strncasecmp(line, "https://", 8) == 0) {
> if (!https_uri_parse(NULL, NULL, NULL, NULL, &rp, line)) {
> warnx("%s: RFC 8630 section 2.2: "
> "failed to parse URL: %s", fn, line);
> goto out;
> }
> } else if (!rsync_uri_parse(NULL, NULL, NULL, NULL, NULL, NULL, &rp,
> line)) {
> warnx("%s: RFC 8630 section 2.2: "
> "failed to parse URL: %s", fn, line);
> goto out;
> }
> if (rp != RTYPE_CER) {
> warnx("%s: RFC 7730 section 2.1: "
> "not a certificate URL: %s", fn, line);
> goto out;
> }
>
> }
>
> if (tal->urisz == 0) {
> warnx("%s: no URIs in manifest part", fn);
> goto out;
> } else if (tal->urisz > 1)
> warnx("%s: multiple URIs: using the first", fn);
>
> sz = strlen(buf);
> if (sz == 0) {
> warnx("%s: RFC 7730 section 2.1: subjectPublicKeyInfo: "
> "zero-length public key", fn);
> goto out;
> }
>
> /* Now the BASE64-encoded public key. */
> sz = ((sz + 2) / 3) * 4 + 1;
> if ((b64 = malloc(sz)) == NULL)
> err(EXIT_FAILURE, NULL);
> if ((b64sz = b64_pton(buf, b64, sz)) < 0)
> errx(EXIT_FAILURE, "b64_pton");
>
> tal->pkey = b64;
> tal->pkeysz = b64sz;
>
> /* Make sure it's a valid public key. */
> pkey = d2i_PUBKEY(NULL, (const unsigned char **)&b64, b64sz);
> if (pkey == NULL) {
> cryptowarnx("%s: RFC 7730 section 2.1: subjectPublicKeyInfo: "
> "failed public key parse", fn);
> goto out;
> }
> rc = 1;
> out:
> if (rc == 0) {
> tal_free(tal);
> tal = NULL;
> }
> EVP_PKEY_free(pkey);
> return tal;
> }
>
> /*
> * Parse a TAL from a file conformant to RFC 7730.
> * Returns the encoded data or NULL on failure.
> * Failure can be any number of things: failure to open file, allocate
> * memory, bad syntax, etc.
> */
> struct tal *
> tal_parse(const char *fn, char *buf)
> {
> struct tal *p;
> char *d;
> size_t dlen;
>
> p = tal_parse_buffer(fn, buf);
>
> if (p != NULL) {
> /* extract the TAL basename (without .tal suffix) */
> d = basename((char*)fn);
> if (d == NULL) {
> warnx("%s: basename", fn);
> } else {
> dlen = strlen(d);
> if (strcasecmp(d + dlen - 4, ".tal") == 0)
> dlen -= 4;
> if ((p->descr = malloc(dlen + 1)) == NULL)
> err(EXIT_FAILURE, NULL);
> memcpy(p->descr, d, dlen);
> p->descr[dlen] = 0;
> }
> }
> return p;
> }
>
>
>
> On 05/11/2019 11:01, Alexandre Hamada wrote:
> > Hi Claudio,
> >
> > I was testing some tal files, and when it contains an https url (RFC
> > 8630), it generates a segmentation fault.
> >
> > Thus, I would like to suggest adding the following on tal_parse/tal_free.
> >
> > Example:
> > https://rir.docker/ta/ta.cer
> >
> > MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoFVWio0auchdC1mCbp4N
> > pSG9b43tXDIIOHHsc/6fTg0wdFdX68qHFYAwTlXVriXs5j0WmB8DZ1qiE4nyYfEj
> > kVIU6bVbz8WZ03BpajGO1AfbasBdbAr4SWjl8YCyCFjfojij2SnH/lbjxca5mSa0
> > wJAT4LEG/B4kMROcKRSebTCi8iDxMYha1GFFXBD9ze9qpEoUE3ZobQfITMNd8xZx
> > mZyg6bXXnT8qj7m5IrCs7dD4qrhjPTKbxwlpXFlS4pNdh9p9H/gFHxF7SbOLIq4m
> > 2rBQKNCMzvFnFgWJyM2QqiCb89WJf6kvyBjMbh7h/HygaXy8SuXUprExudQy8OZp
> > xwIDAQAB
> >
> >
> > Regards,
> > Alexandre Hamada
> >
> > @@ -142,18 +142,19 @@ tal_parse(const char *fn, char *buf)
> >
> > p = tal_parse_buffer(fn, buf);
> >
> > - /* extract the TAL basename (without .tal suffix) */
> > - d = basename((char*)fn);
> > - if (d == NULL)
> > - err(EXIT_FAILURE, "%s: basename", fn);
> > - dlen = strlen(d);
> > - if (strcasecmp(d + dlen - 4, ".tal") == 0)
> > - dlen -= 4;
> > - if ((p->descr = malloc(dlen + 1)) == NULL)
> > - err(EXIT_FAILURE, NULL);
> > - memcpy(p->descr, d, dlen);
> > - p->descr[dlen] = 0;
> > -
> > + if(p != NULL) {
> > + /* extract the TAL basename (without .tal suffix) */
> > + d = basename((char*)fn);
> > + if (d == NULL)
> > + err(EXIT_FAILURE, "%s: basename", fn);
> > + dlen = strlen(d);
> > + if (strcasecmp(d + dlen - 4, ".tal") == 0)
> > + dlen -= 4;
> > + if ((p->descr = malloc(dlen + 1)) == NULL)
> > + err(EXIT_FAILURE, NULL);
> > + memcpy(p->descr, d, dlen);
> > + p->descr[dlen] = 0;
> > + }
> > return p;
> > }
> >
> > @@ -231,9 +232,15 @@ tal_free(struct tal *p)
> > for (i = 0; i < p->urisz; i++)
> > free(p->uri[i]);
> >
> > - free(p->pkey);
> > - free(p->uri);
> > - free(p->descr);
> > + if (p->pkey != NULL) {
> > + free(p->pkey);
> > + }
> > + if (p->uri != NULL) {
> > + free(p->uri);
> > + }
> > + if (p->descr != NULL) {
> > + free(p->descr);
> > + }
> > free(p);
> > }
> >
>