Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/ftp PR/57003: Handle relative URLs (patch by kim@)
details: https://anonhg.NetBSD.org/src/rev/01f49d3b0a14
branches: trunk
changeset: 369996:01f49d3b0a14
user: christos <christos%NetBSD.org@localhost>
date: Sun Sep 11 20:49:27 2022 +0000
description:
PR/57003: Handle relative URLs (patch by kim@)
diffstat:
usr.bin/ftp/fetch.c | 171 +++++++++++++++++++++++++++++++++------------------
1 files changed, 111 insertions(+), 60 deletions(-)
diffs (truncated from 546 to 300 lines):
diff -r e388fc09e3f1 -r 01f49d3b0a14 usr.bin/ftp/fetch.c
--- a/usr.bin/ftp/fetch.c Sun Sep 11 20:32:37 2022 +0000
+++ b/usr.bin/ftp/fetch.c Sun Sep 11 20:49:27 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fetch.c,v 1.234 2021/08/01 15:29:30 andvar Exp $ */
+/* $NetBSD: fetch.c,v 1.235 2022/09/11 20:49:27 christos Exp $ */
/*-
* Copyright (c) 1997-2015 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: fetch.c,v 1.234 2021/08/01 15:29:30 andvar Exp $");
+__RCSID("$NetBSD: fetch.c,v 1.235 2022/09/11 20:49:27 christos Exp $");
#endif /* not lint */
/*
@@ -106,12 +106,13 @@
static int auth_url(const char *, char **, const struct authinfo *);
static void base64_encode(const unsigned char *, size_t, unsigned char *);
#endif
-static int go_fetch(const char *);
+static int go_fetch(const char *, struct urlinfo *);
static int fetch_ftp(const char *);
-static int fetch_url(const char *, const char *, char *, char *);
+static int fetch_url(const char *, const char *, char *, char *,
+ struct urlinfo *);
static const char *match_token(const char **, const char *);
static int parse_url(const char *, const char *, struct urlinfo *,
- struct authinfo *);
+ struct authinfo *, struct urlinfo *);
static void url_decode(char *);
static void freeauthinfo(struct authinfo *);
static void freeurlinfo(struct urlinfo *);
@@ -274,7 +275,7 @@
scheme = "Basic"; /* only support Basic authentication */
gotpass = NULL;
- DPRINTF("auth_url: challenge `%s'\n", challenge);
+ DPRINTF("%s: challenge `%s'\n", __func__, challenge);
if (! match_token(&cp, scheme)) {
warnx("Unsupported authentication challenge `%s'",
@@ -336,7 +337,7 @@
*response = ftp_malloc(rlen);
(void)strlcpy(*response, scheme, rlen);
len = strlcat(*response, " ", rlen);
- /* use `clen - 1' to not encode the trailing NUL */
+ /* use `clen - 1' to not encode the trailing NUL */
base64_encode((unsigned char *)clear, clen - 1,
(unsigned char *)*response + len);
memset(clear, 0, clen);
@@ -367,7 +368,7 @@
| ((clear[i + 1] >> 4) & 0x0f)];
*(cp++) = enc[((clear[i + 1] << 2) & 0x3c)
| ((clear[i + 2] >> 6) & 0x03)];
- *(cp++) = enc[((clear[i + 2] ) & 0x3f)];
+ *(cp++) = enc[((clear[i + 2] ) & 0x3f)];
}
*cp = '\0';
while (i-- > len)
@@ -400,6 +401,42 @@
*q = '\0';
}
+static const char *
+get_port(const struct urlinfo *ui)
+{
+
+ switch(ui->utype) {
+ case HTTP_URL_T:
+ return httpport;
+ case FTP_URL_T:
+ return ftpport;
+ case FILE_URL_T:
+ return "";
+#ifdef WITH_SSL
+ case HTTPS_URL_T:
+ return httpsport;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+static int
+use_relative(const struct urlinfo *ui)
+{
+ if (ui == NULL)
+ return 0;
+ switch (ui->utype) {
+ case HTTP_URL_T:
+ case FILE_URL_T:
+#ifdef WITH_SSL
+ case HTTPS_URL_T:
+#endif
+ return 1;
+ default:
+ return 0;
+ }
+}
/*
* Parse URL of form (per RFC 3986):
@@ -435,7 +472,7 @@
static int
parse_url(const char *url, const char *desc, struct urlinfo *ui,
- struct authinfo *auth)
+ struct authinfo *auth, struct urlinfo *rui)
{
const char *origurl, *tport;
char *cp, *ep, *thost;
@@ -446,29 +483,26 @@
DPRINTF("parse_url: %s `%s'\n", desc, url);
origurl = url;
- tport = NULL;
if (STRNEQUAL(url, HTTP_URL)) {
url += sizeof(HTTP_URL) - 1;
ui->utype = HTTP_URL_T;
ui->portnum = HTTP_PORT;
- tport = httpport;
} else if (STRNEQUAL(url, FTP_URL)) {
url += sizeof(FTP_URL) - 1;
ui->utype = FTP_URL_T;
ui->portnum = FTP_PORT;
- tport = ftpport;
} else if (STRNEQUAL(url, FILE_URL)) {
url += sizeof(FILE_URL) - 1;
ui->utype = FILE_URL_T;
- tport = "";
#ifdef WITH_SSL
} else if (STRNEQUAL(url, HTTPS_URL)) {
url += sizeof(HTTPS_URL) - 1;
ui->utype = HTTPS_URL_T;
ui->portnum = HTTPS_PORT;
- tport = httpsport;
#endif
+ } else if (rui != NULL) {
+ copyurlinfo(ui, rui);
} else {
warnx("Invalid %s `%s'", desc, url);
cleanup_parse_url:
@@ -477,6 +511,7 @@
return (-1);
}
+
if (*url == '\0')
return (0);
@@ -541,7 +576,8 @@
#endif /* INET6 */
if ((cp = strchr(thost, ':')) != NULL)
*cp++ = '\0';
- ui->host = thost;
+ if (*thost != '\0')
+ ui->host = thost;
/* look for [:port] */
if (cp != NULL) {
@@ -556,7 +592,9 @@
}
ui->portnum = nport;
tport = cp;
- }
+ } else
+ tport = get_port(ui);
+
if (tport != NULL)
ui->port = ftp_strdup(tport);
@@ -567,8 +605,8 @@
ui->path = ftp_strdup(emptypath);
}
- DPRINTF("parse_url: user `%s' pass `%s' host %s port %s(%d) "
- "path `%s'\n",
+ DPRINTF("%s: user `%s' pass `%s' host %s port %s(%d) "
+ "path `%s'\n", __func__,
STRorNULL(auth->user), STRorNULL(auth->pass),
STRorNULL(ui->host), STRorNULL(ui->port),
ui->portnum ? ui->portnum : -1, STRorNULL(ui->path));
@@ -581,7 +619,7 @@
static int
ftp_socket(const struct urlinfo *ui, void **ssl)
{
- struct addrinfo hints, *res, *res0 = NULL;
+ struct addrinfo hints, *res, *res0 = NULL;
int error;
int s;
const char *host = ui->host;
@@ -686,7 +724,7 @@
if (*cp == '\0')
continue;
if ((np = strrchr(cp, ':')) != NULL) {
- *np++ = '\0';
+ *np++ = '\0';
np_port = strtoul(np, &ep, 10);
if (*np == '\0' || *ep != '\0')
continue;
@@ -718,7 +756,7 @@
}
initurlinfo(&pui);
- if (parse_url(penv, "proxy URL", &pui, pauth) == -1)
+ if (parse_url(penv, "proxy URL", &pui, pauth, NULL) == -1)
return -1;
if ((!IS_HTTP_TYPE(pui.utype) && pui.utype != FTP_URL_T) ||
@@ -889,9 +927,9 @@
}
#endif
-#define C_OK 0
-#define C_CLEANUP 1
-#define C_IMPROPER 2
+#define C_OK 0
+#define C_CLEANUP 1
+#define C_IMPROPER 2
static int
getresponseline(FETCH *fin, char *buf, size_t buflen, int *len)
@@ -990,7 +1028,7 @@
static void
do_auth(int hcode, const char *url, const char *penv, struct authinfo *wauth,
struct authinfo *pauth, char **auth, const char *message,
- volatile int *rval)
+ volatile int *rval, struct urlinfo *ui)
{
struct authinfo aauth;
char *response;
@@ -1025,7 +1063,8 @@
if (auth_url(*auth, &response, &aauth) == 0) {
*rval = fetch_url(url, penv,
hcode == 401 ? pauth->auth : response,
- hcode == 401 ? response: wauth->auth);
+ hcode == 401 ? response : wauth->auth,
+ ui);
memset(response, 0, strlen(response));
FREEPTR(response);
}
@@ -1036,12 +1075,12 @@
negotiate_connection(FETCH *fin, const char *url, const char *penv,
struct posinfo *pi, time_t *mtime, struct authinfo *wauth,
struct authinfo *pauth, volatile int *rval, volatile int *ischunked,
- char **auth)
+ char **auth, struct urlinfo *ui)
{
int len, hcode, rv;
char buf[FTPBUFLEN], *ep;
const char *cp, *token;
- char *location, *message;
+ char *location, *message;
*auth = message = location = NULL;
@@ -1156,18 +1195,19 @@
fprintf(ttyout, "Redirected via %s\n",
location);
*rval = fetch_url(url, location,
- pauth->auth, wauth->auth);
+ pauth->auth, wauth->auth, ui);
} else {
if (verbose)
fprintf(ttyout, "Redirected to %s\n",
location);
- *rval = go_fetch(location);
+ *rval = go_fetch(location, ui);
}
goto cleanup_fetch_url;
#ifndef NO_AUTH
case 401:
case 407:
- do_auth(hcode, url, penv, wauth, pauth, auth, message, rval);
+ do_auth(hcode, url, penv, wauth, pauth, auth, message, rval,
+ ui);
goto cleanup_fetch_url;
#endif
default:
@@ -1232,7 +1272,7 @@
message = ftp_strdup(ep);
break;
}
-
+
for (;;) {
int len;
if (getresponseline(fin, buf, sizeof(buf), &len) != C_OK)
@@ -1261,7 +1301,8 @@
break;
#ifndef NO_AUTH
case 407:
- do_auth(hcode, url, penv, wauth, pauth, auth, message, rval);
+ do_auth(hcode, url, penv, wauth, pauth, auth, message, rval,
+ ui);
goto cleanup_fetch_url;
Home |
Main Index |
Thread Index |
Old Index