Annotation of src/usr.bin/ftp/ftp.c, Revision 1.87
1.87 ! deraadt 1: /* $OpenBSD: ftp.c,v 1.86 2014/05/20 01:25:23 guenther Exp $ */
1.22 millert 2: /* $NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $ */
1.1 deraadt 3:
4: /*
1.34 itojun 5: * Copyright (C) 1997 and 1998 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: /*
1.1 deraadt 34: * Copyright (c) 1985, 1989, 1993, 1994
35: * The Regents of the University of California. All rights reserved.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
1.53 millert 45: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 46: * may be used to endorse or promote products derived from this software
47: * without specific prior written permission.
48: *
49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59: * SUCH DAMAGE.
60: */
61:
1.10 millert 62: #include <sys/types.h>
1.1 deraadt 63: #include <sys/stat.h>
64: #include <sys/socket.h>
65:
66: #include <netinet/in.h>
67: #include <netinet/in_systm.h>
68: #include <netinet/ip.h>
69: #include <arpa/inet.h>
70: #include <arpa/ftp.h>
71: #include <arpa/telnet.h>
72:
73: #include <ctype.h>
74: #include <err.h>
75: #include <errno.h>
76: #include <netdb.h>
1.54 millert 77: #include <poll.h>
78: #include <stdarg.h>
1.1 deraadt 79: #include <stdio.h>
80: #include <stdlib.h>
81: #include <string.h>
82: #include <unistd.h>
1.12 millert 83: #include <utime.h>
1.1 deraadt 84:
85: #include "ftp_var.h"
86:
1.34 itojun 87: union sockunion {
88: struct sockinet {
89: u_char si_len;
90: u_char si_family;
91: u_short si_port;
92: } su_si;
93: struct sockaddr_in su_sin;
94: struct sockaddr_in6 su_sin6;
95: };
96: #define su_len su_si.si_len
97: #define su_family su_si.si_family
98: #define su_port su_si.si_port
99:
100: union sockunion myctladdr, hisctladdr, data_addr;
101:
1.1 deraadt 102: int data = -1;
103: int abrtflag = 0;
104: jmp_buf ptabort;
105: int ptabflg;
106: int ptflag = 0;
107: off_t restart_point = 0;
108:
109:
110: FILE *cin, *cout;
111:
112: char *
1.56 deraadt 113: hookup(char *host, char *port)
1.1 deraadt 114: {
1.57 deraadt 115: int s, tos, error;
1.10 millert 116: static char hostnamebuf[MAXHOSTNAMELEN];
1.82 haesbaer 117: struct addrinfo hints, *res, *res0, *ares;
1.51 itojun 118: char hbuf[NI_MAXHOST];
1.34 itojun 119: char *cause = "unknown";
1.57 deraadt 120: socklen_t namelen;
1.34 itojun 121:
1.36 itojun 122: epsv4bad = 0;
123:
1.34 itojun 124: memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
125: memset(&hints, 0, sizeof(hints));
126: hints.ai_flags = AI_CANONNAME;
1.45 deraadt 127: hints.ai_family = family;
1.34 itojun 128: hints.ai_socktype = SOCK_STREAM;
129: hints.ai_protocol = 0;
130: error = getaddrinfo(host, port, &hints, &res0);
1.35 deraadt 131: if (error == EAI_SERVICE) {
132: /*
133: * If the services file is corrupt/missing, fall back
134: * on our hard-coded defines.
135: */
136: char pbuf[NI_MAXSERV];
137:
138: pbuf[0] = '\0';
139: if (strcmp(port, "ftp") == 0)
140: snprintf(pbuf, sizeof(pbuf), "%d", FTP_PORT);
141: else if (strcmp(port, "ftpgate") == 0)
142: snprintf(pbuf, sizeof(pbuf), "%d", GATE_PORT);
143: else if (strcmp(port, "http") == 0)
144: snprintf(pbuf, sizeof(pbuf), "%d", HTTP_PORT);
1.63 deraadt 145: #ifndef SMALL
146: else if (strcmp(port, "https") == 0)
147: snprintf(pbuf, sizeof(pbuf), "%d", HTTPS_PORT);
1.72 martynas 148: #endif /* !SMALL */
1.35 deraadt 149: if (pbuf[0])
150: error = getaddrinfo(host, pbuf, &hints, &res0);
151: }
1.34 itojun 152: if (error) {
1.39 itojun 153: if (error == EAI_SERVICE)
154: warnx("%s: bad port number `%s'", host, port);
155: else
156: warnx("%s: %s", host, gai_strerror(error));
1.1 deraadt 157: code = -1;
158: return (0);
159: }
1.34 itojun 160:
161: if (res0->ai_canonname)
1.41 lebel 162: strlcpy(hostnamebuf, res0->ai_canonname, sizeof(hostnamebuf));
1.34 itojun 163: else
1.41 lebel 164: strlcpy(hostnamebuf, host, sizeof(hostnamebuf));
1.34 itojun 165: hostname = hostnamebuf;
1.82 haesbaer 166:
167: #ifndef SMALL
168: if (srcaddr) {
169: struct addrinfo ahints;
170:
171: memset(&ahints, 0, sizeof(ahints));
172: ahints.ai_family = family;
173: ahints.ai_socktype = SOCK_STREAM;
174: ahints.ai_flags |= AI_NUMERICHOST;
175: ahints.ai_protocol = 0;
176:
177: error = getaddrinfo(srcaddr, NULL, &ahints, &ares);
178: if (error) {
1.86 guenther 179: warnx("%s: %s", srcaddr, gai_strerror(error));
1.82 haesbaer 180: code = -1;
181: return (0);
182: }
183: }
184: #endif /* !SMALL */
1.34 itojun 185:
186: s = -1;
187: for (res = res0; res; res = res->ai_next) {
188: #if 0 /*old behavior*/
189: if (res != res0) /* not on the first address */
190: #else
191: if (res0->ai_next) /* if we have multiple possibilities */
192: #endif
193: {
1.50 itojun 194: if (getnameinfo(res->ai_addr, res->ai_addrlen,
195: hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
196: strlcpy(hbuf, "unknown", sizeof(hbuf));
1.70 pyr 197: if (verbose)
198: fprintf(ttyout, "Trying %s...\n", hbuf);
1.34 itojun 199: }
200: s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
201: if (s < 0) {
202: cause = "socket";
1.27 deraadt 203: continue;
1.34 itojun 204: }
1.82 haesbaer 205: #ifndef SMALL
206: if (srcaddr) {
207: if (ares->ai_family != res->ai_family) {
208: close(s);
209: s = -1;
210: errno = EINVAL;
211: cause = "bind";
212: continue;
213: }
214: if (bind(s, ares->ai_addr, ares->ai_addrlen) < 0) {
215: cause = "bind";
216: error = errno;
217: close(s);
218: errno = error;
219: s = -1;
220: continue;
221: }
222: }
223: #endif /* !SMALL */
1.34 itojun 224: while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0
225: && errno == EINTR) {
226: ;
227: }
228: if (error) {
229: /* this "if" clause is to prevent print warning twice */
1.78 martynas 230: if (verbose && res->ai_next) {
1.50 itojun 231: if (getnameinfo(res->ai_addr, res->ai_addrlen,
232: hbuf, sizeof(hbuf), NULL, 0,
233: NI_NUMERICHOST) != 0)
234: strlcpy(hbuf, "(unknown)",
235: sizeof(hbuf));
1.34 itojun 236: warn("connect to address %s", hbuf);
1.1 deraadt 237: }
1.34 itojun 238: cause = "connect";
1.60 moritz 239: error = errno;
1.34 itojun 240: close(s);
1.60 moritz 241: errno = error;
1.34 itojun 242: s = -1;
1.1 deraadt 243: continue;
244: }
1.34 itojun 245:
246: /* finally we got one */
247: break;
248: }
249: if (s < 0) {
1.38 millert 250: warn("%s", cause);
1.1 deraadt 251: code = -1;
1.34 itojun 252: freeaddrinfo(res0);
253: return 0;
1.1 deraadt 254: }
1.34 itojun 255: memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen);
1.57 deraadt 256: namelen = res->ai_addrlen;
1.34 itojun 257: freeaddrinfo(res0);
258: res0 = res = NULL;
1.82 haesbaer 259: #ifndef SMALL
260: if (srcaddr) {
261: freeaddrinfo(ares);
262: ares = NULL;
263: }
264: #endif /* !SMALL */
1.57 deraadt 265: if (getsockname(s, (struct sockaddr *)&myctladdr, &namelen) < 0) {
1.1 deraadt 266: warn("getsockname");
267: code = -1;
268: goto bad;
269: }
1.34 itojun 270: #if defined(IPPROTO_IP) && defined(IP_TOS)
271: if (hisctladdr.su_family == AF_INET) {
272: tos = IPTOS_LOWDELAY;
273: if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
274: warn("setsockopt TOS (ignored)");
275: }
1.1 deraadt 276: #endif
277: cin = fdopen(s, "r");
278: cout = fdopen(s, "w");
279: if (cin == NULL || cout == NULL) {
280: warnx("fdopen failed.");
281: if (cin)
1.11 millert 282: (void)fclose(cin);
1.1 deraadt 283: if (cout)
1.11 millert 284: (void)fclose(cout);
1.1 deraadt 285: code = -1;
286: goto bad;
287: }
288: if (verbose)
1.18 deraadt 289: fprintf(ttyout, "Connected to %s.\n", hostname);
1.1 deraadt 290: if (getreply(0) > 2) { /* read startup message from server */
291: if (cin)
1.11 millert 292: (void)fclose(cin);
1.1 deraadt 293: if (cout)
1.11 millert 294: (void)fclose(cout);
1.1 deraadt 295: code = -1;
296: goto bad;
297: }
298: #ifdef SO_OOBINLINE
299: {
1.73 martynas 300: int ret, on = 1;
1.1 deraadt 301:
1.73 martynas 302: ret = setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on));
303: #ifndef SMALL
304: if (ret < 0 && debug)
305: warn("setsockopt");
306: #endif /* !SMALL */
1.1 deraadt 307: }
308: #endif /* SO_OOBINLINE */
309:
310: return (hostname);
311: bad:
1.11 millert 312: (void)close(s);
1.1 deraadt 313: return ((char *)0);
314: }
315:
1.57 deraadt 316: /* ARGSUSED */
1.1 deraadt 317: void
1.57 deraadt 318: cmdabort(int signo)
1.1 deraadt 319: {
1.87 ! deraadt 320: int save_errno = errno;
1.1 deraadt 321:
1.10 millert 322: alarmtimer(0);
1.87 ! deraadt 323: (void) write(fileno(ttyout), "\n\r", 2);
1.1 deraadt 324: abrtflag++;
1.87 ! deraadt 325:
! 326: errno = save_errno;
1.1 deraadt 327: if (ptflag)
1.10 millert 328: longjmp(ptabort, 1);
1.1 deraadt 329: }
330:
331: /*VARARGS*/
332: int
1.13 millert 333: command(const char *fmt, ...)
1.1 deraadt 334: {
335: va_list ap;
336: int r;
337: sig_t oldintr;
338:
339: abrtflag = 0;
1.73 martynas 340: #ifndef SMALL
1.1 deraadt 341: if (debug) {
1.18 deraadt 342: fputs("---> ", ttyout);
1.13 millert 343: va_start(ap, fmt);
1.1 deraadt 344: if (strncmp("PASS ", fmt, 5) == 0)
1.18 deraadt 345: fputs("PASS XXXX", ttyout);
1.10 millert 346: else if (strncmp("ACCT ", fmt, 5) == 0)
1.18 deraadt 347: fputs("ACCT XXXX", ttyout);
1.10 millert 348: else
1.28 millert 349: vfprintf(ttyout, fmt, ap);
1.1 deraadt 350: va_end(ap);
1.18 deraadt 351: putc('\n', ttyout);
352: (void)fflush(ttyout);
1.1 deraadt 353: }
1.73 martynas 354: #endif /* !SMALL */
1.1 deraadt 355: if (cout == NULL) {
1.13 millert 356: warnx("No control connection for command.");
1.1 deraadt 357: code = -1;
358: return (0);
359: }
360: oldintr = signal(SIGINT, cmdabort);
1.13 millert 361: va_start(ap, fmt);
1.1 deraadt 362: vfprintf(cout, fmt, ap);
363: va_end(ap);
1.11 millert 364: fputs("\r\n", cout);
365: (void)fflush(cout);
1.1 deraadt 366: cpend = 1;
367: r = getreply(!strcmp(fmt, "QUIT"));
368: if (abrtflag && oldintr != SIG_IGN)
369: (*oldintr)(SIGINT);
1.11 millert 370: (void)signal(SIGINT, oldintr);
1.1 deraadt 371: return (r);
372: }
373:
1.68 espie 374: int keep_alive_timeout = 60; /* 0 -> no timeout */
1.67 espie 375:
376: static int full_noops_sent = 0;
377: static time_t last_timestamp = 0; /* 0 -> no measurement yet */
378: static char noop[] = "NOOP\r\n";
379: #define NOOP_LENGTH (sizeof noop - 1)
380: static int current_nop_pos = 0; /* 0 -> no noop started */
381:
382: /* to achieve keep alive, we send noop one byte at a time */
1.83 deraadt 383: static void
384: send_noop_char(void)
1.67 espie 385: {
1.73 martynas 386: #ifndef SMALL
1.67 espie 387: if (debug)
388: fprintf(ttyout, "---> %c\n", noop[current_nop_pos]);
1.73 martynas 389: #endif /* !SMALL */
1.67 espie 390: fputc(noop[current_nop_pos++], cout);
391: (void)fflush(cout);
392: if (current_nop_pos >= NOOP_LENGTH) {
393: full_noops_sent++;
394: current_nop_pos = 0;
395: }
396: }
397:
1.83 deraadt 398: static void
399: may_reset_noop_timeout(void)
1.67 espie 400: {
401: if (keep_alive_timeout != 0)
402: last_timestamp = time(NULL);
403: }
404:
1.83 deraadt 405: static void
406: may_receive_noop_ack(void)
1.67 espie 407: {
408: int i;
1.74 martynas 409:
410: if (cout == NULL) {
411: /* Lost connection; so just pretend we're fine. */
412: current_nop_pos = full_noops_sent = 0;
413: return;
414: }
1.67 espie 415:
416: /* finish sending last incomplete noop */
417: if (current_nop_pos != 0) {
418: fputs(&(noop[current_nop_pos]), cout);
1.73 martynas 419: #ifndef SMALL
1.67 espie 420: if (debug)
421: fprintf(ttyout, "---> %s\n", &(noop[current_nop_pos]));
1.73 martynas 422: #endif /* !SMALL */
1.67 espie 423: (void)fflush(cout);
424: current_nop_pos = 0;
425: full_noops_sent++;
426: }
427: /* and get the replies */
428: for (i = 0; i < full_noops_sent; i++)
429: (void)getreply(0);
430:
431: full_noops_sent = 0;
432: }
433:
1.83 deraadt 434: static void
435: may_send_noop_char(void)
1.67 espie 436: {
437: if (keep_alive_timeout != 0) {
438: if (last_timestamp != 0) {
439: time_t t = time(NULL);
440:
441: if (t - last_timestamp >= keep_alive_timeout) {
442: last_timestamp = t;
443: send_noop_char();
444: }
445: } else {
446: last_timestamp = time(NULL);
447: }
448: }
449: }
450:
1.10 millert 451: char reply_string[BUFSIZ]; /* first line of previous reply */
1.1 deraadt 452:
453: int
1.56 deraadt 454: getreply(int expecteof)
1.1 deraadt 455: {
1.10 millert 456: char current_line[BUFSIZ]; /* last line of previous reply */
1.64 ray 457: int c, n, lineno;
1.1 deraadt 458: int dig;
459: int originalcode = 0, continuation = 0;
460: sig_t oldintr;
461: int pflag = 0;
462: char *cp, *pt = pasv;
463:
1.25 weingart 464: memset(current_line, 0, sizeof(current_line));
1.1 deraadt 465: oldintr = signal(SIGINT, cmdabort);
1.64 ray 466: for (lineno = 0 ;; lineno++) {
1.1 deraadt 467: dig = n = code = 0;
1.10 millert 468: cp = current_line;
1.23 millert 469: while ((c = fgetc(cin)) != '\n') {
1.1 deraadt 470: if (c == IAC) { /* handle telnet commands */
1.23 millert 471: switch (c = fgetc(cin)) {
1.1 deraadt 472: case WILL:
473: case WONT:
1.23 millert 474: c = fgetc(cin);
1.1 deraadt 475: fprintf(cout, "%c%c%c", IAC, DONT, c);
1.11 millert 476: (void)fflush(cout);
1.1 deraadt 477: break;
478: case DO:
479: case DONT:
1.23 millert 480: c = fgetc(cin);
1.1 deraadt 481: fprintf(cout, "%c%c%c", IAC, WONT, c);
1.11 millert 482: (void)fflush(cout);
1.1 deraadt 483: break;
484: default:
485: break;
486: }
487: continue;
488: }
489: dig++;
490: if (c == EOF) {
491: if (expecteof) {
1.11 millert 492: (void)signal(SIGINT, oldintr);
1.1 deraadt 493: code = 221;
494: return (0);
495: }
496: lostpeer();
497: if (verbose) {
1.18 deraadt 498: fputs(
499: "421 Service not available, remote server has closed connection.\n", ttyout);
500: (void)fflush(ttyout);
1.1 deraadt 501: }
502: code = 421;
503: return (4);
504: }
1.10 millert 505: if (c != '\r' && (verbose > 0 ||
1.71 martynas 506: ((verbose > -1 && n == '5' && dig > 4) &&
1.21 mickey 507: (((!n && c < '5') || (n && n < '5'))
1.71 martynas 508: || !retry_connect)))) {
1.1 deraadt 509: if (proxflag &&
1.10 millert 510: (dig == 1 || (dig == 5 && verbose == 0)))
1.18 deraadt 511: fprintf(ttyout, "%s:", hostname);
512: (void)putc(c, ttyout);
1.1 deraadt 513: }
514: if (dig < 4 && isdigit(c))
515: code = code * 10 + (c - '0');
1.34 itojun 516: if (!pflag && (code == 227 || code == 228))
1.1 deraadt 517: pflag = 1;
1.34 itojun 518: else if (!pflag && code == 229)
519: pflag = 100;
1.1 deraadt 520: if (dig > 4 && pflag == 1 && isdigit(c))
521: pflag = 2;
522: if (pflag == 2) {
1.44 itojun 523: if (c != '\r' && c != ')') {
524: if (pt < &pasv[sizeof(pasv) - 1])
525: *pt++ = c;
526: } else {
1.1 deraadt 527: *pt = '\0';
528: pflag = 3;
529: }
530: }
1.34 itojun 531: if (pflag == 100 && c == '(')
532: pflag = 2;
1.1 deraadt 533: if (dig == 4 && c == '-') {
534: if (continuation)
535: code = 0;
536: continuation++;
537: }
1.10 millert 538: if (n == 0)
539: n = c;
540: if (cp < ¤t_line[sizeof(current_line) - 1])
1.1 deraadt 541: *cp++ = c;
542: }
1.11 millert 543: if (verbose > 0 || ((verbose > -1 && n == '5') &&
544: (n < '5' || !retry_connect))) {
1.18 deraadt 545: (void)putc(c, ttyout);
546: (void)fflush (ttyout);
1.1 deraadt 547: }
1.64 ray 548: if (lineno == 0) {
1.10 millert 549: size_t len = cp - current_line;
550:
551: if (len > sizeof(reply_string))
552: len = sizeof(reply_string);
553:
1.48 itojun 554: (void)strlcpy(reply_string, current_line, len);
1.10 millert 555: }
1.1 deraadt 556: if (continuation && code != originalcode) {
557: if (originalcode == 0)
558: originalcode = code;
559: continue;
560: }
561: *cp = '\0';
562: if (n != '1')
563: cpend = 0;
1.11 millert 564: (void)signal(SIGINT, oldintr);
1.1 deraadt 565: if (code == 421 || originalcode == 421)
566: lostpeer();
567: if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
568: (*oldintr)(SIGINT);
569: return (n - '0');
570: }
571: }
572:
1.77 martynas 573: #ifndef SMALL
1.1 deraadt 574: jmp_buf sendabort;
575:
1.57 deraadt 576: /* ARGSUSED */
1.1 deraadt 577: void
1.57 deraadt 578: abortsend(int signo)
1.1 deraadt 579: {
1.87 ! deraadt 580: int save_errno = errno;
1.10 millert 581: alarmtimer(0);
1.1 deraadt 582: mflag = 0;
583: abrtflag = 0;
1.87 ! deraadt 584: #define MSG "\nsend aborted\nwaiting for remote to finish abort.\n"
! 585: (void) write(fileno(ttyout), MSG, strlen(MSG));
! 586: #undef MSG
! 587:
! 588: errno = save_errno;
1.1 deraadt 589: longjmp(sendabort, 1);
590: }
591:
592: void
1.56 deraadt 593: sendrequest(const char *cmd, const char *local, const char *remote,
594: int printnames)
1.1 deraadt 595: {
596: struct stat st;
597: int c, d;
1.40 millert 598: FILE * volatile fin, * volatile dout;
1.42 millert 599: int (* volatile closefunc)(FILE *);
1.40 millert 600: volatile sig_t oldinti, oldintr, oldintp;
1.20 millert 601: volatile off_t hashbytes;
1.40 millert 602: char * volatile lmode;
603: char buf[BUFSIZ], *bufp;
1.69 ray 604: int oprogress, serrno;
1.1 deraadt 605:
1.10 millert 606: hashbytes = mark;
607: direction = "sent";
1.20 millert 608: dout = NULL;
1.10 millert 609: bytes = 0;
610: filesize = -1;
1.13 millert 611: oprogress = progress;
1.1 deraadt 612: if (verbose && printnames) {
613: if (local && *local != '-')
1.18 deraadt 614: fprintf(ttyout, "local: %s ", local);
1.1 deraadt 615: if (remote)
1.18 deraadt 616: fprintf(ttyout, "remote: %s\n", remote);
1.1 deraadt 617: }
618: if (proxy) {
619: proxtrans(cmd, local, remote);
620: return;
621: }
622: if (curtype != type)
623: changetype(type, 0);
624: closefunc = NULL;
625: oldintr = NULL;
626: oldintp = NULL;
1.10 millert 627: oldinti = NULL;
1.1 deraadt 628: lmode = "w";
629: if (setjmp(sendabort)) {
630: while (cpend) {
1.11 millert 631: (void)getreply(0);
1.1 deraadt 632: }
633: if (data >= 0) {
1.11 millert 634: (void)close(data);
1.1 deraadt 635: data = -1;
636: }
637: if (oldintr)
1.11 millert 638: (void)signal(SIGINT, oldintr);
1.1 deraadt 639: if (oldintp)
1.11 millert 640: (void)signal(SIGPIPE, oldintp);
1.10 millert 641: if (oldinti)
1.11 millert 642: (void)signal(SIGINFO, oldinti);
1.13 millert 643: progress = oprogress;
1.1 deraadt 644: code = -1;
645: return;
646: }
647: oldintr = signal(SIGINT, abortsend);
1.10 millert 648: oldinti = signal(SIGINFO, psummary);
1.13 millert 649: if (strcmp(local, "-") == 0) {
1.1 deraadt 650: fin = stdin;
1.31 millert 651: if (progress == 1)
652: progress = 0;
1.13 millert 653: } else if (*local == '|') {
1.10 millert 654: oldintp = signal(SIGPIPE, SIG_IGN);
1.1 deraadt 655: fin = popen(local + 1, "r");
656: if (fin == NULL) {
657: warn("%s", local + 1);
1.11 millert 658: (void)signal(SIGINT, oldintr);
659: (void)signal(SIGPIPE, oldintp);
660: (void)signal(SIGINFO, oldinti);
1.1 deraadt 661: code = -1;
662: return;
663: }
1.31 millert 664: if (progress == 1)
665: progress = 0;
1.1 deraadt 666: closefunc = pclose;
667: } else {
668: fin = fopen(local, "r");
669: if (fin == NULL) {
670: warn("local: %s", local);
1.11 millert 671: (void)signal(SIGINT, oldintr);
672: (void)signal(SIGINFO, oldinti);
1.1 deraadt 673: code = -1;
674: return;
675: }
676: closefunc = fclose;
677: if (fstat(fileno(fin), &st) < 0 ||
1.14 millert 678: (st.st_mode & S_IFMT) != S_IFREG) {
1.18 deraadt 679: fprintf(ttyout, "%s: not a plain file.\n", local);
1.11 millert 680: (void)signal(SIGINT, oldintr);
681: (void)signal(SIGINFO, oldinti);
1.1 deraadt 682: fclose(fin);
683: code = -1;
684: return;
685: }
1.10 millert 686: filesize = st.st_size;
1.1 deraadt 687: }
688: if (initconn()) {
1.11 millert 689: (void)signal(SIGINT, oldintr);
690: (void)signal(SIGINFO, oldinti);
1.1 deraadt 691: if (oldintp)
1.11 millert 692: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 693: code = -1;
1.13 millert 694: progress = oprogress;
1.1 deraadt 695: if (closefunc != NULL)
696: (*closefunc)(fin);
697: return;
698: }
699: if (setjmp(sendabort))
700: goto abort;
701:
702: if (restart_point &&
703: (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
1.59 deraadt 704: int rc = -1;
1.1 deraadt 705:
706: switch (curtype) {
707: case TYPE_A:
1.58 sturm 708: rc = fseeko(fin, restart_point, SEEK_SET);
1.1 deraadt 709: break;
710: case TYPE_I:
711: case TYPE_L:
1.59 deraadt 712: if (lseek(fileno(fin), restart_point, SEEK_SET) != -1)
713: rc = 0;
1.1 deraadt 714: break;
715: }
1.59 deraadt 716: if (rc == -1) {
1.1 deraadt 717: warn("local: %s", local);
1.13 millert 718: progress = oprogress;
1.1 deraadt 719: if (closefunc != NULL)
720: (*closefunc)(fin);
721: return;
722: }
1.58 sturm 723: if (command("REST %lld", (long long) restart_point)
1.1 deraadt 724: != CONTINUE) {
1.13 millert 725: progress = oprogress;
1.1 deraadt 726: if (closefunc != NULL)
727: (*closefunc)(fin);
728: return;
729: }
730: lmode = "r+w";
731: }
732: if (remote) {
733: if (command("%s %s", cmd, remote) != PRELIM) {
1.11 millert 734: (void)signal(SIGINT, oldintr);
735: (void)signal(SIGINFO, oldinti);
1.13 millert 736: progress = oprogress;
1.1 deraadt 737: if (oldintp)
1.11 millert 738: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 739: if (closefunc != NULL)
740: (*closefunc)(fin);
741: return;
742: }
743: } else
744: if (command("%s", cmd) != PRELIM) {
1.11 millert 745: (void)signal(SIGINT, oldintr);
746: (void)signal(SIGINFO, oldinti);
1.13 millert 747: progress = oprogress;
1.1 deraadt 748: if (oldintp)
1.11 millert 749: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 750: if (closefunc != NULL)
751: (*closefunc)(fin);
752: return;
753: }
754: dout = dataconn(lmode);
755: if (dout == NULL)
756: goto abort;
1.75 martynas 757: progressmeter(-1, remote);
1.67 espie 758: may_reset_noop_timeout();
1.1 deraadt 759: oldintp = signal(SIGPIPE, SIG_IGN);
760: switch (curtype) {
761:
762: case TYPE_I:
763: case TYPE_L:
1.69 ray 764: d = 0;
1.11 millert 765: while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) {
1.67 espie 766: may_send_noop_char();
1.1 deraadt 767: bytes += c;
768: for (bufp = buf; c > 0; c -= d, bufp += d)
1.20 millert 769: if ((d = write(fileno(dout), bufp, (size_t)c))
770: <= 0)
1.1 deraadt 771: break;
1.10 millert 772: if (hash && (!progress || filesize < 0) ) {
1.1 deraadt 773: while (bytes >= hashbytes) {
1.18 deraadt 774: (void)putc('#', ttyout);
1.7 kstailey 775: hashbytes += mark;
1.1 deraadt 776: }
1.18 deraadt 777: (void)fflush(ttyout);
1.1 deraadt 778: }
779: }
1.69 ray 780: if (c == -1 || d == -1)
781: serrno = errno;
1.10 millert 782: if (hash && (!progress || filesize < 0) && bytes > 0) {
1.7 kstailey 783: if (bytes < mark)
1.18 deraadt 784: (void)putc('#', ttyout);
785: (void)putc('\n', ttyout);
786: (void)fflush(ttyout);
1.1 deraadt 787: }
788: if (c < 0)
1.86 guenther 789: warnc(serrno, "local: %s", local);
1.1 deraadt 790: if (d < 0) {
1.69 ray 791: if (serrno != EPIPE)
1.86 guenther 792: warnc(serrno, "netout");
1.1 deraadt 793: bytes = -1;
794: }
795: break;
796:
797: case TYPE_A:
1.23 millert 798: while ((c = fgetc(fin)) != EOF) {
1.67 espie 799: may_send_noop_char();
1.1 deraadt 800: if (c == '\n') {
1.10 millert 801: while (hash && (!progress || filesize < 0) &&
802: (bytes >= hashbytes)) {
1.18 deraadt 803: (void)putc('#', ttyout);
804: (void)fflush(ttyout);
1.7 kstailey 805: hashbytes += mark;
1.1 deraadt 806: }
807: if (ferror(dout))
808: break;
1.11 millert 809: (void)putc('\r', dout);
1.1 deraadt 810: bytes++;
811: }
1.11 millert 812: (void)putc(c, dout);
1.1 deraadt 813: bytes++;
1.10 millert 814: #if 0 /* this violates RFC */
815: if (c == '\r') {
816: (void)putc('\0', dout);
817: bytes++;
818: }
819: #endif
1.1 deraadt 820: }
1.69 ray 821: if (ferror(fin) || ferror(dout))
822: serrno = errno;
1.10 millert 823: if (hash && (!progress || filesize < 0)) {
1.1 deraadt 824: if (bytes < hashbytes)
1.18 deraadt 825: (void)putc('#', ttyout);
826: (void)putc('\n', ttyout);
827: (void)fflush(ttyout);
1.1 deraadt 828: }
829: if (ferror(fin))
1.86 guenther 830: warnc(serrno, "local: %s", local);
1.1 deraadt 831: if (ferror(dout)) {
832: if (errno != EPIPE)
1.86 guenther 833: warnc(serrno, "netout");
1.1 deraadt 834: bytes = -1;
835: }
836: break;
837: }
1.75 martynas 838: progressmeter(1, NULL);
1.13 millert 839: progress = oprogress;
1.1 deraadt 840: if (closefunc != NULL)
841: (*closefunc)(fin);
1.11 millert 842: (void)fclose(dout);
843: (void)getreply(0);
1.67 espie 844: may_receive_noop_ack();
1.11 millert 845: (void)signal(SIGINT, oldintr);
846: (void)signal(SIGINFO, oldinti);
1.1 deraadt 847: if (oldintp)
1.11 millert 848: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 849: if (bytes > 0)
1.10 millert 850: ptransfer(0);
1.1 deraadt 851: return;
852: abort:
1.11 millert 853: (void)signal(SIGINT, oldintr);
854: (void)signal(SIGINFO, oldinti);
1.13 millert 855: progress = oprogress;
1.1 deraadt 856: if (oldintp)
1.11 millert 857: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 858: if (!cpend) {
859: code = -1;
860: return;
861: }
862: if (data >= 0) {
1.11 millert 863: (void)close(data);
1.1 deraadt 864: data = -1;
865: }
866: if (dout)
1.11 millert 867: (void)fclose(dout);
868: (void)getreply(0);
1.1 deraadt 869: code = -1;
870: if (closefunc != NULL && fin != NULL)
871: (*closefunc)(fin);
872: if (bytes > 0)
1.10 millert 873: ptransfer(0);
1.1 deraadt 874: }
1.77 martynas 875: #endif /* !SMALL */
1.1 deraadt 876:
877: jmp_buf recvabort;
878:
1.57 deraadt 879: /* ARGSUSED */
1.1 deraadt 880: void
1.57 deraadt 881: abortrecv(int signo)
1.1 deraadt 882: {
883:
1.10 millert 884: alarmtimer(0);
1.1 deraadt 885: mflag = 0;
886: abrtflag = 0;
1.18 deraadt 887: fputs("\nreceive aborted\nwaiting for remote to finish abort.\n", ttyout);
888: (void)fflush(ttyout);
1.1 deraadt 889: longjmp(recvabort, 1);
890: }
891:
892: void
1.56 deraadt 893: recvrequest(const char *cmd, const char * volatile local, const char *remote,
894: const char *lmode, int printnames, int ignorespecial)
1.1 deraadt 895: {
1.40 millert 896: FILE * volatile fout, * volatile din;
1.42 millert 897: int (* volatile closefunc)(FILE *);
1.40 millert 898: volatile sig_t oldinti, oldintr, oldintp;
1.69 ray 899: int c, d, serrno;
1.20 millert 900: volatile int is_retr, tcrflag, bare_lfs;
901: static size_t bufsize;
1.1 deraadt 902: static char *buf;
1.20 millert 903: volatile off_t hashbytes;
1.1 deraadt 904: struct stat st;
1.10 millert 905: time_t mtime;
1.13 millert 906: int oprogress;
1.16 millert 907: int opreserve;
1.1 deraadt 908:
1.20 millert 909: fout = NULL;
910: din = NULL;
911: oldinti = NULL;
1.10 millert 912: hashbytes = mark;
913: direction = "received";
914: bytes = 0;
1.20 millert 915: bare_lfs = 0;
1.10 millert 916: filesize = -1;
1.13 millert 917: oprogress = progress;
1.16 millert 918: opreserve = preserve;
1.1 deraadt 919: is_retr = strcmp(cmd, "RETR") == 0;
920: if (is_retr && verbose && printnames) {
1.22 millert 921: if (local && (ignorespecial || *local != '-'))
1.18 deraadt 922: fprintf(ttyout, "local: %s ", local);
1.1 deraadt 923: if (remote)
1.18 deraadt 924: fprintf(ttyout, "remote: %s\n", remote);
1.1 deraadt 925: }
926: if (proxy && is_retr) {
927: proxtrans(cmd, local, remote);
928: return;
929: }
930: closefunc = NULL;
931: oldintr = NULL;
932: oldintp = NULL;
933: tcrflag = !crflag && is_retr;
934: if (setjmp(recvabort)) {
935: while (cpend) {
1.11 millert 936: (void)getreply(0);
1.1 deraadt 937: }
938: if (data >= 0) {
1.11 millert 939: (void)close(data);
1.1 deraadt 940: data = -1;
941: }
942: if (oldintr)
1.11 millert 943: (void)signal(SIGINT, oldintr);
1.10 millert 944: if (oldinti)
1.11 millert 945: (void)signal(SIGINFO, oldinti);
1.15 millert 946: progress = oprogress;
1.16 millert 947: preserve = opreserve;
1.1 deraadt 948: code = -1;
949: return;
950: }
951: oldintr = signal(SIGINT, abortrecv);
1.10 millert 952: oldinti = signal(SIGINFO, psummary);
1.22 millert 953: if (ignorespecial || (strcmp(local, "-") && *local != '|')) {
954: if (access(local, W_OK) < 0) {
1.69 ray 955: char *dir;
1.1 deraadt 956:
957: if (errno != ENOENT && errno != EACCES) {
958: warn("local: %s", local);
1.11 millert 959: (void)signal(SIGINT, oldintr);
960: (void)signal(SIGINFO, oldinti);
1.1 deraadt 961: code = -1;
962: return;
963: }
1.69 ray 964: dir = strrchr(local, '/');
1.1 deraadt 965: if (dir != NULL)
966: *dir = 0;
1.22 millert 967: d = access(dir == local ? "/" : dir ? local : ".", W_OK);
1.1 deraadt 968: if (dir != NULL)
969: *dir = '/';
970: if (d < 0) {
971: warn("local: %s", local);
1.11 millert 972: (void)signal(SIGINT, oldintr);
973: (void)signal(SIGINFO, oldinti);
1.1 deraadt 974: code = -1;
975: return;
976: }
977: if (!runique && errno == EACCES &&
1.20 millert 978: chmod(local, (S_IRUSR|S_IWUSR)) < 0) {
1.1 deraadt 979: warn("local: %s", local);
1.11 millert 980: (void)signal(SIGINT, oldintr);
981: (void)signal(SIGINFO, oldinti);
1.1 deraadt 982: code = -1;
983: return;
984: }
985: if (runique && errno == EACCES &&
986: (local = gunique(local)) == NULL) {
1.11 millert 987: (void)signal(SIGINT, oldintr);
988: (void)signal(SIGINFO, oldinti);
1.1 deraadt 989: code = -1;
990: return;
991: }
992: }
993: else if (runique && (local = gunique(local)) == NULL) {
1.11 millert 994: (void)signal(SIGINT, oldintr);
995: (void)signal(SIGINFO, oldinti);
1.1 deraadt 996: code = -1;
997: return;
998: }
999: }
1000: if (!is_retr) {
1001: if (curtype != TYPE_A)
1002: changetype(TYPE_A, 0);
1.10 millert 1003: } else {
1004: if (curtype != type)
1005: changetype(type, 0);
1006: filesize = remotesize(remote, 0);
1007: }
1.1 deraadt 1008: if (initconn()) {
1.11 millert 1009: (void)signal(SIGINT, oldintr);
1010: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1011: code = -1;
1012: return;
1013: }
1014: if (setjmp(recvabort))
1015: goto abort;
1016: if (is_retr && restart_point &&
1.58 sturm 1017: command("REST %lld", (long long) restart_point) != CONTINUE)
1.1 deraadt 1018: return;
1019: if (remote) {
1020: if (command("%s %s", cmd, remote) != PRELIM) {
1.11 millert 1021: (void)signal(SIGINT, oldintr);
1022: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1023: return;
1024: }
1025: } else {
1026: if (command("%s", cmd) != PRELIM) {
1.11 millert 1027: (void)signal(SIGINT, oldintr);
1028: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1029: return;
1030: }
1031: }
1032: din = dataconn("r");
1033: if (din == NULL)
1034: goto abort;
1.22 millert 1035: if (!ignorespecial && strcmp(local, "-") == 0) {
1.1 deraadt 1036: fout = stdout;
1.16 millert 1037: preserve = 0;
1.22 millert 1038: } else if (!ignorespecial && *local == '|') {
1.1 deraadt 1039: oldintp = signal(SIGPIPE, SIG_IGN);
1040: fout = popen(local + 1, "w");
1041: if (fout == NULL) {
1042: warn("%s", local+1);
1043: goto abort;
1044: }
1.31 millert 1045: if (progress == 1)
1046: progress = 0;
1.16 millert 1047: preserve = 0;
1.1 deraadt 1048: closefunc = pclose;
1049: } else {
1050: fout = fopen(local, lmode);
1051: if (fout == NULL) {
1052: warn("local: %s", local);
1053: goto abort;
1054: }
1055: closefunc = fclose;
1056: }
1057: if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
1058: st.st_blksize = BUFSIZ;
1059: if (st.st_blksize > bufsize) {
1.65 steven 1060: (void)free(buf);
1.1 deraadt 1061: buf = malloc((unsigned)st.st_blksize);
1062: if (buf == NULL) {
1063: warn("malloc");
1064: bufsize = 0;
1065: goto abort;
1066: }
1067: bufsize = st.st_blksize;
1068: }
1.14 millert 1069: if ((st.st_mode & S_IFMT) != S_IFREG) {
1.31 millert 1070: if (progress == 1)
1071: progress = 0;
1.13 millert 1072: preserve = 0;
1073: }
1.75 martynas 1074: progressmeter(-1, remote);
1.67 espie 1075: may_reset_noop_timeout();
1.1 deraadt 1076: switch (curtype) {
1077:
1078: case TYPE_I:
1079: case TYPE_L:
1080: if (restart_point &&
1081: lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1082: warn("local: %s", local);
1.13 millert 1083: progress = oprogress;
1.16 millert 1084: preserve = opreserve;
1.1 deraadt 1085: if (closefunc != NULL)
1086: (*closefunc)(fout);
1087: return;
1088: }
1089: errno = d = 0;
1090: while ((c = read(fileno(din), buf, bufsize)) > 0) {
1.57 deraadt 1091: ssize_t wr;
1.32 deraadt 1092: size_t rd = c;
1093:
1.67 espie 1094: may_send_noop_char();
1.32 deraadt 1095: d = 0;
1096: do {
1097: wr = write(fileno(fout), buf + d, rd);
1.84 jca 1098: if (wr == -1) {
1099: d = -1;
1.32 deraadt 1100: break;
1.84 jca 1101: }
1.32 deraadt 1102: d += wr;
1103: rd -= wr;
1104: } while (d < c);
1105: if (rd != 0)
1.1 deraadt 1106: break;
1107: bytes += c;
1.10 millert 1108: if (hash && (!progress || filesize < 0)) {
1.1 deraadt 1109: while (bytes >= hashbytes) {
1.18 deraadt 1110: (void)putc('#', ttyout);
1.7 kstailey 1111: hashbytes += mark;
1.1 deraadt 1112: }
1.18 deraadt 1113: (void)fflush(ttyout);
1.1 deraadt 1114: }
1115: }
1.69 ray 1116: if (c == -1 || d < c)
1117: serrno = errno;
1.10 millert 1118: if (hash && (!progress || filesize < 0) && bytes > 0) {
1.7 kstailey 1119: if (bytes < mark)
1.18 deraadt 1120: (void)putc('#', ttyout);
1121: (void)putc('\n', ttyout);
1122: (void)fflush(ttyout);
1.1 deraadt 1123: }
1124: if (c < 0) {
1.69 ray 1125: if (serrno != EPIPE)
1.86 guenther 1126: warnc(serrno, "netin");
1.1 deraadt 1127: bytes = -1;
1128: }
1129: if (d < c) {
1130: if (d < 0)
1.86 guenther 1131: warnc(serrno, "local: %s", local);
1.1 deraadt 1132: else
1133: warnx("%s: short write", local);
1134: }
1135: break;
1136:
1137: case TYPE_A:
1138: if (restart_point) {
1139: int i, n, ch;
1140:
1141: if (fseek(fout, 0L, SEEK_SET) < 0)
1142: goto done;
1143: n = restart_point;
1144: for (i = 0; i++ < n;) {
1.69 ray 1145: if ((ch = fgetc(fout)) == EOF) {
1146: if (!ferror(fout))
1147: errno = 0;
1.1 deraadt 1148: goto done;
1.69 ray 1149: }
1.1 deraadt 1150: if (ch == '\n')
1151: i++;
1152: }
1153: if (fseek(fout, 0L, SEEK_CUR) < 0) {
1154: done:
1.69 ray 1155: if (errno)
1156: warn("local: %s", local);
1157: else
1158: warnx("local: %s", local);
1.13 millert 1159: progress = oprogress;
1.16 millert 1160: preserve = opreserve;
1.1 deraadt 1161: if (closefunc != NULL)
1162: (*closefunc)(fout);
1163: return;
1164: }
1165: }
1.23 millert 1166: while ((c = fgetc(din)) != EOF) {
1.67 espie 1167: may_send_noop_char();
1.1 deraadt 1168: if (c == '\n')
1169: bare_lfs++;
1170: while (c == '\r') {
1.10 millert 1171: while (hash && (!progress || filesize < 0) &&
1172: (bytes >= hashbytes)) {
1.18 deraadt 1173: (void)putc('#', ttyout);
1174: (void)fflush(ttyout);
1.7 kstailey 1175: hashbytes += mark;
1.1 deraadt 1176: }
1177: bytes++;
1.23 millert 1178: if ((c = fgetc(din)) != '\n' || tcrflag) {
1.1 deraadt 1179: if (ferror(fout))
1180: goto break2;
1.11 millert 1181: (void)putc('\r', fout);
1.1 deraadt 1182: if (c == '\0') {
1183: bytes++;
1184: goto contin2;
1185: }
1186: if (c == EOF)
1187: goto contin2;
1188: }
1189: }
1.11 millert 1190: (void)putc(c, fout);
1.1 deraadt 1191: bytes++;
1192: contin2: ;
1193: }
1194: break2:
1.69 ray 1195: if (ferror(din) || ferror(fout))
1196: serrno = errno;
1.1 deraadt 1197: if (bare_lfs) {
1.22 millert 1198: fprintf(ttyout,
1.13 millert 1199: "WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
1.22 millert 1200: fputs("File may not have transferred correctly.\n",
1201: ttyout);
1.1 deraadt 1202: }
1.10 millert 1203: if (hash && (!progress || filesize < 0)) {
1.1 deraadt 1204: if (bytes < hashbytes)
1.18 deraadt 1205: (void)putc('#', ttyout);
1206: (void)putc('\n', ttyout);
1207: (void)fflush(ttyout);
1.1 deraadt 1208: }
1209: if (ferror(din)) {
1.69 ray 1210: if (serrno != EPIPE)
1.86 guenther 1211: warnc(serrno, "netin");
1.1 deraadt 1212: bytes = -1;
1213: }
1214: if (ferror(fout))
1.86 guenther 1215: warnc(serrno, "local: %s", local);
1.1 deraadt 1216: break;
1217: }
1.75 martynas 1218: progressmeter(1, NULL);
1.13 millert 1219: progress = oprogress;
1.16 millert 1220: preserve = opreserve;
1.1 deraadt 1221: if (closefunc != NULL)
1222: (*closefunc)(fout);
1.11 millert 1223: (void)signal(SIGINT, oldintr);
1224: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1225: if (oldintp)
1.11 millert 1226: (void)signal(SIGPIPE, oldintp);
1227: (void)fclose(din);
1228: (void)getreply(0);
1.67 espie 1229: may_receive_noop_ack();
1.10 millert 1230: if (bytes >= 0 && is_retr) {
1231: if (bytes > 0)
1232: ptransfer(0);
1233: if (preserve && (closefunc == fclose)) {
1234: mtime = remotemodtime(remote, 0);
1235: if (mtime != -1) {
1.12 millert 1236: struct utimbuf ut;
1237:
1238: ut.actime = time(NULL);
1239: ut.modtime = mtime;
1240: if (utime(local, &ut) == -1)
1.22 millert 1241: fprintf(ttyout,
1.13 millert 1242: "Can't change modification time on %s to %s",
1.11 millert 1243: local, asctime(localtime(&mtime)));
1.10 millert 1244: }
1245: }
1246: }
1.1 deraadt 1247: return;
1.13 millert 1248:
1.1 deraadt 1249: abort:
1.79 martynas 1250: /* abort using RFC959 recommended IP,SYNC sequence */
1.13 millert 1251: progress = oprogress;
1.16 millert 1252: preserve = opreserve;
1.1 deraadt 1253: if (oldintp)
1.11 millert 1254: (void)signal(SIGPIPE, oldintp);
1255: (void)signal(SIGINT, SIG_IGN);
1.1 deraadt 1256: if (!cpend) {
1257: code = -1;
1.11 millert 1258: (void)signal(SIGINT, oldintr);
1259: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1260: return;
1261: }
1262:
1263: abort_remote(din);
1264: code = -1;
1265: if (data >= 0) {
1.11 millert 1266: (void)close(data);
1.1 deraadt 1267: data = -1;
1268: }
1269: if (closefunc != NULL && fout != NULL)
1270: (*closefunc)(fout);
1271: if (din)
1.11 millert 1272: (void)fclose(din);
1.1 deraadt 1273: if (bytes > 0)
1.10 millert 1274: ptransfer(0);
1.11 millert 1275: (void)signal(SIGINT, oldintr);
1276: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1277: }
1278:
1279: /*
1280: * Need to start a listen on the data channel before we send the command,
1281: * otherwise the server's connect may fail.
1282: */
1283: int
1.56 deraadt 1284: initconn(void)
1.1 deraadt 1285: {
1286: char *p, *a;
1.57 deraadt 1287: int result = ERROR, tmpno = 0;
1.1 deraadt 1288: int on = 1;
1.34 itojun 1289: int error;
1290: u_int addr[16], port[2];
1291: u_int af, hal, pal;
1292: char *pasvcmd = NULL;
1.57 deraadt 1293: socklen_t namelen;
1.82 haesbaer 1294: struct addrinfo *ares;
1.34 itojun 1295:
1296: if (myctladdr.su_family == AF_INET6
1297: && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr)
1298: || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) {
1299: warnx("use of scoped address can be troublesome");
1300: }
1.82 haesbaer 1301: #ifndef SMALL
1302: if (srcaddr) {
1303: struct addrinfo ahints;
1304:
1305: memset(&ahints, 0, sizeof(ahints));
1306: ahints.ai_family = family;
1307: ahints.ai_socktype = SOCK_STREAM;
1308: ahints.ai_flags |= AI_NUMERICHOST;
1309: ahints.ai_protocol = 0;
1310:
1311: error = getaddrinfo(srcaddr, NULL, &ahints, &ares);
1312: if (error) {
1.86 guenther 1313: warnx("%s: %s", srcaddr, gai_strerror(error));
1.82 haesbaer 1314: code = -1;
1315: return (0);
1316: }
1317: }
1318: #endif /* !SMALL */
1.24 millert 1319: reinit:
1.1 deraadt 1320: if (passivemode) {
1.34 itojun 1321: data_addr = myctladdr;
1322: data = socket(data_addr.su_family, SOCK_STREAM, 0);
1.1 deraadt 1323: if (data < 0) {
1.10 millert 1324: warn("socket");
1325: return (1);
1.1 deraadt 1326: }
1.73 martynas 1327: #ifndef SMALL
1.82 haesbaer 1328: if (srcaddr) {
1329: if (bind(data, ares->ai_addr, ares->ai_addrlen) < 0) {
1330: warn("bind");
1331: close(data);
1332: return (1);
1333: }
1334: }
1.1 deraadt 1335: if ((options & SO_DEBUG) &&
1336: setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1.11 millert 1337: sizeof(on)) < 0)
1.10 millert 1338: warn("setsockopt (ignored)");
1.73 martynas 1339: #endif /* !SMALL */
1.34 itojun 1340: switch (data_addr.su_family) {
1341: case AF_INET:
1.36 itojun 1342: if (epsv4 && !epsv4bad) {
1.66 beck 1343: int ov;
1344: /* shut this command up in case it fails */
1345: ov = verbose;
1346: verbose = -1;
1.36 itojun 1347: result = command(pasvcmd = "EPSV");
1.66 beck 1348: /*
1349: * now back to whatever verbosity we had before
1350: * and we can try PASV
1351: */
1352: verbose = ov;
1.36 itojun 1353: if (code / 10 == 22 && code != 229) {
1354: fputs(
1.34 itojun 1355: "wrong server: return code must be 229\n",
1.36 itojun 1356: ttyout);
1357: result = COMPLETE + 1;
1358: }
1359: if (result != COMPLETE) {
1360: epsv4bad = 1;
1.73 martynas 1361: #ifndef SMALL
1.36 itojun 1362: if (debug) {
1363: fputs(
1364: "disabling epsv4 for this connection\n",
1365: ttyout);
1366: }
1.73 martynas 1367: #endif /* !SMALL */
1.36 itojun 1368: }
1.34 itojun 1369: }
1370: if (result != COMPLETE)
1371: result = command(pasvcmd = "PASV");
1372: break;
1373: case AF_INET6:
1374: result = command(pasvcmd = "EPSV");
1375: if (code / 10 == 22 && code != 229) {
1376: fputs(
1377: "wrong server: return code must be 229\n",
1378: ttyout);
1379: result = COMPLETE + 1;
1380: }
1381: if (result != COMPLETE)
1382: result = command(pasvcmd = "LPSV");
1383: break;
1384: default:
1385: result = COMPLETE + 1;
1386: break;
1387: }
1388: if (result != COMPLETE) {
1.24 millert 1389: if (activefallback) {
1390: (void)close(data);
1391: data = -1;
1392: passivemode = 0;
1393: activefallback = 0;
1394: goto reinit;
1395: }
1.18 deraadt 1396: fputs("Passive mode refused.\n", ttyout);
1.1 deraadt 1397: goto bad;
1398: }
1399:
1.34 itojun 1400: #define pack2(var, off) \
1401: (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0))
1402: #define pack4(var, off) \
1403: (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \
1404: ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0))
1405:
1.1 deraadt 1406: /*
1.34 itojun 1407: * What we've got at this point is a string of comma separated
1408: * one-byte unsigned integer values, separated by commas.
1.1 deraadt 1409: */
1.38 millert 1410: if (!pasvcmd)
1411: goto bad;
1.34 itojun 1412: if (strcmp(pasvcmd, "PASV") == 0) {
1413: if (data_addr.su_family != AF_INET) {
1414: fputs(
1415: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1416: goto bad;
1417: }
1418: if (code / 10 == 22 && code != 227) {
1419: fputs("wrong server: return code must be 227\n",
1420: ttyout);
1421: goto bad;
1422: }
1423: error = sscanf(pasv, "%u,%u,%u,%u,%u,%u",
1424: &addr[0], &addr[1], &addr[2], &addr[3],
1425: &port[0], &port[1]);
1426: if (error != 6) {
1427: fputs(
1428: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1429: goto bad;
1430: }
1431: memset(&data_addr, 0, sizeof(data_addr));
1432: data_addr.su_family = AF_INET;
1433: data_addr.su_len = sizeof(struct sockaddr_in);
1434: data_addr.su_sin.sin_addr.s_addr =
1435: htonl(pack4(addr, 0));
1436: data_addr.su_port = htons(pack2(port, 0));
1437: } else if (strcmp(pasvcmd, "LPSV") == 0) {
1438: if (code / 10 == 22 && code != 228) {
1439: fputs("wrong server: return code must be 228\n",
1440: ttyout);
1441: goto bad;
1442: }
1443: switch (data_addr.su_family) {
1444: case AF_INET:
1445: error = sscanf(pasv,
1446: "%u,%u,%u,%u,%u,%u,%u,%u,%u",
1447: &af, &hal,
1448: &addr[0], &addr[1], &addr[2], &addr[3],
1449: &pal, &port[0], &port[1]);
1450: if (error != 9) {
1451: fputs(
1452: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1453: goto bad;
1454: }
1455: if (af != 4 || hal != 4 || pal != 2) {
1456: fputs(
1457: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1458: error = 1;
1459: goto bad;
1460: }
1.1 deraadt 1461:
1.34 itojun 1462: memset(&data_addr, 0, sizeof(data_addr));
1463: data_addr.su_family = AF_INET;
1464: data_addr.su_len = sizeof(struct sockaddr_in);
1465: data_addr.su_sin.sin_addr.s_addr =
1466: htonl(pack4(addr, 0));
1467: data_addr.su_port = htons(pack2(port, 0));
1468: break;
1469: case AF_INET6:
1470: error = sscanf(pasv,
1471: "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
1472: &af, &hal,
1473: &addr[0], &addr[1], &addr[2], &addr[3],
1474: &addr[4], &addr[5], &addr[6], &addr[7],
1475: &addr[8], &addr[9], &addr[10],
1476: &addr[11], &addr[12], &addr[13],
1477: &addr[14], &addr[15],
1478: &pal, &port[0], &port[1]);
1479: if (error != 21) {
1480: fputs(
1.18 deraadt 1481: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1.34 itojun 1482: goto bad;
1483: }
1484: if (af != 6 || hal != 16 || pal != 2) {
1485: fputs(
1486: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1487: goto bad;
1488: }
1489:
1490: memset(&data_addr, 0, sizeof(data_addr));
1491: data_addr.su_family = AF_INET6;
1492: data_addr.su_len = sizeof(struct sockaddr_in6);
1493: {
1494: u_int32_t *p32;
1495: p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr;
1496: p32[0] = htonl(pack4(addr, 0));
1497: p32[1] = htonl(pack4(addr, 4));
1498: p32[2] = htonl(pack4(addr, 8));
1499: p32[3] = htonl(pack4(addr, 12));
1500: }
1501: data_addr.su_port = htons(pack2(port, 0));
1502: break;
1503: default:
1.85 tedu 1504: fputs("Bad family!\n", ttyout);
1505: goto bad;
1.34 itojun 1506: }
1507: } else if (strcmp(pasvcmd, "EPSV") == 0) {
1508: char delim[4];
1509:
1510: port[0] = 0;
1511: if (code / 10 == 22 && code != 229) {
1512: fputs("wrong server: return code must be 229\n",
1513: ttyout);
1514: goto bad;
1515: }
1516: if (sscanf(pasv, "%c%c%c%d%c", &delim[0],
1517: &delim[1], &delim[2], &port[1],
1518: &delim[3]) != 5) {
1519: fputs("parse error!\n", ttyout);
1520: goto bad;
1521: }
1522: if (delim[0] != delim[1] || delim[0] != delim[2]
1523: || delim[0] != delim[3]) {
1524: fputs("parse error!\n", ttyout);
1525: goto bad;
1526: }
1527: data_addr = hisctladdr;
1528: data_addr.su_port = htons(port[1]);
1529: } else
1.1 deraadt 1530: goto bad;
1531:
1.27 deraadt 1532: while (connect(data, (struct sockaddr *)&data_addr,
1.34 itojun 1533: data_addr.su_len) < 0) {
1.27 deraadt 1534: if (errno == EINTR)
1535: continue;
1.33 millert 1536: if (activefallback) {
1537: (void)close(data);
1538: data = -1;
1539: passivemode = 0;
1540: activefallback = 0;
1541: goto reinit;
1542: }
1.10 millert 1543: warn("connect");
1.1 deraadt 1544: goto bad;
1545: }
1.34 itojun 1546: #if defined(IPPROTO_IP) && defined(IP_TOS)
1547: if (data_addr.su_family == AF_INET) {
1548: on = IPTOS_THROUGHPUT;
1549: if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1550: sizeof(int)) < 0)
1551: warn("setsockopt TOS (ignored)");
1552: }
1.1 deraadt 1553: #endif
1.10 millert 1554: return (0);
1.1 deraadt 1555: }
1556:
1557: noport:
1558: data_addr = myctladdr;
1559: if (sendport)
1.34 itojun 1560: data_addr.su_port = 0; /* let system pick one */
1.1 deraadt 1561: if (data != -1)
1.11 millert 1562: (void)close(data);
1.34 itojun 1563: data = socket(data_addr.su_family, SOCK_STREAM, 0);
1.1 deraadt 1564: if (data < 0) {
1565: warn("socket");
1566: if (tmpno)
1567: sendport = 1;
1568: return (1);
1569: }
1570: if (!sendport)
1.10 millert 1571: if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
1.11 millert 1572: sizeof(on)) < 0) {
1.1 deraadt 1573: warn("setsockopt (reuse address)");
1574: goto bad;
1575: }
1.49 jakob 1576: switch (data_addr.su_family) {
1577: case AF_INET:
1578: on = IP_PORTRANGE_HIGH;
1579: if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE,
1580: (char *)&on, sizeof(on)) < 0)
1581: warn("setsockopt IP_PORTRANGE (ignored)");
1582: break;
1583: case AF_INET6:
1584: on = IPV6_PORTRANGE_HIGH;
1585: if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE,
1586: (char *)&on, sizeof(on)) < 0)
1587: warn("setsockopt IPV6_PORTRANGE (ignored)");
1588: break;
1589: }
1.34 itojun 1590: if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) {
1.1 deraadt 1591: warn("bind");
1592: goto bad;
1593: }
1.73 martynas 1594: #ifndef SMALL
1.1 deraadt 1595: if (options & SO_DEBUG &&
1.10 millert 1596: setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1.11 millert 1597: sizeof(on)) < 0)
1.1 deraadt 1598: warn("setsockopt (ignored)");
1.73 martynas 1599: #endif /* !SMALL */
1.57 deraadt 1600: namelen = sizeof(data_addr);
1601: if (getsockname(data, (struct sockaddr *)&data_addr, &namelen) < 0) {
1.1 deraadt 1602: warn("getsockname");
1603: goto bad;
1604: }
1605: if (listen(data, 1) < 0)
1606: warn("listen");
1.34 itojun 1607:
1608: #define UC(b) (((int)b)&0xff)
1609:
1.1 deraadt 1610: if (sendport) {
1.47 itojun 1611: char hname[NI_MAXHOST], pbuf[NI_MAXSERV];
1.64 ray 1612: int af_tmp;
1.47 itojun 1613: union sockunion tmp;
1.34 itojun 1614:
1.47 itojun 1615: tmp = data_addr;
1616: switch (tmp.su_family) {
1.34 itojun 1617: case AF_INET:
1.36 itojun 1618: if (!epsv4 || epsv4bad) {
1619: result = COMPLETE +1;
1620: break;
1621: }
1622: /*FALLTHROUGH*/
1.34 itojun 1623: case AF_INET6:
1.47 itojun 1624: if (tmp.su_family == AF_INET6)
1625: tmp.su_sin6.sin6_scope_id = 0;
1.64 ray 1626: af_tmp = (tmp.su_family == AF_INET) ? 1 : 2;
1.47 itojun 1627: if (getnameinfo((struct sockaddr *)&tmp,
1628: tmp.su_len, hname, sizeof(hname),
1629: pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
1.34 itojun 1630: result = ERROR;
1631: } else {
1.47 itojun 1632: result = command("EPRT |%d|%s|%s|",
1.64 ray 1633: af_tmp, hname, pbuf);
1.36 itojun 1634: if (result != COMPLETE) {
1635: epsv4bad = 1;
1.73 martynas 1636: #ifndef SMALL
1.36 itojun 1637: if (debug) {
1638: fputs(
1639: "disabling epsv4 for this connection\n",
1640: ttyout);
1641: }
1.73 martynas 1642: #endif /* !SMALL */
1.36 itojun 1643: }
1.34 itojun 1644: }
1645: break;
1646: default:
1647: result = COMPLETE + 1;
1648: break;
1649: }
1650: if (result == COMPLETE)
1651: goto skip_port;
1652:
1653: switch (data_addr.su_family) {
1654: case AF_INET:
1655: a = (char *)&data_addr.su_sin.sin_addr;
1656: p = (char *)&data_addr.su_port;
1657: result = command("PORT %d,%d,%d,%d,%d,%d",
1658: UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1659: UC(p[0]), UC(p[1]));
1660: break;
1661: case AF_INET6:
1662: a = (char *)&data_addr.su_sin6.sin6_addr;
1663: p = (char *)&data_addr.su_port;
1664: result = command(
1665: "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1666: 6, 16,
1667: UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
1668: UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
1669: UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
1670: UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
1671: 2, UC(p[0]), UC(p[1]));
1672: break;
1673: default:
1674: result = COMPLETE + 1; /* xxx */
1675: }
1676: skip_port:
1677:
1.1 deraadt 1678: if (result == ERROR && sendport == -1) {
1679: sendport = 0;
1680: tmpno = 1;
1681: goto noport;
1682: }
1683: return (result != COMPLETE);
1684: }
1685: if (tmpno)
1686: sendport = 1;
1.34 itojun 1687: #if defined(IPPROTO_IP) && defined(IP_TOS)
1688: if (data_addr.su_family == AF_INET) {
1689: on = IPTOS_THROUGHPUT;
1690: if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1691: sizeof(int)) < 0)
1692: warn("setsockopt TOS (ignored)");
1693: }
1.1 deraadt 1694: #endif
1695: return (0);
1696: bad:
1.11 millert 1697: (void)close(data), data = -1;
1.1 deraadt 1698: if (tmpno)
1699: sendport = 1;
1700: return (1);
1701: }
1702:
1703: FILE *
1.56 deraadt 1704: dataconn(const char *lmode)
1.1 deraadt 1705: {
1.34 itojun 1706: union sockunion from;
1.57 deraadt 1707: socklen_t fromlen = myctladdr.su_len;
1708: int s;
1.1 deraadt 1709:
1710: if (passivemode)
1711: return (fdopen(data, lmode));
1712:
1713: s = accept(data, (struct sockaddr *) &from, &fromlen);
1714: if (s < 0) {
1715: warn("accept");
1.11 millert 1716: (void)close(data), data = -1;
1.1 deraadt 1717: return (NULL);
1718: }
1.11 millert 1719: (void)close(data);
1.1 deraadt 1720: data = s;
1.34 itojun 1721: #if defined(IPPROTO_IP) && defined(IP_TOS)
1722: if (from.su_family == AF_INET) {
1723: int tos = IPTOS_THROUGHPUT;
1724: if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1725: sizeof(int)) < 0) {
1726: warn("setsockopt TOS (ignored)");
1727: }
1728: }
1.1 deraadt 1729: #endif
1730: return (fdopen(data, lmode));
1731: }
1732:
1.57 deraadt 1733: /* ARGSUSED */
1.1 deraadt 1734: void
1.57 deraadt 1735: psummary(int signo)
1.1 deraadt 1736: {
1.26 deraadt 1737: int save_errno = errno;
1.10 millert 1738:
1739: if (bytes > 0)
1740: ptransfer(1);
1.26 deraadt 1741: errno = save_errno;
1.1 deraadt 1742: }
1743:
1.57 deraadt 1744: /* ARGSUSED */
1.1 deraadt 1745: void
1.57 deraadt 1746: psabort(int signo)
1.1 deraadt 1747: {
1748:
1.10 millert 1749: alarmtimer(0);
1.1 deraadt 1750: abrtflag++;
1751: }
1752:
1753: void
1.56 deraadt 1754: pswitch(int flag)
1.1 deraadt 1755: {
1756: sig_t oldintr;
1757: static struct comvars {
1758: int connect;
1759: char name[MAXHOSTNAMELEN];
1.34 itojun 1760: union sockunion mctl;
1761: union sockunion hctl;
1.1 deraadt 1762: FILE *in;
1763: FILE *out;
1764: int tpe;
1765: int curtpe;
1766: int cpnd;
1767: int sunqe;
1768: int runqe;
1769: int mcse;
1770: int ntflg;
1771: char nti[17];
1772: char nto[17];
1773: int mapflg;
1774: char mi[MAXPATHLEN];
1775: char mo[MAXPATHLEN];
1776: } proxstruct, tmpstruct;
1777: struct comvars *ip, *op;
1778:
1779: abrtflag = 0;
1780: oldintr = signal(SIGINT, psabort);
1781: if (flag) {
1782: if (proxy)
1783: return;
1784: ip = &tmpstruct;
1785: op = &proxstruct;
1786: proxy++;
1787: } else {
1788: if (!proxy)
1789: return;
1790: ip = &proxstruct;
1791: op = &tmpstruct;
1792: proxy = 0;
1793: }
1794: ip->connect = connected;
1795: connected = op->connect;
1796: if (hostname) {
1.41 lebel 1797: (void)strlcpy(ip->name, hostname, sizeof(ip->name));
1.1 deraadt 1798: } else
1.11 millert 1799: ip->name[0] = '\0';
1.1 deraadt 1800: hostname = op->name;
1801: ip->hctl = hisctladdr;
1802: hisctladdr = op->hctl;
1803: ip->mctl = myctladdr;
1804: myctladdr = op->mctl;
1805: ip->in = cin;
1806: cin = op->in;
1807: ip->out = cout;
1808: cout = op->out;
1809: ip->tpe = type;
1810: type = op->tpe;
1811: ip->curtpe = curtype;
1812: curtype = op->curtpe;
1813: ip->cpnd = cpend;
1814: cpend = op->cpnd;
1815: ip->sunqe = sunique;
1816: sunique = op->sunqe;
1817: ip->runqe = runique;
1818: runique = op->runqe;
1819: ip->mcse = mcase;
1820: mcase = op->mcse;
1821: ip->ntflg = ntflag;
1822: ntflag = op->ntflg;
1.41 lebel 1823: (void)strlcpy(ip->nti, ntin, sizeof(ip->nti));
1.52 deraadt 1824: (void)strlcpy(ntin, op->nti, sizeof ntin);
1.41 lebel 1825: (void)strlcpy(ip->nto, ntout, sizeof(ip->nto));
1.52 deraadt 1826: (void)strlcpy(ntout, op->nto, sizeof ntout);
1.1 deraadt 1827: ip->mapflg = mapflag;
1828: mapflag = op->mapflg;
1.41 lebel 1829: (void)strlcpy(ip->mi, mapin, sizeof(ip->mi));
1.52 deraadt 1830: (void)strlcpy(mapin, op->mi, sizeof mapin);
1.41 lebel 1831: (void)strlcpy(ip->mo, mapout, sizeof(ip->mo));
1.52 deraadt 1832: (void)strlcpy(mapout, op->mo, sizeof mapout);
1.11 millert 1833: (void)signal(SIGINT, oldintr);
1.1 deraadt 1834: if (abrtflag) {
1835: abrtflag = 0;
1836: (*oldintr)(SIGINT);
1837: }
1838: }
1839:
1.57 deraadt 1840: /* ARGSUSED */
1.1 deraadt 1841: void
1.57 deraadt 1842: abortpt(int signo)
1.1 deraadt 1843: {
1844:
1.10 millert 1845: alarmtimer(0);
1.18 deraadt 1846: putc('\n', ttyout);
1847: (void)fflush(ttyout);
1.1 deraadt 1848: ptabflg++;
1849: mflag = 0;
1850: abrtflag = 0;
1851: longjmp(ptabort, 1);
1852: }
1853:
1854: void
1.56 deraadt 1855: proxtrans(const char *cmd, const char *local, const char *remote)
1.1 deraadt 1856: {
1.40 millert 1857: volatile sig_t oldintr;
1.20 millert 1858: int prox_type, nfnd;
1859: volatile int secndflag;
1.40 millert 1860: char * volatile cmd2;
1.54 millert 1861: struct pollfd pfd[1];
1.20 millert 1862:
1863: oldintr = NULL;
1864: secndflag = 0;
1.1 deraadt 1865: if (strcmp(cmd, "RETR"))
1866: cmd2 = "RETR";
1867: else
1868: cmd2 = runique ? "STOU" : "STOR";
1869: if ((prox_type = type) == 0) {
1870: if (unix_server && unix_proxy)
1871: prox_type = TYPE_I;
1872: else
1873: prox_type = TYPE_A;
1874: }
1875: if (curtype != prox_type)
1876: changetype(prox_type, 1);
1877: if (command("PASV") != COMPLETE) {
1.18 deraadt 1878: fputs("proxy server does not support third party transfers.\n",
1879: ttyout);
1.1 deraadt 1880: return;
1881: }
1882: pswitch(0);
1883: if (!connected) {
1.18 deraadt 1884: fputs("No primary connection.\n", ttyout);
1.1 deraadt 1885: pswitch(1);
1886: code = -1;
1887: return;
1888: }
1889: if (curtype != prox_type)
1890: changetype(prox_type, 1);
1891: if (command("PORT %s", pasv) != COMPLETE) {
1892: pswitch(1);
1893: return;
1894: }
1895: if (setjmp(ptabort))
1896: goto abort;
1897: oldintr = signal(SIGINT, abortpt);
1898: if (command("%s %s", cmd, remote) != PRELIM) {
1.11 millert 1899: (void)signal(SIGINT, oldintr);
1.1 deraadt 1900: pswitch(1);
1901: return;
1902: }
1903: sleep(2);
1904: pswitch(1);
1905: secndflag++;
1906: if (command("%s %s", cmd2, local) != PRELIM)
1907: goto abort;
1908: ptflag++;
1.11 millert 1909: (void)getreply(0);
1.1 deraadt 1910: pswitch(0);
1.11 millert 1911: (void)getreply(0);
1912: (void)signal(SIGINT, oldintr);
1.1 deraadt 1913: pswitch(1);
1914: ptflag = 0;
1.18 deraadt 1915: fprintf(ttyout, "local: %s remote: %s\n", local, remote);
1.1 deraadt 1916: return;
1917: abort:
1.11 millert 1918: (void)signal(SIGINT, SIG_IGN);
1.1 deraadt 1919: ptflag = 0;
1920: if (strcmp(cmd, "RETR") && !proxy)
1921: pswitch(1);
1922: else if (!strcmp(cmd, "RETR") && proxy)
1923: pswitch(0);
1924: if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1925: if (command("%s %s", cmd2, local) != PRELIM) {
1926: pswitch(0);
1927: if (cpend)
1.19 kstailey 1928: abort_remote(NULL);
1.1 deraadt 1929: }
1930: pswitch(1);
1931: if (ptabflg)
1932: code = -1;
1.11 millert 1933: (void)signal(SIGINT, oldintr);
1.1 deraadt 1934: return;
1935: }
1936: if (cpend)
1.19 kstailey 1937: abort_remote(NULL);
1.1 deraadt 1938: pswitch(!proxy);
1939: if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1940: if (command("%s %s", cmd2, local) != PRELIM) {
1941: pswitch(0);
1942: if (cpend)
1.19 kstailey 1943: abort_remote(NULL);
1.1 deraadt 1944: pswitch(1);
1945: if (ptabflg)
1946: code = -1;
1.11 millert 1947: (void)signal(SIGINT, oldintr);
1.1 deraadt 1948: return;
1949: }
1950: }
1951: if (cpend)
1.19 kstailey 1952: abort_remote(NULL);
1.1 deraadt 1953: pswitch(!proxy);
1954: if (cpend) {
1.54 millert 1955: pfd[0].fd = fileno(cin);
1956: pfd[0].events = POLLIN;
1957: if ((nfnd = poll(pfd, 1, 10 * 1000)) <= 0) {
1958: if (nfnd < 0)
1.1 deraadt 1959: warn("abort");
1960: if (ptabflg)
1961: code = -1;
1962: lostpeer();
1963: }
1.11 millert 1964: (void)getreply(0);
1965: (void)getreply(0);
1.1 deraadt 1966: }
1967: if (proxy)
1968: pswitch(0);
1969: pswitch(1);
1970: if (ptabflg)
1971: code = -1;
1.11 millert 1972: (void)signal(SIGINT, oldintr);
1.1 deraadt 1973: }
1974:
1.80 deraadt 1975: #ifndef SMALL
1.57 deraadt 1976: /* ARGSUSED */
1.1 deraadt 1977: void
1.56 deraadt 1978: reset(int argc, char *argv[])
1.1 deraadt 1979: {
1.54 millert 1980: struct pollfd pfd[1];
1.1 deraadt 1981: int nfnd = 1;
1982:
1.54 millert 1983: pfd[0].fd = fileno(cin);
1984: pfd[0].events = POLLIN;
1.1 deraadt 1985: while (nfnd > 0) {
1.54 millert 1986: if ((nfnd = poll(pfd, 1, 0)) < 0) {
1.1 deraadt 1987: warn("reset");
1988: code = -1;
1989: lostpeer();
1.54 millert 1990: } else if (nfnd) {
1.11 millert 1991: (void)getreply(0);
1.1 deraadt 1992: }
1993: }
1994: }
1.80 deraadt 1995: #endif
1.1 deraadt 1996:
1997: char *
1.56 deraadt 1998: gunique(const char *local)
1.1 deraadt 1999: {
2000: static char new[MAXPATHLEN];
2001: char *cp = strrchr(local, '/');
2002: int d, count=0;
2003: char ext = '1';
2004:
2005: if (cp)
2006: *cp = '\0';
1.22 millert 2007: d = access(cp == local ? "/" : cp ? local : ".", W_OK);
1.1 deraadt 2008: if (cp)
2009: *cp = '/';
2010: if (d < 0) {
2011: warn("local: %s", local);
2012: return ((char *) 0);
2013: }
1.52 deraadt 2014: (void)strlcpy(new, local, sizeof new);
1.1 deraadt 2015: cp = new + strlen(new);
2016: *cp++ = '.';
2017: while (!d) {
2018: if (++count == 100) {
1.18 deraadt 2019: fputs("runique: can't find unique file name.\n", ttyout);
1.1 deraadt 2020: return ((char *) 0);
2021: }
2022: *cp++ = ext;
2023: *cp = '\0';
2024: if (ext == '9')
2025: ext = '0';
2026: else
2027: ext++;
1.22 millert 2028: if ((d = access(new, F_OK)) < 0)
1.1 deraadt 2029: break;
2030: if (ext != '0')
2031: cp--;
2032: else if (*(cp - 2) == '.')
2033: *(cp - 1) = '1';
2034: else {
2035: *(cp - 2) = *(cp - 2) + 1;
2036: cp--;
2037: }
2038: }
2039: return (new);
2040: }
2041:
1.79 martynas 2042: jmp_buf forceabort;
2043:
2044: /* ARGSUSED */
1.83 deraadt 2045: static void
1.79 martynas 2046: abortforce(int signo)
2047: {
1.87 ! deraadt 2048: int save_errno = errno;
1.79 martynas 2049:
1.87 ! deraadt 2050: #define MSG "Forced abort. The connection will be closed.\n"
! 2051: (void) write(fileno(ttyout), MSG, strlen(MSG));
! 2052: #undef MSG
1.79 martynas 2053:
1.87 ! deraadt 2054: errno = save_errno;
1.79 martynas 2055: longjmp(forceabort, 1);
2056: }
2057:
1.1 deraadt 2058: void
1.56 deraadt 2059: abort_remote(FILE *din)
1.1 deraadt 2060: {
2061: char buf[BUFSIZ];
1.81 lum 2062: nfds_t nfds;
1.1 deraadt 2063: int nfnd;
1.54 millert 2064: struct pollfd pfd[2];
1.79 martynas 2065: sig_t oldintr;
1.13 millert 2066:
1.79 martynas 2067: if (cout == NULL || setjmp(forceabort)) {
1.87 ! deraadt 2068: if (cout)
! 2069: fclose(cout);
1.13 millert 2070: warnx("Lost control connection for abort.");
2071: if (ptabflg)
2072: code = -1;
2073: lostpeer();
2074: return;
2075: }
1.1 deraadt 2076:
1.79 martynas 2077: oldintr = signal(SIGINT, abortforce);
2078:
1.1 deraadt 2079: /*
2080: * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
2081: * after urgent byte rather than before as is protocol now
2082: */
1.46 deraadt 2083: snprintf(buf, sizeof buf, "%c%c%c", IAC, IP, IAC);
1.1 deraadt 2084: if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
2085: warn("abort");
1.10 millert 2086: fprintf(cout, "%cABOR\r\n", DM);
1.11 millert 2087: (void)fflush(cout);
1.54 millert 2088: pfd[0].fd = fileno(cin);
2089: pfd[0].events = POLLIN;
1.81 lum 2090: nfds = 1;
1.10 millert 2091: if (din) {
1.54 millert 2092: pfd[1].fd = fileno(din);
2093: pfd[1].events = POLLIN;
1.81 lum 2094: nfds++;
1.1 deraadt 2095: }
1.81 lum 2096: if ((nfnd = poll(pfd, nfds, 10 * 1000)) <= 0) {
1.54 millert 2097: if (nfnd < 0)
1.1 deraadt 2098: warn("abort");
2099: if (ptabflg)
2100: code = -1;
2101: lostpeer();
2102: }
1.54 millert 2103: if (din && (pfd[1].revents & POLLIN)) {
1.1 deraadt 2104: while (read(fileno(din), buf, BUFSIZ) > 0)
2105: /* LOOP */;
2106: }
2107: if (getreply(0) == ERROR && code == 552) {
2108: /* 552 needed for nic style abort */
1.11 millert 2109: (void)getreply(0);
1.1 deraadt 2110: }
1.11 millert 2111: (void)getreply(0);
1.79 martynas 2112: (void)signal(SIGINT, oldintr);
1.1 deraadt 2113: }