/* $OpenBSD: rsync.c,v 1.7 2019/10/31 08:36:43 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <netinet/in.h> #include <assert.h> #include <err.h> #include <resolv.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/ssl.h> #include "extern.h" /* * Conforms to RFC 5781. * Note that "Source" is broken down into the module, path, and also * file type relevant to RPKI. * Any of the pointers (except "uri") may be NULL. * Returns zero on failure, non-zero on success. */ int rsync_uri_parse(const char **hostp, size_t *hostsz, const char **modulep, size_t *modulesz, const char **pathp, size_t *pathsz, enum rtype *rtypep, const char *uri) { const char *host, *module, *path; size_t sz; /* Initialise all output values to NULL or 0. */ if (hostsz != NULL) *hostsz = 0; if (modulesz != NULL) *modulesz = 0; if (pathsz != NULL) *pathsz = 0; if (hostp != NULL) *hostp = 0; if (modulep != NULL) *modulep = 0; if (pathp != NULL) *pathp = 0; if (rtypep != NULL) *rtypep = RTYPE_EOF; /* Case-insensitive rsync URI. */ if (strncasecmp(uri, "rsync://", 8)) { warnx("%s: not using rsync schema", uri); return 0; } /* Parse the non-zero-length hostname. */ host = uri + 8; if ((module = strchr(host, '/')) == NULL) { warnx("%s: missing rsync module", uri); return 0; } else if (module == host) { warnx("%s: zero-length rsync host", uri); return 0; } if (hostp != NULL) *hostp = host; if (hostsz != NULL) *hostsz = module - host; /* The non-zero-length module follows the hostname. */ if (module[1] == '\0') { warnx("%s: zero-length rsync module", uri); return 0; } module++; /* The path component is optional. */ if ((path = strchr(module, '/')) == NULL) { assert(*module != '\0'); if (modulep != NULL) *modulep = module; if (modulesz != NULL) *modulesz = strlen(module); return 1; } else if (path == module) { warnx("%s: zero-length module", uri); return 0; } if (modulep != NULL) *modulep = module; if (modulesz != NULL) *modulesz = path - module; 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; }