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 * Copyright (C) 1998 by the FundsXpress, INC.
37 * All rights reserved.
39 * Export of this software from the United States of America may require
40 * a specific license from the United States Government. It is the
41 * responsibility of any person or organization contemplating export to
42 * obtain such a license before exporting.
44 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
45 * distribute this software and its documentation for any purpose and
46 * without fee is hereby granted, provided that the above copyright
47 * notice appear in all copies and that both that copyright notice and
48 * this permission notice appear in supporting documentation, and that
49 * the name of FundsXpress. not be used in advertising or publicity pertaining
50 * to distribution of the software without specific, written prior
51 * permission. FundsXpress makes no representations about the suitability of
52 * this software for any purpose. It is provided "as is" without express
53 * or implied warranty.
55 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
56 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
57 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
61 static char sccsid[] = "@(#)ftp.c 5.38 (Berkeley) 4/22/91";
67 #include <sys/timeb.h>
74 #define pclose _pclose
75 #define sleep(secs) Sleep(secs * 1000)
76 int gettimeofday(struct timeval *tv, void *tz);
88 #include <sys/param.h>
90 #include <sys/ioctl.h>
91 #ifndef KRB5_KRB4_COMPAT
92 /* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
93 #include <sys/socket.h>
98 #ifdef HAVE_SYS_SELECT_H
99 #include <sys/select.h>
102 #include <netinet/in.h>
103 #include <netinet/in_systm.h>
104 #include <netinet/ip.h>
108 #include <arpa/ftp.h>
109 #include <arpa/telnet.h>
118 #include <port-sockets.h>
127 #ifdef KRB5_KRB4_COMPAT
132 Key_schedule schedule;
134 #endif /* KRB5_KRB4_COMPAT */
136 #include <gssapi/gssapi.h>
137 /* need to include the krb5 file, because we're doing manual fallback
138 from the v2 mech to the v2 mech. Once there's real negotiation,
139 we can be generic again. */
140 #include <gssapi/gssapi_generic.h>
141 #include <gssapi/gssapi_krb5.h>
142 gss_ctx_id_t gcontext;
145 static int kerror; /* XXX needed for all auth types */
147 char *auth_type; /* Authentication succeeded? If so, what type? */
149 unsigned int maxbuf, actualbuf;
150 unsigned char *ucbuf;
157 void user_gss_error (OM_uint32, OM_uint32, char *);
160 static void proxtrans (char *, char *, char *);
161 static int initconn (void);
162 static void ptransfer (char *, long, struct timeval *, struct timeval *);
163 static void abort_remote (FILE *);
164 static void tvsub (struct timeval *, struct timeval *, struct timeval *);
165 static char *gunique (char *);
167 struct sockaddr_in hisctladdr;
168 struct sockaddr_in hisdataaddr;
169 struct sockaddr_in data_addr;
173 struct sockaddr_in myctladdr;
178 off_t restart_point = 0;
181 #ifndef HAVE_STRERROR
182 #define strerror(error) (sys_errlist[error])
183 #ifdef NEED_SYS_ERRLIST
184 extern char *sys_errlist[];
188 extern int connected;
190 #define herror() printf("unknown host\n")
193 FILE *dataconn (char *);
196 hookup(char* host, int port)
198 register struct hostent *hp = 0;
202 #ifdef IPTOS_LOWDELAY
206 static char hostnamebuf[80];
208 memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
209 hisctladdr.sin_addr.s_addr = inet_addr(host);
210 if (hisctladdr.sin_addr.s_addr != -1) {
211 hisctladdr.sin_family = AF_INET;
212 (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
214 hp = gethostbyname(host);
216 fprintf(stderr, "ftp: %s: ", host);
221 hisctladdr.sin_family = hp->h_addrtype;
222 memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0],
223 sizeof(hisctladdr.sin_addr));
224 (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
226 hostname = hostnamebuf;
227 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
228 if (s == INVALID_SOCKET) {
229 PERROR_SOCKET("ftp: socket");
233 hisctladdr.sin_port = port;
234 while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) == SOCKET_ERROR) {
235 if (hp && hp->h_addr_list[1]) {
236 int oerrno = SOCKET_ERRNO;
238 extern char *inet_ntoa();
240 fprintf(stderr, "ftp: connect to address %s: ",
241 inet_ntoa(hisctladdr.sin_addr));
242 SOCKET_SET_ERRNO(oerrno);
243 PERROR_SOCKET((char *) 0);
245 memcpy(&hisctladdr.sin_addr,
247 sizeof(hisctladdr.sin_addr));
248 fprintf(stdout, "Trying %s...\n",
249 inet_ntoa(hisctladdr.sin_addr));
250 (void) closesocket(s);
251 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
252 if (s == INVALID_SOCKET) {
253 PERROR_SOCKET("ftp: socket");
259 PERROR_SOCKET("ftp: connect");
263 len = sizeof (myctladdr);
264 if (getsockname(s, (struct sockaddr *)&myctladdr, &len) == SOCKET_ERROR) {
265 PERROR_SOCKET("ftp: getsockname");
270 #ifdef IPTOS_LOWDELAY
271 tos = IPTOS_LOWDELAY;
272 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) == SOCKET_ERROR) {
273 PERROR_SOCKET("ftp: setsockopt TOS (ignored)");
277 cin = FDOPEN_SOCKET(s, "r");
278 cout = FDOPEN_SOCKET(s, "w");
279 if (cin == NULL || cout == NULL) {
280 fprintf(stderr, "ftp: fdopen failed.\n");
282 (void) FCLOSE_SOCKET(cin);
286 (void) FCLOSE_SOCKET(cout);
293 printf("Connected to %s.\n", hostname);
294 if (getreply(0) > 2) { /* read startup message from server */
296 (void) FCLOSE_SOCKET(cin);
300 (void) FCLOSE_SOCKET(cout);
310 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
311 == SOCKET_ERROR && debug) {
312 PERROR_SOCKET("ftp: setsockopt");
315 #endif /* SO_OOBINLINE */
319 (void) closesocket(s);
323 int login(char *host)
326 char *l_user, *pass, *l_acct, *getenv(), *getlogin();
329 l_user = pass = l_acct = 0;
330 if (ruserpass(host, &l_user, &pass, &l_acct) < 0) {
334 while (l_user == NULL) {
337 myname = getenv("LOGNAME");
339 myname = getenv("USER");
343 if (myname == NULL) {
344 struct passwd *pp = getpwuid(getuid());
347 myname = pp->pw_name;
350 if (myname == NULL) {
351 static char buffer[200];
352 int len = sizeof(buffer);
353 if (GetUserName(buffer, &len))
356 myname = "<Unknown>";
360 printf("Name (%s:%s): ", host, myname);
362 printf("Name (%s): ", host);
363 (void) fgets(tmp, sizeof(tmp) - 1, stdin);
364 tmp[strlen(tmp) - 1] = '\0';
370 n = command("USER %s", l_user);
372 /* determine if we need to send a dummy password */
373 int oldverbose = verbose;
376 if (command("PWD") != COMPLETE) {
377 verbose = oldverbose;
378 command("PASS dummy");
380 verbose = oldverbose;
383 else if (n == CONTINUE) {
388 pass = mygetpass("Password:");
393 n = command("PASS %s", pass);
395 /* level may have changed */
396 if (clevel == PROT_P) clevel = oldclevel;
401 l_acct = mygetpass("Account:");
402 n = command("ACCT %s", l_acct);
405 fprintf(stderr, "Login failed.\n");
408 if (!aflag && l_acct != NULL)
409 (void) command("ACCT %s", l_acct);
412 for (n = 0; n < macnum; ++n) {
413 if (!strcmp("init", macros[n].mac_name)) {
414 (void) strcpy(line, "$init");
416 domacro(margc, margv);
427 (void) fflush(stdout);
433 static int secure_command(char* cmd)
435 unsigned char in[FTP_BUFSIZ], out[FTP_BUFSIZ];
438 if (auth_type && clevel != PROT_C) {
439 #ifdef KRB5_KRB4_COMPAT
440 if (strcmp(auth_type, "KERBEROS_V4") == 0)
441 if ((length = clevel == PROT_P ?
442 krb_mk_priv((unsigned char *)cmd, (unsigned char *)out,
443 strlen(cmd), schedule,
444 &cred.session, &myctladdr, &hisctladdr)
445 : krb_mk_safe((unsigned char *)cmd, (unsigned char *)out,
446 strlen(cmd), &cred.session,
447 &myctladdr, &hisctladdr)) == -1) {
448 fprintf(stderr, "krb_mk_%s failed for KERBEROS_V4\n",
449 clevel == PROT_P ? "priv" : "safe");
452 #endif /* KRB5_KRB4_COMPAT */
454 /* secure_command (based on level) */
455 if (strcmp(auth_type, "GSSAPI") == 0) {
456 gss_buffer_desc in_buf, out_buf;
457 OM_uint32 maj_stat, min_stat;
459 /* clevel = PROT_P; */
461 in_buf.length = strlen(cmd) + 1;
462 maj_stat = gss_seal(&min_stat, gcontext,
463 (clevel==PROT_P), /* private */
465 &in_buf, &conf_state,
467 if (maj_stat != GSS_S_COMPLETE) {
468 /* generally need to deal */
469 user_gss_error(maj_stat, min_stat,
471 "gss_seal ENC didn't complete":
472 "gss_seal MIC didn't complete");
473 } else if ((clevel == PROT_P) && !conf_state) {
475 "GSSAPI didn't encrypt message");
478 fprintf(stderr, "sealed (%s) %d bytes\n",
479 clevel==PROT_P?"ENC":"MIC",
481 length=out_buf.length;
482 memcpy(out, out_buf.value, out_buf.length);
483 gss_release_buffer(&min_stat, &out_buf);
487 /* Other auth types go here ... */
488 kerror = radix_encode(out, in, &length, 0);
490 fprintf(stderr,"Couldn't base 64 encode command (%s)\n",
491 radix_error(kerror));
494 fprintf(cout, "%s %s", clevel == PROT_P ? "ENC" : "MIC", in);
496 fprintf(stderr, "secure_command(%s)\nencoding %d bytes %s %s\n",
497 cmd, length, clevel==PROT_P ? "ENC" : "MIC", in);
498 } else fputs(cmd, cout);
499 fprintf(cout, "\r\n");
504 int command(char *fmt, ...)
513 if (proxflag) printf("%s ", hostname);
516 if (strncmp("PASS ", fmt, 5) == 0)
519 vfprintf(stdout, fmt, ap);
522 (void) fflush(stdout);
525 perror ("No control connection for command");
529 oldintr = signal(SIGINT, cmdabort);
531 vsprintf(in, fmt, ap);
533 again: if (secure_command(in) == 0)
536 r = getreply(!strcmp(fmt, "QUIT"));
538 if (r == 533 && clevel == PROT_P) {
540 "ENC command not supported at server; retrying under MIC...\n");
545 if (abrtflag && oldintr && oldintr != SIG_IGN)
547 (void) signal(SIGINT, oldintr);
551 char reply_string[FTP_BUFSIZ]; /* last line of previous reply */
553 /* for parsing replies to the ADAT command */
554 char *reply_parse, reply_buf[FTP_BUFSIZ], *reply_ptr;
558 int getreply(int expecteof)
560 register int i, c, n;
563 int originalcode = 0, continuation = 0;
567 char ibuf[FTP_BUFSIZ], obuf[FTP_BUFSIZ];
570 extern char *strpbrk();
573 extern char *strstr();
577 if (reply_parse) reply_ptr = reply_buf;
578 oldintr = signal(SIGINT, cmdabort);
581 dig = n = code = i = 0;
583 while ((c = ibuf[0] ? ibuf[i++] : getc(cin)) != '\n') {
584 if (c == IAC) { /* handle telnet commands */
585 switch (c = getc(cin)) {
589 fprintf(cout, "%c%c%c", IAC, DONT, c);
595 fprintf(cout, "%c%c%c", IAC, WONT, c);
606 (void) signal(SIGINT,oldintr);
612 printf("421 Service not available, remote server has closed connection\n");
613 (void) fflush(stdout);
620 if (auth_type && !ibuf[0] &&
621 (n == '6' || continuation)) {
622 if (c != '\r' && dig > 4)
625 if (auth_type && !ibuf[0] && dig == 1 && verbose)
626 printf("Unauthenticated reply received from server:\n");
627 if (reply_parse) *reply_ptr++ = c;
628 if (c != '\r' && (verbose > 0 ||
629 (verbose > -1 && n == '5' && dig > 4))) {
631 (dig == 1 || (dig == 5 && verbose == 0)))
632 printf("%s:",hostname);
636 if (auth_type && !ibuf[0] && n != '6') continue;
637 if (dig < 4 && isdigit(c))
638 code = code * 10 + (c - '0');
639 if (!pflag && code == 227)
641 if (dig > 4 && pflag == 1 && isdigit(c))
644 if (c != '\r' && c != ')')
651 if (dig == 4 && c == '-' && n != '6') {
656 if (cp < &reply_string[sizeof(reply_string) - 1])
659 if (auth_type && !ibuf[0] && n != '6')
660 return(getreply(expecteof));
661 ibuf[0] = obuf[i] = '\0';
662 if (code && n == '6') {
663 if (code != 631 && code != 632 && code != 633) {
664 printf("Unknown reply: %d %s\n", code, obuf);
666 } else safe = (code == 631);
668 if (obuf[0]) /* if there is a string to decode */
670 printf("Cannot decode reply:\n%d %s\n", code, obuf);
674 else if (code == 632) {
675 printf("Cannot decrypt %d reply: %s\n", code, obuf);
679 #ifdef NOCONFIDENTIAL
680 else if (code == 633) {
681 printf("Cannot decrypt %d reply: %s\n", code, obuf);
687 kerror = radix_encode((unsigned char *)obuf,
688 (unsigned char *)ibuf,
691 printf("Can't base 64 decode reply %d (%s)\n\"%s\"\n",
692 code, radix_error(kerror), obuf);
695 #ifdef KRB5_KRB4_COMPAT
696 else if (strcmp(auth_type, "KERBEROS_V4") == 0) {
698 kerror = krb_rd_safe((unsigned char *)ibuf,
702 &myctladdr, &msg_data);
704 kerror = krb_rd_priv((unsigned char *)ibuf,
706 schedule, &cred.session,
707 &hisctladdr, &myctladdr,
709 if (kerror != KSUCCESS) {
710 printf("%d reply %s! (krb_rd_%s: %s)\n", code,
711 safe ? "modified" : "garbled",
712 safe ? "safe" : "priv",
713 krb_get_err_text(kerror));
716 if (debug) printf("%c:", safe ? 'S' : 'P');
717 if(msg_data.app_length < sizeof(ibuf) - 2) {
718 memmove(ibuf, msg_data.app_data,
719 msg_data.app_length);
720 strcpy(&ibuf[msg_data.app_length], "\r\n");
722 printf("Message too long!");
729 else if (strcmp(auth_type, "GSSAPI") == 0) {
730 gss_buffer_desc xmit_buf, msg_buf;
731 OM_uint32 maj_stat, min_stat;
733 xmit_buf.value = ibuf;
734 xmit_buf.length = len;
735 /* decrypt/verify the message */
737 maj_stat = gss_unseal(&min_stat, gcontext,
740 if (maj_stat != GSS_S_COMPLETE) {
741 user_gss_error(maj_stat, min_stat,
742 "failed unsealing reply");
745 if(msg_buf.length < sizeof(ibuf) - 2 - 1) {
746 memcpy(ibuf, msg_buf.value,
748 strcpy(&ibuf[msg_buf.length], "\r\n");
750 user_gss_error(maj_stat, min_stat,
751 "reply was too long");
753 gss_release_buffer(&min_stat,&msg_buf);
758 /* Other auth types go here... */
761 if (verbose > 0 || (verbose > -1 && n == '5')) {
763 (void) fflush (stdout);
765 if (continuation && code != originalcode) {
766 if (originalcode == 0)
773 (void) signal(SIGINT,oldintr);
774 if (code == 421 || originalcode == 421)
776 if (abrtflag && oldintr && oldintr != cmdabort && oldintr != SIG_IGN)
780 reply_ptr = strstr(reply_buf, reply_parse);
782 reply_parse = reply_ptr + strlen(reply_parse);
783 reply_ptr = strpbrk(reply_parse, " \r");
786 } else reply_parse = reply_ptr;
792 static int empty(fd_set *mask, int sec)
796 t.tv_sec = (long) sec;
798 return(select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
809 printf("\nsend aborted\nwaiting for remote to finish abort\n");
810 (void) fflush(stdout);
811 longjmp(sendabort, 1);
814 void secure_error(char *fmt, ...)
819 vfprintf(stderr, fmt, ap);
824 #define HASHBYTES 1024
826 void sendrequest(char *cmd, char *local, char *remote, int printnames)
829 struct timeval start, stop;
831 FILE *volatile fin, *volatile dout = 0;
832 int (*volatile closefunc)();
833 volatile sig_t oldintr, oldintp;
834 volatile long bytes = 0, hashbytes = HASHBYTES;
835 char *volatile lmode;
836 unsigned char buf[FTP_BUFSIZ], *bufp;
838 if (verbose && printnames) {
839 if (local && *local != '-')
840 printf("local: %s ", local);
842 printf("remote: %s\n", remote);
845 proxtrans(cmd, local, remote);
854 if (setjmp(sendabort)) {
858 if (data != INVALID_SOCKET) {
859 (void) closesocket(data);
860 data = INVALID_SOCKET;
863 (void) signal(SIGINT,oldintr);
866 (void) signal(SIGPIPE,oldintp);
871 oldintr = signal(SIGINT, abortsend);
872 if (strcmp(local, "-") == 0)
874 else if (*local == '|') {
876 oldintp = signal(SIGPIPE,SIG_IGN);
878 fin = popen(local + 1, "r");
881 (void) signal(SIGINT, oldintr);
883 (void) signal(SIGPIPE, oldintp);
891 if ((curtype == TYPE_I) || (curtype == TYPE_L))
892 fin = fopen(local, "rb");
894 fin = fopen(local, "rt");
896 fin = fopen(local, "r");
899 fprintf(stderr, "local: %s: %s\n", local,
901 (void) signal(SIGINT, oldintr);
906 if (fstat(fileno(fin), &st) < 0 ||
907 (st.st_mode&S_IFMT) != S_IFREG) {
908 fprintf(stdout, "%s: not a plain file.\n", local);
909 (void) signal(SIGINT, oldintr);
916 (void) signal(SIGINT, oldintr);
919 (void) signal(SIGPIPE, oldintp);
922 if (closefunc != NULL)
926 if (setjmp(sendabort))
930 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
931 if (fseek(fin, (long) restart_point, 0) < 0) {
932 fprintf(stderr, "local: %s: %s\n", local,
935 if (closefunc != NULL)
939 if (command("REST %ld", (long) restart_point)
942 if (closefunc != NULL)
950 if (command("%s %s", cmd, remote) != PRELIM) {
951 (void) signal(SIGINT, oldintr);
954 (void) signal(SIGPIPE, oldintp);
956 if (closefunc != NULL)
961 if (command("%s", cmd) != PRELIM) {
962 (void) signal(SIGINT, oldintr);
965 (void) signal(SIGPIPE, oldintp);
967 if (closefunc != NULL)
971 dout = dataconn(lmode);
974 (void) gettimeofday(&start, (struct timezone *)0);
976 oldintp = signal(SIGPIPE, SIG_IGN);
983 while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
985 for (bufp = buf; c > 0; c -= d, bufp += d)
986 if ((d = secure_write(fileno(dout), bufp,
987 (unsigned int) c)) <= 0)
990 while (bytes >= hashbytes) {
992 hashbytes += HASHBYTES;
994 (void) fflush(stdout);
999 if (hash && bytes > 0) {
1000 if (bytes < HASHBYTES)
1001 (void) putchar('#');
1002 (void) putchar('\n');
1003 (void) fflush(stdout);
1006 fprintf(stderr, "local: %s: %s\n", local,
1008 if (d < 0 || (d = secure_flush(fileno(dout))) < 0) {
1009 if (d == -1 && errno != EPIPE)
1016 while ((c = getc(fin)) != EOF) {
1018 while (hash && (bytes >= hashbytes)) {
1019 (void) putchar('#');
1020 (void) fflush(stdout);
1021 hashbytes += HASHBYTES;
1024 secure_putc('\r', dout) < 0)
1028 if (secure_putc(c, dout) < 0)
1031 /* if (c == '\r') { */
1032 /* (void) putc('\0', dout); this violates rfc */
1037 if (bytes < hashbytes)
1038 (void) putchar('#');
1039 (void) putchar('\n');
1040 (void) fflush(stdout);
1043 fprintf(stderr, "local: %s: %s\n", local,
1046 if (ferror(dout) || (d = secure_flush(fileno(dout))) < 0) {
1047 if ((ferror(dout) || d == -1) && errno != EPIPE)
1053 (void) gettimeofday(&stop, (struct timezone *)0);
1054 if (closefunc != NULL)
1056 (void) FCLOSE_SOCKET(dout);
1059 (void) signal(SIGINT, oldintr);
1062 (void) signal(SIGPIPE, oldintp);
1065 ptransfer("sent", bytes, &start, &stop);
1068 (void) gettimeofday(&stop, (struct timezone *)0);
1069 (void) signal(SIGINT, oldintr);
1072 (void) signal(SIGPIPE, oldintp);
1078 if (data != INVALID_SOCKET) {
1079 (void) closesocket(data);
1080 data = INVALID_SOCKET;
1083 (void) FCLOSE_SOCKET(dout);
1088 if (closefunc != NULL && fin != NULL)
1091 ptransfer("sent", bytes, &start, &stop);
1102 printf("\nreceive aborted\nwaiting for remote to finish abort\n");
1103 (void) fflush(stdout);
1104 longjmp(recvabort, 1);
1107 void recvrequest(char *cmd, char *volatile local, char *remote, char *lmode,
1108 int printnames, int fnameonly)
1110 FILE *volatile fout, *volatile din = 0, *popen();
1111 int (*volatile closefunc)(), pclose(), fclose();
1112 volatile sig_t oldintr, oldintp;
1113 volatile int is_retr, tcrflag, bare_lfs = 0;
1114 static unsigned int bufsize;
1116 unsigned int blksize;
1117 volatile long bytes = 0, hashbytes = HASHBYTES;
1119 struct timeval start, stop;
1125 is_retr = strcmp(cmd, "RETR") == 0;
1126 if (is_retr && verbose && printnames) {
1127 if (local && *local != '-')
1128 printf("local: %s ", local);
1130 printf("remote: %s\n", remote);
1132 if (proxy && is_retr) {
1133 proxtrans(cmd, local, remote);
1139 tcrflag = !crflag && is_retr;
1140 if (setjmp(recvabort)) {
1144 if (data != INVALID_SOCKET) {
1145 (void) closesocket(data);
1146 data = INVALID_SOCKET;
1149 (void) signal(SIGINT, oldintr);
1153 oldintr = signal(SIGINT, abortrecv);
1154 if (fnameonly || (strcmp(local, "-") && *local != '|')) {
1155 if (access(local, 2) < 0) {
1156 char *dir = strrchr(local, '/');
1158 if (errno != ENOENT && errno != EACCES) {
1159 fprintf(stderr, "local: %s: %s\n", local,
1161 (void) signal(SIGINT, oldintr);
1167 d = access(dir ? local : ".", 2);
1171 fprintf(stderr, "local: %s: %s\n", local,
1173 (void) signal(SIGINT, oldintr);
1177 if (!runique && errno == EACCES &&
1178 chmod(local, 0600) < 0) {
1179 fprintf(stderr, "local: %s: %s\n", local,
1181 (void) signal(SIGINT, oldintr);
1182 (void) signal(SIGINT, oldintr);
1186 if (runique && errno == EACCES &&
1187 (local = gunique(local)) == NULL) {
1188 (void) signal(SIGINT, oldintr);
1193 else if (runique && (local = gunique(local)) == NULL) {
1194 (void) signal(SIGINT, oldintr);
1200 if (curtype != TYPE_A)
1201 changetype(TYPE_A, 0);
1202 } else if (curtype != type)
1203 changetype(type, 0);
1205 (void) signal(SIGINT, oldintr);
1209 if (setjmp(recvabort))
1211 if (is_retr && restart_point &&
1212 command("REST %ld", (long) restart_point) != CONTINUE)
1215 if (command("%s %s", cmd, remote) != PRELIM) {
1216 (void) signal(SIGINT, oldintr);
1220 if (command("%s", cmd) != PRELIM) {
1221 (void) signal(SIGINT, oldintr);
1225 din = dataconn("r");
1228 if (strcmp(local, "-") == 0 && !fnameonly)
1230 else if (*local == '|' && !fnameonly) {
1232 oldintp = signal(SIGPIPE, SIG_IGN);
1234 fout = popen(local + 1, "w");
1242 int old_fmode = _fmode;
1244 if ((curtype == TYPE_I) || (curtype == TYPE_L))
1247 fout = fopen(local, lmode);
1252 fprintf(stderr, "local: %s: %s\n", local,
1258 blksize = FTP_BUFSIZ;
1260 if (fstat(fileno(fout), &st) == 0 && st.st_blksize != 0)
1261 blksize = st.st_blksize;
1263 if (blksize > bufsize) {
1266 buf = (char *)malloc((unsigned)blksize);
1274 (void) gettimeofday(&start, (struct timezone *)0);
1279 if (restart_point &&
1280 lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
1281 fprintf(stderr, "local: %s: %s\n", local,
1283 if (closefunc != NULL)
1288 while ((c = secure_read(fileno(din), buf, bufsize)) > 0) {
1289 d = write(fileno(fout), buf,(unsigned int) c);
1294 while (bytes >= hashbytes) {
1295 (void) putchar('#');
1296 hashbytes += HASHBYTES;
1298 (void) fflush(stdout);
1301 if (hash && bytes > 0) {
1302 if (bytes < HASHBYTES)
1303 (void) putchar('#');
1304 (void) putchar('\n');
1305 (void) fflush(stdout);
1308 if (c == -1 && errno != EPIPE)
1314 fprintf(stderr, "local: %s: %s\n", local,
1317 fprintf(stderr, "%s: short write\n", local);
1322 if (restart_point) {
1323 register int i, n, ch;
1325 if (fseek(fout, 0L, L_SET) < 0)
1328 for (i = 0; i++ < n;) {
1329 if ((ch = getc(fout)) == EOF)
1334 if (fseek(fout, 0L, L_INCR) < 0) {
1336 fprintf(stderr, "local: %s: %s\n", local,
1338 if (closefunc != NULL)
1343 while ((c = secure_getc(din)) >= 0) {
1347 while (hash && (bytes >= hashbytes)) {
1348 (void) putchar('#');
1349 (void) fflush(stdout);
1350 hashbytes += HASHBYTES;
1353 if ((c = secure_getc(din)) != '\n' || tcrflag) {
1356 (void) putc('\r', fout);
1364 (void) putc(c, fout);
1370 printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
1371 printf("File may not have transferred correctly.\n");
1374 if (bytes < hashbytes)
1375 (void) putchar('#');
1376 (void) putchar('\n');
1377 (void) fflush(stdout);
1384 if (ferror(fout) || c == -2) {
1386 fprintf(stderr, "local: %s: %s\n", local,
1392 if (closefunc != NULL)
1394 (void) signal(SIGINT, oldintr);
1397 (void) signal(SIGPIPE, oldintp);
1399 (void) gettimeofday(&stop, (struct timezone *)0);
1400 (void) FCLOSE_SOCKET(din);
1403 if (bytes > 0 && is_retr)
1404 ptransfer("received", bytes, &start, &stop);
1408 /* abort using RFC959 recommended IP,SYNC sequence */
1410 (void) gettimeofday(&stop, (struct timezone *)0);
1413 (void) signal(SIGPIPE, oldintr);
1415 (void) signal(SIGINT, SIG_IGN);
1418 (void) signal(SIGINT, oldintr);
1424 if (data != INVALID_SOCKET) {
1425 (void) closesocket(data);
1426 data = INVALID_SOCKET;
1428 if (closefunc != NULL && fout != NULL)
1431 (void) FCLOSE_SOCKET(din);
1435 ptransfer("received", bytes, &start, &stop);
1436 (void) signal(SIGINT, oldintr);
1440 * Need to start a listen on the data channel before we send the command,
1441 * otherwise the server's connect may fail.
1443 static int initconn()
1445 register char *p, *a;
1446 int result, tmpno = 0;
1449 #ifndef NO_PASSIVE_MODE
1450 int a1,a2,a3,a4,p1,p2;
1453 data = socket(AF_INET, SOCK_STREAM, 0);
1454 if (data == INVALID_SOCKET) {
1455 PERROR_SOCKET("ftp: socket");
1458 if (options & SO_DEBUG &&
1459 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) == SOCKET_ERROR)
1460 PERROR_SOCKET("ftp: setsockopt (ignored)");
1461 if (command("PASV") != COMPLETE) {
1462 printf("Passive mode refused. Turning off passive mode.\n");
1468 * What we've got at this point is a string of comma separated
1469 * one-byte unsigned integer values, separated by commas.
1470 * The first four are the an IP address. The fifth is the MSB
1471 * of the port number, the sixth is the LSB. From that we'll
1472 * prepare a sockaddr_in.
1475 if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",&a1,&a2,&a3,&a4,&p1,&p2) != 6) {
1476 printf("Passive mode address scan failure. Shouldn't happen!\n");
1480 data_addr.sin_family = AF_INET;
1481 data_addr.sin_addr.s_addr = htonl((a1<<24)|(a2<<16)|(a3<<8)|a4);
1482 data_addr.sin_port = htons((p1<<8)|p2);
1484 if (connect(data, (struct sockaddr *) &data_addr, sizeof(data_addr)) == SOCKET_ERROR) {
1485 PERROR_SOCKET("ftp: connect");
1489 #ifdef IPTOS_THROUGHPUT
1490 on = IPTOS_THROUGHPUT;
1491 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) == SOCKET_ERROR)
1492 PERROR_SOCKET("ftp: setsockopt TOS (ignored)");
1495 hisdataaddr = data_addr;
1501 data_addr = myctladdr;
1503 data_addr.sin_port = 0; /* let system pick one */
1504 if (data != INVALID_SOCKET)
1505 (void) closesocket(data);
1506 data = socket(AF_INET, SOCK_STREAM, 0);
1507 if (data == INVALID_SOCKET) {
1508 PERROR_SOCKET("ftp: socket");
1514 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) == SOCKET_ERROR) {
1515 PERROR_SOCKET("ftp: setsockopt (reuse address)");
1518 if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) == SOCKET_ERROR) {
1519 PERROR_SOCKET("ftp: bind");
1522 if (options & SO_DEBUG &&
1523 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) == SOCKET_ERROR)
1524 PERROR_SOCKET("ftp: setsockopt (ignored)");
1525 len = sizeof (data_addr);
1526 if (getsockname(data, (struct sockaddr *)&data_addr, &len) == SOCKET_ERROR) {
1527 PERROR_SOCKET("ftp: getsockname");
1530 if (listen(data, 1) == SOCKET_ERROR)
1531 PERROR_SOCKET("ftp: listen");
1533 a = (char *)&data_addr.sin_addr;
1534 p = (char *)&data_addr.sin_port;
1535 #define UC(b) (((int)b)&0xff)
1537 command("PORT %d,%d,%d,%d,%d,%d",
1538 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1539 UC(p[0]), UC(p[1]));
1540 if (result == ERROR && sendport == -1) {
1545 return (result != COMPLETE);
1550 #ifdef IPTOS_THROUGHPUT
1551 on = IPTOS_THROUGHPUT;
1552 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) == SOCKET_ERROR)
1553 PERROR_SOCKET("ftp: setsockopt TOS (ignored)");
1558 (void) closesocket(data), data = INVALID_SOCKET;
1565 dataconn(char *lmode)
1568 socklen_t fromlen = sizeof (hisdataaddr);
1570 #ifdef IPTOS_LOWDELAY
1575 #ifndef NO_PASSIVE_MODE
1577 return (FDOPEN_SOCKET(data, lmode));
1579 s = accept(data, (struct sockaddr *) &hisdataaddr, &fromlen);
1580 if (s == INVALID_SOCKET) {
1581 PERROR_SOCKET("ftp: accept");
1582 (void) closesocket(data), data = INVALID_SOCKET;
1585 (void) closesocket(data);
1588 #ifdef IPTOS_THROUGHPUT
1589 tos = IPTOS_THROUGHPUT;
1590 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) == SOCKET_ERROR)
1591 PERROR_SOCKET("ftp: setsockopt TOS (ignored)");
1594 return (FDOPEN_SOCKET(data, lmode));
1597 static void ptransfer(char *direction, long bytes,
1598 struct timeval *t0, struct timeval *t1)
1605 s = td.tv_sec + (td.tv_usec / 1000000.);
1606 #define nz(x) ((x) == 0 ? 1 : (x))
1607 kbs = (bytes / nz(s))/1024.0;
1608 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
1609 bytes, direction, s, kbs);
1614 struct timeval *tsum, *t0;
1617 tsum->tv_sec += t0->tv_sec;
1618 tsum->tv_usec += t0->tv_usec;
1619 if (tsum->tv_usec > 1000000)
1620 tsum->tv_sec++, tsum->tv_usec -= 1000000;
1623 static void tvsub(struct timeval *tdiff, struct timeval *t1,
1627 tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1628 tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1629 if (tdiff->tv_usec < 0)
1630 tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1639 void pswitch(int flag)
1642 static struct comvars {
1644 char name[MAXHOSTNAMELEN];
1645 struct sockaddr_in mctl;
1646 struct sockaddr_in hctl;
1659 char mi[MAXPATHLEN];
1660 char mo[MAXPATHLEN];
1664 #ifdef KRB5_KRB4_COMPAT
1666 Key_schedule schedule;
1667 #endif /* KRB5_KRB4_COMPAT */
1668 } proxstruct, tmpstruct;
1669 struct comvars *ip, *op;
1672 oldintr = signal(SIGINT, psabort);
1686 ip->connect = connected;
1687 connected = op->connect;
1689 if (ip->name != hostname)
1690 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1691 ip->name[strlen(ip->name)] = '\0';
1694 hostname = op->name;
1695 ip->hctl = hisctladdr;
1696 hisctladdr = op->hctl;
1697 ip->mctl = myctladdr;
1698 myctladdr = op->mctl;
1705 ip->curtpe = curtype;
1706 curtype = op->curtpe;
1709 ip->sunqe = sunique;
1710 sunique = op->sunqe;
1711 ip->runqe = runique;
1712 runique = op->runqe;
1717 (void) strncpy(ip->nti, ntin, sizeof(ip->nti) - 1);
1718 (ip->nti)[strlen(ip->nti)] = '\0';
1719 (void) strncpy(ntin, op->nti, sizeof(ntin) - 1);
1720 ntin[sizeof(ntin) - 1] = '\0';
1721 (void) strncpy(ip->nto, ntout, sizeof(ip->nto) - 1);
1722 (ip->nto)[strlen(ip->nto)] = '\0';
1723 (void) strncpy(ntout, op->nto, sizeof(ntout) - 1);
1724 ntout[sizeof(ntout) - 1] = '\0';
1725 ip->mapflg = mapflag;
1726 mapflag = op->mapflg;
1727 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1728 (ip->mi)[strlen(ip->mi)] = '\0';
1729 (void) strncpy(mapin, op->mi, sizeof(mapin) - 1);
1730 mapin[sizeof(mapin) - 1] = '\0';
1731 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1732 (ip->mo)[strlen(ip->mo)] = '\0';
1733 (void) strncpy(mapout, op->mo, sizeof(mapout) - 1);
1734 mapout[sizeof(mapout) - 1] = '\0';
1735 ip->authtype = auth_type;
1736 auth_type = op->authtype;
1745 #ifdef KRB5_KRB4_COMPAT
1746 memcpy(ip->session, cred.session, sizeof(cred.session));
1747 memcpy(cred.session, op->session, sizeof(cred.session));
1748 memcpy(ip->schedule, schedule, sizeof(schedule));
1749 memcpy(schedule, op->schedule, sizeof(schedule));
1750 #endif /* KRB5_KRB4_COMPAT */
1751 (void) signal(SIGINT, oldintr);
1765 (void) fflush(stdout);
1769 longjmp(ptabort, 1);
1773 proxtrans(char *cmd, char *local, char *remote)
1775 volatile sig_t oldintr;
1776 volatile int secndflag = 0;
1777 int prox_type, nfnd;
1778 char *volatile cmd2;
1781 if (strcmp(cmd, "RETR"))
1784 cmd2 = runique ? "STOU" : "STOR";
1785 if ((prox_type = type) == 0) {
1786 if (unix_server && unix_proxy)
1791 if (curtype != prox_type)
1792 changetype(prox_type, 1);
1793 if (command("PASV") != COMPLETE) {
1794 printf("proxy server does not support third party transfers.\n");
1799 printf("No primary connection\n");
1804 if (curtype != prox_type)
1805 changetype(prox_type, 1);
1806 if (command("PORT %s", pasv) != COMPLETE) {
1810 if (setjmp(ptabort))
1812 oldintr = signal(SIGINT, abortpt);
1813 if (command("%s %s", cmd, remote) != PRELIM) {
1814 (void) signal(SIGINT, oldintr);
1821 if (command("%s %s", cmd2, local) != PRELIM)
1827 (void) signal(SIGINT, oldintr);
1830 printf("local: %s remote: %s\n", local, remote);
1833 (void) signal(SIGINT, SIG_IGN);
1835 if (strcmp(cmd, "RETR") && !proxy)
1837 else if (!strcmp(cmd, "RETR") && proxy)
1839 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1840 if (command("%s %s", cmd2, local) != PRELIM) {
1843 abort_remote((FILE *) NULL);
1848 (void) signal(SIGINT, oldintr);
1852 abort_remote((FILE *) NULL);
1854 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1855 if (command("%s %s", cmd2, local) != PRELIM) {
1858 abort_remote((FILE *) NULL);
1862 (void) signal(SIGINT, oldintr);
1867 abort_remote((FILE *) NULL);
1871 FD_SET(SOCKETNO(fileno(cin)), &mask);
1872 if ((nfnd = empty(&mask, 10)) <= 0) {
1888 (void) signal(SIGINT, oldintr);
1898 FD_SET(SOCKETNO(fileno(cin)), &mask);
1899 if ((nfnd = empty(&mask,0)) < 0) {
1911 gunique(char *local)
1913 static char new[MAXPATHLEN];
1914 char *cp = strrchr(local, '/');
1920 d = access(cp ? local : ".", 2);
1924 fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
1927 (void) strncpy(new, local, sizeof(new) - 3);
1928 new[sizeof(new) - 1] = '\0';
1929 cp = new + strlen(new);
1932 if (++count == 100) {
1933 printf("runique: can't find unique file name.\n");
1942 if ((d = access(new, 0)) < 0)
1946 else if (*(cp - 2) == '.')
1949 *(cp - 2) = *(cp - 2) + 1;
1956 #ifdef KRB5_KRB4_COMPAT
1957 char realm[REALM_SZ + 1];
1958 #endif /* KRB5_KRB4_COMPAT */
1965 { GSS_C_NO_OID, "ftp" },
1966 { GSS_C_NO_OID, "host" },
1968 int n_gss_trials = sizeof(gss_trials)/sizeof(gss_trials[0]);
1973 int oldverbose = verbose;
1974 #ifdef KRB5_KRB4_COMPAT
1975 char *service, inst[INST_SZ];
1976 KRB4_32 cksum, checksum = getpid();
1977 #endif /* KRB5_KRB4_COMPAT */
1978 #if defined(KRB5_KRB4_COMPAT) || defined(GSSAPI)
1979 u_char out_buf[FTP_BUFSIZ];
1981 #endif /* KRB5_KRB4_COMPAT */
1983 if (auth_type) return(1); /* auth already succeeded */
1985 /* Other auth types go here ... */
1988 if (command("AUTH %s", "GSSAPI") == CONTINUE) {
1989 OM_uint32 maj_stat, min_stat, dummy_stat;
1990 gss_name_t target_name;
1991 gss_buffer_desc send_tok, recv_tok, *token_ptr;
1992 char stbuf[FTP_BUFSIZ];
1994 struct gss_channel_bindings_struct chan;
1995 chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32 */
1996 chan.initiator_address.length = 4;
1997 chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
1998 chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
1999 chan.acceptor_address.length = 4;
2000 chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
2001 chan.application_data.length = 0;
2002 chan.application_data.value = 0;
2005 printf("GSSAPI accepted as authentication type\n");
2007 /* blob from gss-client */
2009 for (trial = 0; trial < n_gss_trials; trial++) {
2010 /* ftp@hostname first, the host@hostname */
2011 /* the V5 GSSAPI binding canonicalizes this for us... */
2012 sprintf(stbuf, "%s@%s", gss_trials[trial].service_name, hostname);
2014 fprintf(stderr, "Trying to authenticate to <%s>\n", stbuf);
2016 send_tok.value = stbuf;
2017 send_tok.length = strlen(stbuf) + 1;
2018 maj_stat = gss_import_name(&min_stat, &send_tok,
2019 gss_nt_service_name, &target_name);
2021 if (maj_stat != GSS_S_COMPLETE) {
2022 user_gss_error(maj_stat, min_stat, "parsing name");
2023 secure_error("name parsed <%s>\n", stbuf);
2027 token_ptr = GSS_C_NO_BUFFER;
2028 gcontext = GSS_C_NO_CONTEXT; /* structure copy */
2032 fprintf(stderr, "calling gss_init_sec_context\n");
2034 gss_init_sec_context(&min_stat,
2035 GSS_C_NO_CREDENTIAL,
2038 (gss_OID_desc *)gss_trials[trial].mech_type,
2039 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
2040 (forward ? GSS_C_DELEG_FLAG :
2043 &chan, /* channel bindings */
2045 NULL, /* ignore mech type */
2047 NULL, /* ignore ret_flags */
2048 NULL); /* ignore time_rec */
2051 if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED){
2052 if (trial == n_gss_trials-1)
2053 user_gss_error(maj_stat, min_stat, "initializing context");
2054 /* could just be that we missed on the service name */
2058 if (send_tok.length != 0) {
2059 int len = send_tok.length;
2060 reply_parse = "ADAT="; /* for command() later */
2061 oldverbose = verbose;
2062 verbose = (trial == n_gss_trials-1)?0:-1;
2063 kerror = radix_encode(send_tok.value, out_buf, &len, 0);
2064 gss_release_buffer(&dummy_stat, &send_tok);
2066 fprintf(stderr, "Base 64 encoding failed: %s\n",
2067 radix_error(kerror));
2068 } else if ((comcode = command("ADAT %s", out_buf))!=COMPLETE
2069 && comcode != 3 /* (335) */) {
2070 if (trial == n_gss_trials-1) {
2071 fprintf(stderr, "GSSAPI ADAT failed\n");
2072 /* force out of loop */
2073 maj_stat = GSS_S_FAILURE;
2075 /* backoff to the v1 gssapi is still possible. Send
2076 a new AUTH command. If that fails, terminate the
2078 if (command("AUTH %s", "GSSAPI") != CONTINUE) {
2080 "GSSAPI ADAT failed, AUTH restart failed\n");
2081 /* force out of loop */
2082 maj_stat = GSS_S_FAILURE;
2085 } else if (!reply_parse) {
2087 "No authentication data received from server\n");
2088 if (maj_stat == GSS_S_COMPLETE) {
2089 fprintf(stderr, "...but no more was needed\n");
2090 goto gss_complete_loop;
2092 user_gss_error(maj_stat, min_stat, "no reply, huh?");
2093 goto gss_complete_loop;
2095 } else if ((kerror = radix_encode((unsigned char *)reply_parse,
2097 fprintf(stderr, "Base 64 decoding failed: %s\n",
2098 radix_error(kerror));
2100 /* everything worked */
2101 token_ptr = &recv_tok;
2102 recv_tok.value = out_buf;
2103 recv_tok.length = i;
2107 /* get out of loop clean */
2109 trial = n_gss_trials-1;
2112 } while (maj_stat == GSS_S_CONTINUE_NEEDED);
2114 gss_release_name(&dummy_stat, &target_name);
2115 if (maj_stat == GSS_S_COMPLETE)
2118 verbose = oldverbose;
2119 if (maj_stat == GSS_S_COMPLETE) {
2120 printf("GSSAPI authentication succeeded\n");
2122 auth_type = "GSSAPI";
2125 fprintf(stderr, "GSSAPI authentication failed\n");
2126 verbose = oldverbose;
2131 #ifdef KRB5_KRB4_COMPAT
2132 if (command("AUTH %s", "KERBEROS_V4") == CONTINUE) {
2134 printf("%s accepted as authentication type\n", "KERBEROS_V4");
2136 strncpy(inst, (char *) krb_get_phost(hostname), sizeof(inst) - 1);
2137 inst[sizeof(inst) - 1] = '\0';
2138 if (realm[0] == '\0')
2139 strncpy(realm, (char *) krb_realmofhost(hostname), sizeof(realm) - 1);
2140 realm[sizeof(realm) - 1] = '\0';
2141 if ((kerror = krb_mk_req(&ticket, service = "ftp",
2142 inst, realm, checksum))
2143 && (kerror != KDC_PR_UNKNOWN ||
2144 (kerror = krb_mk_req(&ticket, service = "rcmd",
2145 inst, realm, checksum))))
2146 fprintf(stderr, "Kerberos V4 krb_mk_req failed: %s\n",
2147 krb_get_err_text(kerror));
2148 else if ((kerror = krb_get_cred(service, inst, realm, &cred)))
2149 fprintf(stderr, "Kerberos V4 krb_get_cred failed: %s\n",
2150 krb_get_err_text(kerror));
2152 key_sched(cred.session, schedule);
2153 reply_parse = "ADAT=";
2154 oldverbose = verbose;
2157 if ((kerror = radix_encode(ticket.dat, out_buf, &i, 0)))
2158 fprintf(stderr, "Base 64 encoding failed: %s\n",
2159 radix_error(kerror));
2160 else if (command("ADAT %s", out_buf) != COMPLETE)
2161 fprintf(stderr, "Kerberos V4 authentication failed\n");
2162 else if (!reply_parse)
2164 "No authentication data received from server\n");
2165 else if ((kerror = radix_encode((unsigned char *)reply_parse, out_buf, &i, 1)))
2166 fprintf(stderr, "Base 64 decoding failed: %s\n",
2167 radix_error(kerror));
2168 else if ((kerror = krb_rd_safe(out_buf, (unsigned )i,
2170 &hisctladdr, &myctladdr,
2172 fprintf(stderr, "Kerberos V4 krb_rd_safe failed: %s\n",
2173 krb_get_err_text(kerror));
2175 /* fetch the (modified) checksum */
2176 (void) memcpy(&cksum, msg_data.app_data, sizeof(cksum));
2177 if (ntohl(cksum) == checksum + 1) {
2178 verbose = oldverbose;
2180 printf("Kerberos V4 authentication succeeded\n");
2182 auth_type = "KERBEROS_V4";
2184 } else fprintf(stderr,
2185 "Kerberos V4 mutual authentication failed\n");
2187 verbose = oldverbose;
2190 } else fprintf(stderr, "%s rejected as an authentication type\n",
2192 #endif /* KRB5_KRB4_COMPAT */
2194 /* Other auth types go here ... */
2200 setpbsz(unsigned int size)
2204 if (ucbuf) (void) free(ucbuf);
2206 while ((ucbuf = (unsigned char *)malloc(actualbuf)) == NULL)
2210 perror("Error while trying to malloc PROT buffer:");
2213 oldverbose = verbose;
2215 reply_parse = "PBSZ=";
2216 if (command("PBSZ %u", actualbuf) != COMPLETE)
2217 fatal("Cannot set PROT buffer size");
2219 if ((maxbuf = (unsigned int) atol(reply_parse)) > actualbuf)
2221 } else maxbuf = actualbuf;
2223 verbose = oldverbose;
2226 static void abort_remote(FILE *din)
2228 char buf[FTP_BUFSIZ];
2233 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
2234 * after urgent byte rather than before as is protocol now
2236 sprintf(buf, "%c%c%c", IAC, IP, IAC);
2237 if (send(SOCKETNO(fileno(cout)), buf, 3, MSG_OOB) != 3)
2238 PERROR_SOCKET("abort");
2240 (void) secure_command("ABOR");
2242 FD_SET(SOCKETNO(fileno(cin)), &mask);
2244 FD_SET(SOCKETNO(fileno(din)), &mask);
2246 if ((nfnd = empty(&mask, 10)) <= 0) {
2254 if (din && FD_ISSET(SOCKETNO(fileno(din)), &mask)) {
2255 /* Security: No threat associated with this read. */
2256 while (read(fileno(din), buf, FTP_BUFSIZ) > 0)
2259 if (getreply(0) == ERROR && code == 552) {
2260 /* 552 needed for nic style abort */
2267 void user_gss_error(OM_uint32 maj_stat, OM_uint32 min_stat, char *s)
2269 /* a lot of work just to report the error */
2270 OM_uint32 gmaj_stat, gmin_stat, msg_ctx;
2271 gss_buffer_desc msg;
2274 gmaj_stat = gss_display_status(&gmin_stat, maj_stat,
2278 if ((gmaj_stat == GSS_S_COMPLETE)||
2279 (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
2280 fprintf(stderr, "GSSAPI error major: %s\n",
2282 (void) gss_release_buffer(&gmin_stat, &msg);
2284 if (gmaj_stat != GSS_S_CONTINUE_NEEDED)
2289 gmaj_stat = gss_display_status(&gmin_stat, min_stat,
2293 if ((gmaj_stat == GSS_S_COMPLETE)||
2294 (gmaj_stat == GSS_S_CONTINUE_NEEDED)) {
2295 fprintf(stderr, "GSSAPI error minor: %s\n",
2297 (void) gss_release_buffer(&gmin_stat, &msg);
2299 if (gmaj_stat != GSS_S_CONTINUE_NEEDED)
2302 fprintf(stderr, "GSSAPI error: %s\n", s);
2305 void secure_gss_error(OM_uint32 maj_stat, OM_uint32 min_stat, char *s)
2307 user_gss_error(maj_stat, min_stat, s);
2314 int gettimeofday(struct timeval *tv, void *tz)
2320 tv->tv_sec = tb.time;
2321 tv->tv_usec = tb.millitm * 1000;
2325 tz->tz_minuteswest = tb.timezone;
2326 tz->tz_dsttime = tb.dstflag;
2334 int fclose_socket(FILE* f)
2337 SOCKET _s = _get_osfhandle(_fileno(f));
2342 if (closesocket(_s) == SOCKET_ERROR)
2343 return SOCKET_ERRNO;
2347 FILE* fdopen_socket(SOCKET s, char* mode)
2350 int old_fmode = _fmode;
2353 if (strstr(mode, "a+")) o_mode |= _O_RDWR | _O_APPEND;
2354 if (strstr(mode, "r+")) o_mode |= _O_RDWR;
2355 if (strstr(mode, "w+")) o_mode |= _O_RDWR;
2356 if (strchr(mode, 'a')) o_mode |= _O_WRONLY | _O_APPEND;
2357 if (strchr(mode, 'r')) o_mode |= _O_RDONLY;
2358 if (strchr(mode, 'w')) o_mode |= _O_WRONLY;
2360 /* In theory, _open_osfhandle only takes: _O_APPEND, _O_RDONLY, _O_TEXT */
2363 f = fdopen(_open_osfhandle(s, o_mode), mode);