2 * Copyright (c) 1985, 1989 Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 static char sccsid[] = "@(#)ftp.c 5.38 (Berkeley) 4/22/91";
41 #include <sys/param.h>
43 #include <sys/ioctl.h>
44 #ifndef KRB5_KRB4_COMPAT
45 /* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
46 #include <sys/socket.h>
50 #ifdef HAVE_SYS_SELECT_H
51 #include <sys/select.h>
54 #include <netinet/in.h>
55 #include <netinet/in_systm.h>
56 #include <netinet/ip.h>
58 #include <arpa/telnet.h>
64 #ifndef KRB5_KRB4_COMPAT
65 /* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
71 #if (defined(__STDC__) && ! defined(VARARGS)) || defined(HAVE_STDARG_H)
88 #ifdef KRB5_KRB4_COMPAT
93 Key_schedule schedule;
95 #endif /* KRB5_KRB4_COMPAT */
97 #include <gssapi/gssapi.h>
98 #include <gssapi/gssapi_generic.h>
99 gss_ctx_id_t gcontext;
103 static int kerror; /* XXX needed for all auth types */
105 char *auth_type; /* Authentication succeeded? If so, what type? */
107 unsigned int maxbuf, actualbuf;
108 unsigned char *ucbuf;
113 #define sig_t my_sig_t
114 #define sigtype krb5_sigtype
115 typedef sigtype (*sig_t)();
117 struct sockaddr_in hisctladdr;
118 struct sockaddr_in hisdataaddr;
119 struct sockaddr_in data_addr;
123 struct sockaddr_in myctladdr;
126 off_t restart_point = 0;
128 #define strerror(error) (sys_errlist[error])
129 #ifdef NEED_SYS_ERRLIST
130 extern char *sys_errlist[];
133 extern int connected;
135 #define herror() printf("unknown host\n")
145 register struct hostent *hp = 0;
147 static char hostnamebuf[80];
149 memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
150 hisctladdr.sin_addr.s_addr = inet_addr(host);
151 if (hisctladdr.sin_addr.s_addr != -1) {
152 hisctladdr.sin_family = AF_INET;
153 (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
155 hp = gethostbyname(host);
157 fprintf(stderr, "ftp: %s: ", host);
162 hisctladdr.sin_family = hp->h_addrtype;
163 memcpy((caddr_t)&hisctladdr.sin_addr, hp->h_addr_list[0],
164 sizeof(hisctladdr.sin_addr));
165 (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
167 hostname = hostnamebuf;
168 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
170 perror("ftp: socket");
174 hisctladdr.sin_port = port;
175 while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
176 if (hp && hp->h_addr_list[1]) {
178 extern char *inet_ntoa();
180 fprintf(stderr, "ftp: connect to address %s: ",
181 inet_ntoa(hisctladdr.sin_addr));
185 memcpy((caddr_t)&hisctladdr.sin_addr,
187 sizeof(hisctladdr.sin_addr));
188 fprintf(stdout, "Trying %s...\n",
189 inet_ntoa(hisctladdr.sin_addr));
191 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
193 perror("ftp: socket");
199 perror("ftp: connect");
203 len = sizeof (myctladdr);
204 if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
205 perror("ftp: getsockname");
210 #ifdef IPTOS_LOWDELAY
211 tos = IPTOS_LOWDELAY;
212 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
213 perror("ftp: setsockopt TOS (ignored)");
216 cin = fdopen(s, "r");
217 cout = fdopen(s, "w");
218 if (cin == NULL || cout == NULL) {
219 fprintf(stderr, "ftp: fdopen failed.\n");
228 printf("Connected to %s.\n", hostname);
229 if (getreply(0) > 2) { /* read startup message from server */
241 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
243 perror("ftp: setsockopt");
246 #endif /* SO_OOBINLINE */
258 char *user, *pass, *acct, *getenv(), *getlogin(), *mygetpass();
261 user = pass = acct = 0;
262 if (ruserpass(host, &user, &pass, &acct) < 0) {
266 while (user == NULL) {
269 myname = getenv("LOGNAME");
271 myname = getenv("USER");
274 if (myname == NULL) {
275 struct passwd *pp = getpwuid(getuid());
278 myname = pp->pw_name;
281 printf("Name (%s:%s): ", host, myname);
283 printf("Name (%s): ", host);
284 (void) fgets(tmp, sizeof(tmp) - 1, stdin);
285 tmp[strlen(tmp) - 1] = '\0';
291 n = command("USER %s", user);
293 n = command("PASS dummy");
294 else if (n == CONTINUE) {
299 pass = mygetpass("Password:");
301 if ((oldlevel = level) == PROT_S) level = PROT_P;
303 n = command("PASS %s", pass);
305 /* level may have changed */
306 if (level == PROT_P) level = oldlevel;
311 acct = mygetpass("Account:");
312 n = command("ACCT %s", acct);
315 fprintf(stderr, "Login failed.\n");
318 if (!aflag && acct != NULL)
319 (void) command("ACCT %s", acct);
322 for (n = 0; n < macnum; ++n) {
323 if (!strcmp("init", macros[n].mac_name)) {
324 (void) strcpy(line, "$init");
326 domacro(margc, margv);
337 extern jmp_buf ptabort;
340 (void) fflush(stdout);
349 char in[FTP_BUFSIZ], out[FTP_BUFSIZ];
354 * File protection level also determines whether
355 * commands are MIC or ENC. Should be independent ...
357 #ifdef KRB5_KRB4_COMPAT
358 if (strcmp(auth_type, "KERBEROS_V4") == 0)
359 if ((length = level == PROT_P ?
360 krb_mk_priv((unsigned char *)cmd, (unsigned char *)out,
361 strlen(cmd), schedule,
362 &cred.session, &myctladdr, &hisctladdr)
363 : krb_mk_safe((unsigned char *)cmd, (unsigned char *)out,
364 strlen(cmd), &cred.session,
365 &myctladdr, &hisctladdr)) == -1) {
366 fprintf(stderr, "krb_mk_%s failed for KERBEROS_V4\n",
367 level == PROT_P ? "priv" : "safe");
370 #endif /* KRB5_KRB4_COMPAT */
372 /* secure_command (based on level) */
373 if (strcmp(auth_type, "GSSAPI") == 0) {
374 gss_buffer_desc in_buf, out_buf;
375 OM_uint32 maj_stat, min_stat;
377 /* level = PROT_P; */
379 in_buf.length = strlen(cmd) + 1;
380 maj_stat = gss_seal(&min_stat, gcontext,
381 (level==PROT_P), /* confidential */
383 &in_buf, &conf_state,
385 if (maj_stat != GSS_S_COMPLETE) {
386 /* generally need to deal */
387 user_gss_error(maj_stat, min_stat,
389 "gss_seal ENC didn't complete":
390 "gss_seal MIC didn't complete");
391 } else if ((level == PROT_P) && !conf_state) {
393 "GSSAPI didn't encrypt message");
396 fprintf(stderr, "sealed (%s) %d bytes\n",
397 level==PROT_P?"ENC":"MIC",
399 memcpy(out, out_buf.value,
400 length=out_buf.length);
401 gss_release_buffer(&min_stat, &out_buf);
405 /* Other auth types go here ... */
406 if (kerror = radix_encode(out, in, &length, 0)) {
407 fprintf(stderr,"Couldn't base 64 encode command (%s)\n",
408 radix_error(kerror));
411 fprintf(cout, "%s %s", level == PROT_P ? "ENC" : "MIC", in);
413 fprintf(stderr, "secure_command(%s)\nencoding %d bytes %s %s\n",
414 cmd, length, level==PROT_P ? "ENC" : "MIC", in);
415 } else fputs(cmd, cout);
416 fprintf(cout, "\r\n");
422 command(char *fmt, ...)
440 if (proxflag) printf("%s ", hostname);
446 fmt = va_arg(ap, char *);
448 if (strncmp("PASS ", fmt, 5) == 0)
451 vfprintf(stdout, fmt, ap);
454 (void) fflush(stdout);
457 perror ("No control connection for command");
461 oldintr = signal(SIGINT, cmdabort);
466 fmt = va_arg(ap, char *);
468 vsprintf(in, fmt, ap);
470 again: if (secure_command(in) == 0)
473 r = getreply(!strcmp(fmt, "QUIT"));
475 if (r == 533 && level == PROT_P) {
477 "ENC command not supported at server; retrying under MIC...\n");
482 if (abrtflag && oldintr != SIG_IGN)
484 (void) signal(SIGINT, oldintr);
488 char reply_string[FTP_BUFSIZ]; /* last line of previous reply */
490 /* for parsing replies to the ADAT command */
491 char *reply_parse, reply_buf[FTP_BUFSIZ], *reply_ptr;
498 register int i, c, n;
501 int originalcode = 0, continuation = 0;
506 char ibuf[FTP_BUFSIZ], obuf[FTP_BUFSIZ];
508 extern char *strpbrk(), *strstr();
511 if (reply_parse) reply_ptr = reply_buf;
512 oldintr = signal(SIGINT, cmdabort);
515 dig = n = code = i = 0;
517 while ((c = ibuf[0] ? ibuf[i++] : getc(cin)) != '\n') {
518 if (c == IAC) { /* handle telnet commands */
519 switch (c = getc(cin)) {
523 fprintf(cout, "%c%c%c", IAC, DONT, c);
529 fprintf(cout, "%c%c%c", IAC, WONT, c);
540 (void) signal(SIGINT,oldintr);
546 printf("421 Service not available, remote server has closed connection\n");
547 (void) fflush(stdout);
554 if (auth_type && !ibuf[0] &&
555 (n == '6' || continuation)) {
556 if (c != '\r' && dig > 4)
559 if (auth_type && !ibuf[0] && dig == 1 && verbose)
560 printf("Unauthenticated reply received from server:\n");
561 if (reply_parse) *reply_ptr++ = c;
562 if (c != '\r' && (verbose > 0 ||
563 (verbose > -1 && n == '5' && dig > 4))) {
565 (dig == 1 || dig == 5 && verbose == 0))
566 printf("%s:",hostname);
570 if (auth_type && !ibuf[0] && n != '6') continue;
571 if (dig < 4 && isdigit(c))
572 code = code * 10 + (c - '0');
573 if (!pflag && code == 227)
575 if (dig > 4 && pflag == 1 && isdigit(c))
578 if (c != '\r' && c != ')')
585 if (dig == 4 && c == '-' && n != '6') {
590 if (cp < &reply_string[sizeof(reply_string) - 1])
593 if (auth_type && !ibuf[0] && n != '6')
594 return(getreply(expecteof));
595 ibuf[0] = obuf[i] = '\0';
596 if (code && n == '6')
597 if (code != 631 && code != 632 && code != 633) {
598 printf("Unknown reply: %d %s\n", code, obuf);
600 } else safe = (code == 631);
601 if (obuf[0]) /* if there is a string to decode */
603 printf("Cannot decode reply:\n%d %s\n", code, obuf);
607 else if (code == 632) {
608 printf("Cannot decrypt %d reply: %s\n", code, obuf);
612 #ifdef NOCONFIDENTIAL
613 else if (code == 633) {
614 printf("Cannot decrypt %d reply: %s\n", code, obuf);
620 if (kerror = radix_encode(obuf, ibuf, &len, 1)) {
621 printf("Can't base 64 decode reply %d (%s)\n\"%s\"\n",
622 code, radix_error(kerror), obuf);
625 #ifdef KRB5_KRB4_COMPAT
626 else if (strcmp(auth_type, "KERBEROS_V4") == 0)
628 krb_rd_safe((unsigned char *)ibuf, len,
630 &hisctladdr, &myctladdr, &msg_data)
631 : krb_rd_priv((unsigned char *)ibuf, len,
632 schedule, &cred.session,
633 &hisctladdr, &myctladdr, &msg_data))
635 printf("%d reply %s! (krb_rd_%s: %s)\n", code,
636 safe ? "modified" : "garbled",
637 safe ? "safe" : "priv",
638 krb_get_err_text(kerror));
641 if (debug) printf("%c:", safe ? 'S' : 'P');
642 memcpy(ibuf, msg_data.app_data,
643 msg_data.app_length);
644 strcpy(&ibuf[msg_data.app_length], "\r\n");
649 else if (strcmp(auth_type, "GSSAPI") == 0) {
650 gss_buffer_desc xmit_buf, msg_buf;
651 OM_uint32 maj_stat, min_stat;
653 xmit_buf.value = ibuf;
654 xmit_buf.length = len;
655 /* decrypt/verify the message */
657 maj_stat = gss_unseal(&min_stat, gcontext,
660 if (maj_stat != GSS_S_COMPLETE) {
661 user_gss_error(maj_stat, min_stat,
662 "failed unsealing reply");
665 memcpy(ibuf, msg_buf.value,
667 strcpy(&ibuf[msg_buf.length], "\r\n");
668 gss_release_buffer(&min_stat,&msg_buf);
673 /* Other auth types go here... */
676 if (verbose > 0 || verbose > -1 && n == '5') {
678 (void) fflush (stdout);
680 if (continuation && code != originalcode) {
681 if (originalcode == 0)
688 (void) signal(SIGINT,oldintr);
689 if (code == 421 || originalcode == 421)
691 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
695 if (reply_ptr = strstr(reply_buf, reply_parse)) {
696 reply_parse = reply_ptr + strlen(reply_parse);
697 if (reply_ptr = strpbrk(reply_parse, " \r"))
699 } else reply_parse = reply_ptr;
711 t.tv_sec = (long) sec;
713 return(select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
725 printf("\nsend aborted\nwaiting for remote to finish abort\n");
726 (void) fflush(stdout);
727 longjmp(sendabort, 1);
731 secure_error(char *fmt, ...)
734 secure_error(fmt, p1, p2, p3, p4, p5)
742 vfprintf(stderr, fmt, ap);
745 fprintf(stderr, fmt, p1, p2, p3, p4, p5);
750 #define HASHBYTES 1024
752 sendrequest(cmd, local, remote, printnames)
753 char *cmd, *local, *remote;
757 struct timeval start, stop;
759 FILE *fin, *dout = 0, *popen();
760 int (*closefunc)(), pclose(), fclose();
761 sig_t oldintr, oldintp;
762 long bytes = 0, hashbytes = HASHBYTES;
763 char *lmode, buf[FTP_BUFSIZ], *bufp;
766 if (verbose && printnames) {
767 if (local && *local != '-')
768 printf("local: %s ", local);
770 printf("remote: %s\n", remote);
773 proxtrans(cmd, local, remote);
782 if (setjmp(sendabort)) {
791 (void) signal(SIGINT,oldintr);
793 (void) signal(SIGPIPE,oldintp);
797 oldintr = signal(SIGINT, abortsend);
798 if (strcmp(local, "-") == 0)
800 else if (*local == '|') {
801 oldintp = signal(SIGPIPE,SIG_IGN);
802 fin = popen(local + 1, "r");
805 (void) signal(SIGINT, oldintr);
806 (void) signal(SIGPIPE, oldintp);
812 fin = fopen(local, "r");
814 fprintf(stderr, "local: %s: %s\n", local,
816 (void) signal(SIGINT, oldintr);
821 if (fstat(fileno(fin), &st) < 0 ||
822 (st.st_mode&S_IFMT) != S_IFREG) {
823 fprintf(stdout, "%s: not a plain file.\n", local);
824 (void) signal(SIGINT, oldintr);
831 (void) signal(SIGINT, oldintr);
833 (void) signal(SIGPIPE, oldintp);
835 if (closefunc != NULL)
839 if (setjmp(sendabort))
843 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
844 if (fseek(fin, (long) restart_point, 0) < 0) {
845 fprintf(stderr, "local: %s: %s\n", local,
848 if (closefunc != NULL)
852 if (command("REST %ld", (long) restart_point)
855 if (closefunc != NULL)
863 if (command("%s %s", cmd, remote) != PRELIM) {
864 (void) signal(SIGINT, oldintr);
866 (void) signal(SIGPIPE, oldintp);
867 if (closefunc != NULL)
872 if (command("%s", cmd) != PRELIM) {
873 (void) signal(SIGINT, oldintr);
875 (void) signal(SIGPIPE, oldintp);
876 if (closefunc != NULL)
880 dout = dataconn(lmode);
883 (void) gettimeofday(&start, (struct timezone *)0);
884 oldintp = signal(SIGPIPE, SIG_IGN);
890 while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
892 for (bufp = buf; c > 0; c -= d, bufp += d)
893 if ((d = secure_write(fileno(dout), bufp, c)) <= 0)
896 while (bytes >= hashbytes) {
898 hashbytes += HASHBYTES;
900 (void) fflush(stdout);
905 if (hash && bytes > 0) {
906 if (bytes < HASHBYTES)
908 (void) putchar('\n');
909 (void) fflush(stdout);
912 fprintf(stderr, "local: %s: %s\n", local,
914 if (d < 0 || (d = secure_flush(fileno(dout))) < 0) {
915 if (d == -1 && errno != EPIPE)
922 while ((c = getc(fin)) != EOF) {
924 while (hash && (bytes >= hashbytes)) {
926 (void) fflush(stdout);
927 hashbytes += HASHBYTES;
930 secure_putc('\r', dout) < 0)
934 if (secure_putc(c, dout) < 0)
937 /* if (c == '\r') { */
938 /* (void) putc('\0', dout); /* this violates rfc */
943 if (bytes < hashbytes)
945 (void) putchar('\n');
946 (void) fflush(stdout);
949 fprintf(stderr, "local: %s: %s\n", local,
952 if (ferror(dout) || (d = secure_flush(fileno(dout))) < 0) {
953 if ((ferror(dout) || d == -1) && errno != EPIPE)
959 (void) gettimeofday(&stop, (struct timezone *)0);
960 if (closefunc != NULL)
964 (void) signal(SIGINT, oldintr);
966 (void) signal(SIGPIPE, oldintp);
968 ptransfer("sent", bytes, &start, &stop);
971 (void) gettimeofday(&stop, (struct timezone *)0);
972 (void) signal(SIGINT, oldintr);
974 (void) signal(SIGPIPE, oldintp);
987 if (closefunc != NULL && fin != NULL)
990 ptransfer("sent", bytes, &start, &stop);
1002 printf("\nreceive aborted\nwaiting for remote to finish abort\n");
1003 (void) fflush(stdout);
1004 longjmp(recvabort, 1);
1007 recvrequest(cmd, local, remote, lmode, printnames)
1008 char *cmd, *local, *remote, *lmode;
1010 FILE *fout, *din = 0, *popen();
1011 int (*closefunc)(), pclose(), fclose();
1012 sig_t oldintr, oldintp;
1013 int is_retr, tcrflag, bare_lfs = 0;
1018 long bytes = 0, hashbytes = HASHBYTES;
1020 struct timeval start, stop;
1023 sigtype abortrecv();
1025 is_retr = strcmp(cmd, "RETR") == 0;
1026 if (is_retr && verbose && printnames) {
1027 if (local && *local != '-')
1028 printf("local: %s ", local);
1030 printf("remote: %s\n", remote);
1032 if (proxy && is_retr) {
1033 proxtrans(cmd, local, remote);
1039 tcrflag = !crflag && is_retr;
1040 if (setjmp(recvabort)) {
1049 (void) signal(SIGINT, oldintr);
1053 oldintr = signal(SIGINT, abortrecv);
1054 if (strcmp(local, "-") && *local != '|') {
1055 if (access(local, 2) < 0) {
1056 char *dir = strrchr(local, '/');
1058 if (errno != ENOENT && errno != EACCES) {
1059 fprintf(stderr, "local: %s: %s\n", local,
1061 (void) signal(SIGINT, oldintr);
1067 d = access(dir ? local : ".", 2);
1071 fprintf(stderr, "local: %s: %s\n", local,
1073 (void) signal(SIGINT, oldintr);
1077 if (!runique && errno == EACCES &&
1078 chmod(local, 0600) < 0) {
1079 fprintf(stderr, "local: %s: %s\n", local,
1081 (void) signal(SIGINT, oldintr);
1082 (void) signal(SIGINT, oldintr);
1086 if (runique && errno == EACCES &&
1087 (local = gunique(local)) == NULL) {
1088 (void) signal(SIGINT, oldintr);
1093 else if (runique && (local = gunique(local)) == NULL) {
1094 (void) signal(SIGINT, oldintr);
1100 if (curtype != TYPE_A)
1101 changetype(TYPE_A, 0);
1102 } else if (curtype != type)
1103 changetype(type, 0);
1105 (void) signal(SIGINT, oldintr);
1109 if (setjmp(recvabort))
1111 if (is_retr && restart_point &&
1112 command("REST %ld", (long) restart_point) != CONTINUE)
1115 if (command("%s %s", cmd, remote) != PRELIM) {
1116 (void) signal(SIGINT, oldintr);
1120 if (command("%s", cmd) != PRELIM) {
1121 (void) signal(SIGINT, oldintr);
1125 din = dataconn("r");
1128 if (strcmp(local, "-") == 0)
1130 else if (*local == '|') {
1131 oldintp = signal(SIGPIPE, SIG_IGN);
1132 fout = popen(local + 1, "w");
1139 fout = fopen(local, lmode);
1141 fprintf(stderr, "local: %s: %s\n", local,
1147 blksize = FTP_BUFSIZ;
1149 if (fstat(fileno(fout), &st) == 0 && st.st_blksize != 0)
1150 blksize = st.st_blksize;
1152 if (blksize > bufsize) {
1155 buf = (char *)malloc((unsigned)blksize);
1163 (void) gettimeofday(&start, (struct timezone *)0);
1168 if (restart_point &&
1169 lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
1170 fprintf(stderr, "local: %s: %s\n", local,
1172 if (closefunc != NULL)
1177 while ((c = secure_read(fileno(din), buf, bufsize)) > 0) {
1178 if ((d = write(fileno(fout), buf, c)) != c)
1182 while (bytes >= hashbytes) {
1183 (void) putchar('#');
1184 hashbytes += HASHBYTES;
1186 (void) fflush(stdout);
1189 if (hash && bytes > 0) {
1190 if (bytes < HASHBYTES)
1191 (void) putchar('#');
1192 (void) putchar('\n');
1193 (void) fflush(stdout);
1196 if (c == -1 && errno != EPIPE)
1202 fprintf(stderr, "local: %s: %s\n", local,
1205 fprintf(stderr, "%s: short write\n", local);
1210 if (restart_point) {
1211 register int i, n, ch;
1213 if (fseek(fout, 0L, L_SET) < 0)
1216 for (i = 0; i++ < n;) {
1217 if ((ch = getc(fout)) == EOF)
1222 if (fseek(fout, 0L, L_INCR) < 0) {
1224 fprintf(stderr, "local: %s: %s\n", local,
1226 if (closefunc != NULL)
1231 while ((c = secure_getc(din)) >= 0) {
1235 while (hash && (bytes >= hashbytes)) {
1236 (void) putchar('#');
1237 (void) fflush(stdout);
1238 hashbytes += HASHBYTES;
1241 if ((c = secure_getc(din)) != '\n' || tcrflag) {
1244 (void) putc('\r', fout);
1252 (void) putc(c, fout);
1258 printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
1259 printf("File may not have transferred correctly.\n");
1262 if (bytes < hashbytes)
1263 (void) putchar('#');
1264 (void) putchar('\n');
1265 (void) fflush(stdout);
1272 if (ferror(fout) || c == -2) {
1274 fprintf(stderr, "local: %s: %s\n", local,
1280 if (closefunc != NULL)
1282 (void) signal(SIGINT, oldintr);
1284 (void) signal(SIGPIPE, oldintp);
1285 (void) gettimeofday(&stop, (struct timezone *)0);
1288 if (bytes > 0 && is_retr)
1289 ptransfer("received", bytes, &start, &stop);
1293 /* abort using RFC959 recommended IP,SYNC sequence */
1295 (void) gettimeofday(&stop, (struct timezone *)0);
1297 (void) signal(SIGPIPE, oldintr);
1298 (void) signal(SIGINT, SIG_IGN);
1301 (void) signal(SIGINT, oldintr);
1311 if (closefunc != NULL && fout != NULL)
1316 ptransfer("received", bytes, &start, &stop);
1317 (void) signal(SIGINT, oldintr);
1321 * Need to start a listen on the data channel before we send the command,
1322 * otherwise the server's connect may fail.
1326 register char *p, *a;
1327 int result, len, tmpno = 0;
1329 #ifndef NO_PASSIVE_MODE
1330 int a1,a2,a3,a4,p1,p2;
1333 data = socket(AF_INET, SOCK_STREAM, 0);
1335 perror("ftp: socket");
1338 if (options & SO_DEBUG &&
1339 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1340 perror("ftp: setsockopt (ignored)");
1341 if (command("PASV") != COMPLETE) {
1342 printf("Passive mode refused. Turning off passive mode.\n");
1348 * What we've got at this point is a string of comma separated
1349 * one-byte unsigned integer values, separated by commas.
1350 * The first four are the an IP address. The fifth is the MSB
1351 * of the port number, the sixth is the LSB. From that we'll
1352 * prepare a sockaddr_in.
1355 if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",&a1,&a2,&a3,&a4,&p1,&p2) != 6) {
1356 printf("Passive mode address scan failure. Shouldn't happen!\n");
1360 data_addr.sin_family = AF_INET;
1361 data_addr.sin_addr.s_addr = htonl((a1<<24)|(a2<<16)|(a3<<8)|a4);
1362 data_addr.sin_port = htons((p1<<8)|p2);
1364 if (connect(data, (struct sockaddr *) &data_addr, sizeof(data_addr))<0) {
1365 perror("ftp: connect");
1369 #ifdef IPTOS_THROUGHPUT
1370 on = IPTOS_THROUGHPUT;
1371 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1372 perror("ftp: setsockopt TOS (ignored)");
1375 hisdataaddr = data_addr;
1381 data_addr = myctladdr;
1383 data_addr.sin_port = 0; /* let system pick one */
1386 data = socket(AF_INET, SOCK_STREAM, 0);
1388 perror("ftp: socket");
1394 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1395 perror("ftp: setsockopt (reuse address)");
1398 if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1399 perror("ftp: bind");
1402 if (options & SO_DEBUG &&
1403 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1404 perror("ftp: setsockopt (ignored)");
1405 len = sizeof (data_addr);
1406 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
1407 perror("ftp: getsockname");
1410 if (listen(data, 1) < 0)
1411 perror("ftp: listen");
1413 a = (char *)&data_addr.sin_addr;
1414 p = (char *)&data_addr.sin_port;
1415 #define UC(b) (((int)b)&0xff)
1417 command("PORT %d,%d,%d,%d,%d,%d",
1418 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1419 UC(p[0]), UC(p[1]));
1420 if (result == ERROR && sendport == -1) {
1425 return (result != COMPLETE);
1430 #ifdef IPTOS_THROUGHPUT
1431 on = IPTOS_THROUGHPUT;
1432 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1433 perror("ftp: setsockopt TOS (ignored)");
1438 (void) close(data), data = -1;
1448 int s, fromlen = sizeof (hisdataaddr), tos;
1450 #ifndef NO_PASSIVE_MODE
1452 return (fdopen(data, lmode));
1454 s = accept(data, (struct sockaddr *) &hisdataaddr, &fromlen);
1456 perror("ftp: accept");
1457 (void) close(data), data = -1;
1463 #ifdef IPTOS_THROUGHPUT
1464 tos = IPTOS_THROUGHPUT;
1465 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
1466 perror("ftp: setsockopt TOS (ignored)");
1469 return (fdopen(data, lmode));
1472 ptransfer(direction, bytes, t0, t1)
1475 struct timeval *t0, *t1;
1482 s = td.tv_sec + (td.tv_usec / 1000000.);
1483 #define nz(x) ((x) == 0 ? 1 : (x))
1484 kbs = (bytes / nz(s))/1024.0;
1485 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
1486 bytes, direction, s, kbs);
1491 struct timeval *tsum, *t0;
1494 tsum->tv_sec += t0->tv_sec;
1495 tsum->tv_usec += t0->tv_usec;
1496 if (tsum->tv_usec > 1000000)
1497 tsum->tv_sec++, tsum->tv_usec -= 1000000;
1500 tvsub(tdiff, t1, t0)
1501 struct timeval *tdiff, *t1, *t0;
1504 tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1505 tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1506 if (tdiff->tv_usec < 0)
1507 tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1514 extern int abrtflag;
1522 extern int proxy, abrtflag;
1524 static struct comvars {
1526 char name[MAXHOSTNAMELEN];
1527 struct sockaddr_in mctl;
1528 struct sockaddr_in hctl;
1541 char mi[MAXPATHLEN];
1542 char mo[MAXPATHLEN];
1545 #ifdef KRB5_KRB4_COMPAT
1547 Key_schedule schedule;
1548 #endif /* KRB5_KRB4_COMPAT */
1549 } proxstruct, tmpstruct;
1550 struct comvars *ip, *op;
1553 oldintr = signal(SIGINT, psabort);
1567 ip->connect = connected;
1568 connected = op->connect;
1570 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1571 ip->name[strlen(ip->name)] = '\0';
1574 hostname = op->name;
1575 ip->hctl = hisctladdr;
1576 hisctladdr = op->hctl;
1577 ip->mctl = myctladdr;
1578 myctladdr = op->mctl;
1585 ip->curtpe = curtype;
1586 curtype = op->curtpe;
1589 ip->sunqe = sunique;
1590 sunique = op->sunqe;
1591 ip->runqe = runique;
1592 runique = op->runqe;
1597 (void) strncpy(ip->nti, ntin, 16);
1598 (ip->nti)[strlen(ip->nti)] = '\0';
1599 (void) strcpy(ntin, op->nti);
1600 (void) strncpy(ip->nto, ntout, 16);
1601 (ip->nto)[strlen(ip->nto)] = '\0';
1602 (void) strcpy(ntout, op->nto);
1603 ip->mapflg = mapflag;
1604 mapflag = op->mapflg;
1605 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1606 (ip->mi)[strlen(ip->mi)] = '\0';
1607 (void) strcpy(mapin, op->mi);
1608 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1609 (ip->mo)[strlen(ip->mo)] = '\0';
1610 (void) strcpy(mapout, op->mo);
1611 ip->authtype = auth_type;
1612 auth_type = op->authtype;
1617 #ifdef KRB5_KRB4_COMPAT
1618 memcpy(ip->session, cred.session, sizeof(cred.session));
1619 memcpy(cred.session, op->session, sizeof(cred.session));
1620 memcpy(ip->schedule, schedule, sizeof(schedule));
1621 memcpy(schedule, op->schedule, sizeof(schedule));
1622 #endif /* KRB5_KRB4_COMPAT */
1623 (void) signal(SIGINT, oldintr);
1638 (void) fflush(stdout);
1642 longjmp(ptabort, 1);
1645 proxtrans(cmd, local, remote)
1646 char *cmd, *local, *remote;
1649 int secndflag = 0, prox_type, nfnd;
1650 extern jmp_buf ptabort;
1655 if (strcmp(cmd, "RETR"))
1658 cmd2 = runique ? "STOU" : "STOR";
1659 if ((prox_type = type) == 0) {
1660 if (unix_server && unix_proxy)
1665 if (curtype != prox_type)
1666 changetype(prox_type, 1);
1667 if (command("PASV") != COMPLETE) {
1668 printf("proxy server does not support third party transfers.\n");
1673 printf("No primary connection\n");
1678 if (curtype != prox_type)
1679 changetype(prox_type, 1);
1680 if (command("PORT %s", pasv) != COMPLETE) {
1684 if (setjmp(ptabort))
1686 oldintr = signal(SIGINT, abortpt);
1687 if (command("%s %s", cmd, remote) != PRELIM) {
1688 (void) signal(SIGINT, oldintr);
1695 if (command("%s %s", cmd2, local) != PRELIM)
1701 (void) signal(SIGINT, oldintr);
1704 printf("local: %s remote: %s\n", local, remote);
1707 (void) signal(SIGINT, SIG_IGN);
1709 if (strcmp(cmd, "RETR") && !proxy)
1711 else if (!strcmp(cmd, "RETR") && proxy)
1713 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1714 if (command("%s %s", cmd2, local) != PRELIM) {
1717 abort_remote((FILE *) NULL);
1722 (void) signal(SIGINT, oldintr);
1726 abort_remote((FILE *) NULL);
1728 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1729 if (command("%s %s", cmd2, local) != PRELIM) {
1732 abort_remote((FILE *) NULL);
1736 (void) signal(SIGINT, oldintr);
1741 abort_remote((FILE *) NULL);
1745 FD_SET(fileno(cin), &mask);
1746 if ((nfnd = empty(&mask, 10)) <= 0) {
1762 (void) signal(SIGINT, oldintr);
1772 FD_SET(fileno(cin), &mask);
1773 if ((nfnd = empty(&mask,0)) < 0) {
1788 static char new[MAXPATHLEN];
1789 char *cp = strrchr(local, '/');
1795 d = access(cp ? local : ".", 2);
1799 fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
1802 (void) strcpy(new, local);
1803 cp = new + strlen(new);
1806 if (++count == 100) {
1807 printf("runique: can't find unique file name.\n");
1816 if ((d = access(new, 0)) < 0)
1820 else if (*(cp - 2) == '.')
1823 *(cp - 2) = *(cp - 2) + 1;
1830 #ifdef KRB5_KRB4_COMPAT
1831 char realm[REALM_SZ + 1];
1832 #endif /* KRB5_KRB4_COMPAT */
1835 /* for testing, we don't have an ftp key yet */
1836 char* gss_services[] = { "ftp", "host", 0 };
1841 extern int setsafe();
1842 int oldverbose = verbose;
1843 #ifdef KRB5_KRB4_COMPAT
1844 char *service, inst[INST_SZ];
1845 u_long cksum, checksum = (u_long) getpid();
1846 #endif /* KRB5_KRB4_COMPAT */
1847 #if defined(KRB5_KRB4_COMPAT) || defined(GSSAPI)
1848 u_char out_buf[FTP_BUFSIZ];
1850 #endif /* KRB5_KRB4_COMPAT */
1852 if (auth_type) return(1); /* auth already succeeded */
1854 /* Other auth types go here ... */
1857 if (command("AUTH %s", "GSSAPI") == CONTINUE) {
1858 OM_uint32 maj_stat, min_stat;
1859 gss_name_t target_name;
1860 gss_buffer_desc send_tok, recv_tok, *token_ptr;
1861 char stbuf[FTP_BUFSIZ];
1862 char **service_name, **end_service_name;
1864 struct gss_channel_bindings_struct chan;
1865 chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32 */
1866 chan.initiator_address.length = 4;
1867 chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
1868 chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
1869 chan.acceptor_address.length = 4;
1870 chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
1871 chan.application_data.length = 0;
1872 chan.application_data.value = 0;
1874 for (end_service_name = gss_services; *end_service_name; )
1879 printf("%s accepted as authentication type\n", "GSSAPI");
1881 /* blob from gss-client */
1884 for (service_name = gss_services; *service_name; service_name++) {
1886 /* ftp@hostname first, the host@hostname */
1887 /* the V5 GSSAPI binding canonicalizes this for us... */
1888 sprintf(stbuf, "%s@%s", *service_name, hostname);
1890 fprintf(stderr, "Trying to authenticate to <%s>\n", stbuf);
1892 send_tok.value = stbuf;
1893 send_tok.length = strlen(stbuf) + 1;
1894 maj_stat = gss_import_name(&min_stat, &send_tok,
1895 gss_nt_service_name, &target_name);
1897 if (maj_stat != GSS_S_COMPLETE) {
1898 user_gss_error(maj_stat, min_stat, "parsing name");
1899 secure_error("name parsed <%s>\n", stbuf);
1903 token_ptr = GSS_C_NO_BUFFER;
1904 gcontext = GSS_C_NO_CONTEXT; /* structure copy */
1908 fprintf(stderr, "calling gss_init_sec_context\n");
1910 gss_init_sec_context(&min_stat,
1911 GSS_C_NO_CREDENTIAL,
1915 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
1916 (forward ? GSS_C_DELEG_FLAG : 0),
1918 &chan, /* channel bindings */
1920 NULL, /* ignore mech type */
1922 NULL, /* ignore ret_flags */
1923 NULL); /* ignore time_rec */
1926 if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED){
1927 if (service_name == end_service_name)
1928 user_gss_error(maj_stat, min_stat, "initializing context");
1929 (void) gss_release_name(&min_stat, &target_name);
1930 /* could just be that we missed on the service name */
1934 if (send_tok.length != 0) {
1935 int len = send_tok.length;
1936 reply_parse = "ADAT="; /* for command() later */
1937 oldverbose = verbose;
1939 kerror = radix_encode(send_tok.value, out_buf, &len, 0);
1941 fprintf(stderr, "Base 64 encoding failed: %s\n",
1942 radix_error(kerror));
1943 } else if ((comcode = command("ADAT %s", out_buf))!=COMPLETE
1944 /* && comcode != 3 (335)*/) {
1945 fprintf(stderr, "GSSAPI ADAT failed\n");
1946 /* force out of loop */
1947 maj_stat = GSS_S_FAILURE;
1948 } else if (!reply_parse) {
1950 "No authentication data received from server\n");
1951 if (maj_stat == GSS_S_COMPLETE) {
1952 fprintf(stderr, "...but no more was needed\n");
1953 goto gss_complete_loop;
1955 user_gss_error(maj_stat, min_stat, "no reply, huh?");
1956 goto gss_complete_loop;
1958 } else if (kerror = radix_encode(reply_parse,out_buf,&i,1)) {
1959 fprintf(stderr, "Base 64 decoding failed: %s\n",
1960 radix_error(kerror));
1962 /* everything worked */
1963 token_ptr = &recv_tok;
1964 recv_tok.value = out_buf;
1965 recv_tok.length = i;
1969 /* get out of loop clean */
1971 service_name = end_service_name;
1972 gss_release_buffer(&min_stat, &send_tok);
1973 gss_release_name(&min_stat, &target_name);
1976 } while (maj_stat == GSS_S_CONTINUE_NEEDED);
1978 if (maj_stat == GSS_S_COMPLETE)
1981 verbose = oldverbose;
1982 if (maj_stat == GSS_S_COMPLETE) {
1984 printf("GSSAPI authentication succeeded\n");
1986 auth_type = "GSSAPI";
1989 fprintf(stderr, "GSSAPI authentication failed\n");
1990 verbose = oldverbose;
1995 #ifdef KRB5_KRB4_COMPAT
1996 if (command("AUTH %s", "KERBEROS_V4") == CONTINUE) {
1998 printf("%s accepted as authentication type\n", "KERBEROS_V4");
2000 strcpy(inst, (char *) krb_get_phost(hostname));
2001 if (realm[0] == '\0')
2002 strcpy(realm, (char *) krb_realmofhost(hostname));
2003 if ((kerror = krb_mk_req(&ticket, service = "ftp",
2004 inst, realm, checksum))
2005 && (kerror != KDC_PR_UNKNOWN ||
2006 (kerror = krb_mk_req(&ticket, service = "rcmd",
2007 inst, realm, checksum))))
2008 fprintf(stderr, "Kerberos V4 krb_mk_req failed: %s\n",
2009 krb_get_err_text(kerror));
2010 else if (kerror = krb_get_cred(service, inst, realm, &cred))
2011 fprintf(stderr, "Kerberos V4 krb_get_cred failed: %s\n",
2012 krb_get_err_text(kerror));
2014 key_sched(cred.session, schedule);
2015 reply_parse = "ADAT=";
2016 oldverbose = verbose;
2019 if (kerror = radix_encode(ticket.dat, out_buf, &i, 0))
2020 fprintf(stderr, "Base 64 encoding failed: %s\n",
2021 radix_error(kerror));
2022 else if (command("ADAT %s", out_buf) != COMPLETE)
2023 fprintf(stderr, "Kerberos V4 authentication failed\n");
2024 else if (!reply_parse)
2026 "No authentication data received from server\n");
2027 else if (kerror = radix_encode(reply_parse, out_buf, &i, 1))
2028 fprintf(stderr, "Base 64 decoding failed: %s\n",
2029 radix_error(kerror));
2030 else if (kerror = krb_rd_safe(out_buf, i, &cred.session,
2031 &hisctladdr, &myctladdr, &msg_data))
2032 fprintf(stderr, "Kerberos V4 krb_rd_safe failed: %s\n",
2033 krb_get_err_text(kerror));
2035 /* fetch the (modified) checksum */
2036 (void) memcpy(&cksum, msg_data.app_data, sizeof(cksum));
2037 if (ntohl(cksum) == checksum + 1) {
2038 verbose = oldverbose;
2040 printf("Kerberos V4 authentication succeeded\n");
2042 auth_type = "KERBEROS_V4";
2044 } else fprintf(stderr,
2045 "Kerberos V4 mutual authentication failed\n");
2047 verbose = oldverbose;
2050 } else fprintf(stderr, "%s rejected as an authentication type\n",
2052 #endif /* KRB5_KRB4_COMPAT */
2054 /* Other auth types go here ... */
2064 if (ucbuf) (void) free(ucbuf);
2066 while ((ucbuf = (unsigned char *)malloc(actualbuf)) == NULL)
2070 perror("Error while trying to malloc PROT buffer:");
2073 oldverbose = verbose;
2075 reply_parse = "PBSZ=";
2076 if (command("PBSZ %u", actualbuf) != COMPLETE)
2077 fatal("Cannot set PROT buffer size");
2079 if ((maxbuf = (unsigned int) atol(reply_parse)) > actualbuf)
2081 } else maxbuf = actualbuf;
2083 verbose = oldverbose;
2089 char buf[FTP_BUFSIZ];
2094 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
2095 * after urgent byte rather than before as is protocol now
2097 sprintf(buf, "%c%c%c", IAC, IP, IAC);
2098 if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
2101 (void) secure_command("ABOR");
2103 FD_SET(fileno(cin), &mask);
2105 FD_SET(fileno(din), &mask);
2107 if ((nfnd = empty(&mask, 10)) <= 0) {
2115 if (din && FD_ISSET(fileno(din), &mask)) {
2116 /* Security: No threat associated with this read. */
2117 while (read(fileno(din), buf, FTP_BUFSIZ) > 0)
2120 if (getreply(0) == ERROR && code == 552) {
2121 /* 552 needed for nic style abort */
2127 user_gss_error(maj_stat, min_stat, s)
2128 OM_uint32 maj_stat, min_stat;
2131 /* a lot of work just to report the error */
2132 OM_uint32 gmaj_stat, gmin_stat;
2133 gss_buffer_desc msg;
2137 gmaj_stat = gss_display_status(&gmin_stat, maj_stat,
2141 if ((gmaj_stat == GSS_S_COMPLETE)||
2142 (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
2143 fprintf(stderr, "GSSAPI error major: %s\n",
2145 (void) gss_release_buffer(&gmin_stat, &msg);
2147 if (gmaj_stat != GSS_S_CONTINUE_NEEDED)
2152 gmaj_stat = gss_display_status(&gmin_stat, min_stat,
2156 if ((gmaj_stat == GSS_S_COMPLETE)||
2157 (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
2158 fprintf(stderr, "GSSAPI error minor: %s\n",
2160 (void) gss_release_buffer(&gmin_stat, &msg);
2162 if (gmaj_stat != GSS_S_CONTINUE_NEEDED)
2165 fprintf(stderr, "GSSAPI error: %s\n", s);
2168 secure_gss_error(maj_stat, min_stat, s)
2169 OM_uint32 maj_stat, min_stat;
2172 return user_gss_error(maj_stat, min_stat, s);