* SUCH DAMAGE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government. It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#ifndef lint
static char sccsid[] = "@(#)ftp.c 5.38 (Berkeley) 4/22/91";
#endif /* not lint */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
+#ifndef KRB5_KRB4_COMPAT
+/* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
#include <sys/socket.h>
+#endif
#include <sys/time.h>
#include <sys/file.h>
#ifdef HAVE_SYS_SELECT_H
#include <signal.h>
#include <string.h>
#include <errno.h>
+#ifndef KRB5_KRB4_COMPAT
+/* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
#include <netdb.h>
+#endif
#include <fcntl.h>
#include <pwd.h>
#ifndef STDARG
#define L_INCR 1
#endif
-#ifdef KERBEROS
+#ifdef KRB5_KRB4_COMPAT
#include <krb.h>
KTEXT_ST ticket;
CREDENTIALS cred;
Key_schedule schedule;
MSG_DAT msg_data;
-#endif /* KERBEROS */
+#endif /* KRB5_KRB4_COMPAT */
#ifdef GSSAPI
#include <gssapi/gssapi.h>
+/* need to include the krb5 file, because we're doing manual fallback
+ from the v2 mech to the v2 mech. Once there's real negotiation,
+ we can be generic again. */
#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
gss_ctx_id_t gcontext;
#endif /* GSSAPI */
-
static int kerror; /* XXX needed for all auth types */
char *auth_type; /* Authentication succeeded? If so, what type? */
}
hisctladdr.sin_family = hp->h_addrtype;
memcpy((caddr_t)&hisctladdr.sin_addr, hp->h_addr_list[0],
- hp->h_length);
+ sizeof(hisctladdr.sin_addr));
(void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
}
hostname = hostnamebuf;
perror((char *) 0);
hp->h_addr_list++;
memcpy((caddr_t)&hisctladdr.sin_addr,
- hp->h_addr_list[0], hp->h_length);
+ hp->h_addr_list[0],
+ sizeof(hisctladdr.sin_addr));
fprintf(stdout, "Trying %s...\n",
inet_ntoa(hisctladdr.sin_addr));
(void) close(s);
user = tmp;
}
n = command("USER %s", user);
- if (n == COMPLETE)
- n = command("PASS dummy");
+ if (n == COMPLETE) {
+ /* determine if we need to send a dummy password */
+ int oldverbose = verbose;
+
+ verbose = 0;
+ if (command("PWD") != COMPLETE) {
+ verbose = oldverbose;
+ command("PASS dummy");
+ } else {
+ verbose = oldverbose;
+ }
+ }
else if (n == CONTINUE) {
#ifndef NOENCRYPTION
- int oldlevel;
+ int oldclevel;
#endif
if (pass == NULL)
pass = mygetpass("Password:");
#ifndef NOENCRYPTION
- if ((oldlevel = level) == PROT_S) level = PROT_P;
+ oldclevel = clevel;
+ clevel = PROT_P;
#endif
n = command("PASS %s", pass);
#ifndef NOENCRYPTION
/* level may have changed */
- if (level == PROT_P) level = oldlevel;
+ if (clevel == PROT_P) clevel = oldclevel;
#endif
}
if (n == CONTINUE) {
char in[FTP_BUFSIZ], out[FTP_BUFSIZ];
int length;
- if (auth_type) {
- /*
- * File protection level also determines whether
- * commands are MIC or ENC. Should be independent ...
- */
-#ifdef KERBEROS
+ if (auth_type && clevel != PROT_C) {
+#ifdef KRB5_KRB4_COMPAT
if (strcmp(auth_type, "KERBEROS_V4") == 0)
- if ((length = level == PROT_P ?
+ if ((length = clevel == PROT_P ?
krb_mk_priv((unsigned char *)cmd, (unsigned char *)out,
strlen(cmd), schedule,
&cred.session, &myctladdr, &hisctladdr)
strlen(cmd), &cred.session,
&myctladdr, &hisctladdr)) == -1) {
fprintf(stderr, "krb_mk_%s failed for KERBEROS_V4\n",
- level == PROT_P ? "priv" : "safe");
+ clevel == PROT_P ? "priv" : "safe");
return(0);
}
-#endif /* KERBEROS */
+#endif /* KRB5_KRB4_COMPAT */
#ifdef GSSAPI
/* secure_command (based on level) */
if (strcmp(auth_type, "GSSAPI") == 0) {
gss_buffer_desc in_buf, out_buf;
OM_uint32 maj_stat, min_stat;
int conf_state;
-/* level = PROT_P; */
+/* clevel = PROT_P; */
in_buf.value = cmd;
in_buf.length = strlen(cmd) + 1;
maj_stat = gss_seal(&min_stat, gcontext,
- (level==PROT_P), /* confidential */
+ (clevel==PROT_P), /* private */
GSS_C_QOP_DEFAULT,
&in_buf, &conf_state,
&out_buf);
if (maj_stat != GSS_S_COMPLETE) {
/* generally need to deal */
user_gss_error(maj_stat, min_stat,
- (level==PROT_P)?
+ (clevel==PROT_P)?
"gss_seal ENC didn't complete":
"gss_seal MIC didn't complete");
- } else if ((level == PROT_P) && !conf_state) {
+ } else if ((clevel == PROT_P) && !conf_state) {
fprintf(stderr,
"GSSAPI didn't encrypt message");
} else {
if (debug)
fprintf(stderr, "sealed (%s) %d bytes\n",
- level==PROT_P?"ENC":"MIC",
+ clevel==PROT_P?"ENC":"MIC",
out_buf.length);
memcpy(out, out_buf.value,
length=out_buf.length);
radix_error(kerror));
return(0);
}
- fprintf(cout, "%s %s", level == PROT_P ? "ENC" : "MIC", in);
+ fprintf(cout, "%s %s", clevel == PROT_P ? "ENC" : "MIC", in);
if(debug)
fprintf(stderr, "secure_command(%s)\nencoding %d bytes %s %s\n",
- cmd, length, level==PROT_P ? "ENC" : "MIC", in);
+ cmd, length, clevel==PROT_P ? "ENC" : "MIC", in);
} else fputs(cmd, cout);
fprintf(cout, "\r\n");
(void) fflush(cout);
cpend = 1;
r = getreply(!strcmp(fmt, "QUIT"));
#ifndef NOENCRYPTION
- if (r == 533 && level == PROT_P) {
+ if (r == 533 && clevel == PROT_P) {
fprintf(stderr,
"ENC command not supported at server; retrying under MIC...\n");
- level = PROT_S;
+ clevel = PROT_S;
goto again;
}
#endif
sigtype cmdabort();
char ibuf[FTP_BUFSIZ], obuf[FTP_BUFSIZ];
int safe = 0;
- extern char *strpbrk(), *strstr();
+#ifndef strpbrk
+ extern char *strpbrk();
+#endif
+#ifndef strstr
+ extern char *strstr();
+#endif
ibuf[0] = '\0';
if (reply_parse) reply_ptr = reply_buf;
if (code != 631 && code != 632 && code != 633) {
printf("Unknown reply: %d %s\n", code, obuf);
n = '5';
- } else safe = code;
+ } else safe = (code == 631);
if (obuf[0]) /* if there is a string to decode */
if (!auth_type) {
printf("Cannot decode reply:\n%d %s\n", code, obuf);
code, radix_error(kerror), obuf);
n = '5';
}
-#ifdef KERBEROS
+#ifdef KRB5_KRB4_COMPAT
else if (strcmp(auth_type, "KERBEROS_V4") == 0)
if ((kerror = safe ?
krb_rd_safe((unsigned char *)ibuf, len,
krb_get_err_text(kerror));
n = '5';
} else {
- if (verbose) printf("%c:", safe ? 'S' : 'P');
- memcpy(ibuf, msg_data.app_data,
- msg_data.app_length);
- strcpy(&ibuf[msg_data.app_length], "\r\n");
+ if (debug) printf("%c:", safe ? 'S' : 'P');
+ if(msg_data.app_length < sizeof(ibuf) - 2) {
+ memcpy(ibuf, msg_data.app_data,
+ msg_data.app_length);
+ strcpy(&ibuf[msg_data.app_length], "\r\n");
+ } else {
+ printf("Message too long!");
+ }
continue;
}
#endif
"failed unsealing reply");
n = '5';
} else {
- memcpy(ibuf, msg_buf.value,
- msg_buf.length);
- strcpy(&ibuf[msg_buf.length], "\r\n");
+ if(msg_buf.length < sizeof(ibuf) - 2 - 1) {
+ memcpy(ibuf, msg_buf.value,
+ msg_buf.length);
+ strcpy(&ibuf[msg_buf.length], "\r\n");
+ } else {
+ user_gss_error(maj_stat, min_stat,
+ "reply was too long");
+ }
gss_release_buffer(&min_stat,&msg_buf);
continue;
}
}
empty(mask, sec)
- struct fd_set *mask;
+ fd_set *mask;
int sec;
{
struct timeval t;
t.tv_sec = (long) sec;
t.tv_usec = 0;
- return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
+ return(select(32, mask, (fd_set *) 0, (fd_set *) 0, &t));
}
jmp_buf sendabort;
struct stat st;
struct timeval start, stop;
register int c, d;
- FILE *fin, *dout = 0, *popen();
- int (*closefunc)(), pclose(), fclose();
- sig_t oldintr, oldintp;
- long bytes = 0, hashbytes = HASHBYTES;
- char *lmode, buf[FTP_BUFSIZ], *bufp;
+ FILE *volatile fin, *volatile dout = 0, *popen();
+ int (*volatile closefunc)(), pclose(), fclose();
+ volatile sig_t oldintr, oldintp;
+ volatile long bytes = 0, hashbytes = HASHBYTES;
+ char *volatile lmode, buf[FTP_BUFSIZ], *bufp;
sigtype abortsend();
if (verbose && printnames) {
}
(void) fflush(stdout);
}
+ if (d <= 0 )
+ break;
}
if (hash && bytes > 0) {
if (bytes < HASHBYTES)
}
recvrequest(cmd, local, remote, lmode, printnames)
- char *cmd, *local, *remote, *lmode;
+ char *cmd, *volatile local, *remote, *lmode;
{
- FILE *fout, *din = 0, *popen();
- int (*closefunc)(), pclose(), fclose();
- sig_t oldintr, oldintp;
- int is_retr, tcrflag, bare_lfs = 0;
+ FILE *volatile fout, *volatile din = 0, *popen();
+ int (*volatile closefunc)(), pclose(), fclose();
+ volatile sig_t oldintr, oldintp;
+ volatile int is_retr, tcrflag, bare_lfs = 0;
char *gunique();
static int bufsize;
static char *buf;
int blksize;
- long bytes = 0, hashbytes = HASHBYTES;
+ volatile long bytes = 0, hashbytes = HASHBYTES;
register int c, d;
struct timeval start, stop;
struct stat st;
char mi[MAXPATHLEN];
char mo[MAXPATHLEN];
char *authtype;
- int lvl;
-#ifdef KERBEROS
+ int clvl;
+ int dlvl;
+#ifdef KRB5_KRB4_COMPAT
C_Block session;
Key_schedule schedule;
-#endif /* KERBEROS */
+#endif /* KRB5_KRB4_COMPAT */
} proxstruct, tmpstruct;
struct comvars *ip, *op;
mcase = op->mcse;
ip->ntflg = ntflag;
ntflag = op->ntflg;
- (void) strncpy(ip->nti, ntin, 16);
+ (void) strncpy(ip->nti, ntin, sizeof(ip->nti) - 1);
(ip->nti)[strlen(ip->nti)] = '\0';
- (void) strcpy(ntin, op->nti);
- (void) strncpy(ip->nto, ntout, 16);
+ (void) strncpy(ntin, op->nti, sizeof(ntin) - 1);
+ ntin[sizeof(ntin) - 1] = '\0';
+ (void) strncpy(ip->nto, ntout, sizeof(ip->nto) - 1);
(ip->nto)[strlen(ip->nto)] = '\0';
- (void) strcpy(ntout, op->nto);
+ (void) strncpy(ntout, op->nto, sizeof(ntout) - 1);
+ ntout[sizeof(ntout) - 1] = '\0';
ip->mapflg = mapflag;
mapflag = op->mapflg;
(void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
(ip->mi)[strlen(ip->mi)] = '\0';
- (void) strcpy(mapin, op->mi);
+ (void) strncpy(mapin, op->mi, sizeof(mapin) - 1);
+ mapin[sizeof(mapin) - 1] = '\0';
(void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
(ip->mo)[strlen(ip->mo)] = '\0';
- (void) strcpy(mapout, op->mo);
+ (void) strncpy(mapout, op->mo, sizeof(mapout) - 1);
+ mapout[sizeof(mapout) - 1] = '\0';
ip->authtype = auth_type;
auth_type = op->authtype;
- ip->lvl = level;
- level = op->lvl;
- if (!level)
- level = 1;
-#ifdef KERBEROS
+ ip->clvl = clevel;
+ clevel = op->clvl;
+ ip->dlvl = dlevel;
+ dlevel = op->dlvl;
+ if (!clevel)
+ clevel = PROT_C;
+ if (!dlevel)
+ dlevel = PROT_C;
+#ifdef KRB5_KRB4_COMPAT
memcpy(ip->session, cred.session, sizeof(cred.session));
memcpy(cred.session, op->session, sizeof(cred.session));
memcpy(ip->schedule, schedule, sizeof(schedule));
memcpy(schedule, op->schedule, sizeof(schedule));
-#endif /* KERBEROS */
+#endif /* KRB5_KRB4_COMPAT */
(void) signal(SIGINT, oldintr);
if (abrtflag) {
abrtflag = 0;
proxtrans(cmd, local, remote)
char *cmd, *local, *remote;
{
- sig_t oldintr;
- int secndflag = 0, prox_type, nfnd;
+ volatile sig_t oldintr;
+ volatile int secndflag = 0;
+ int prox_type, nfnd;
extern jmp_buf ptabort;
- char *cmd2;
- struct fd_set mask;
+ char *volatile cmd2;
+ fd_set mask;
sigtype abortpt();
if (strcmp(cmd, "RETR"))
reset()
{
- struct fd_set mask;
+ fd_set mask;
int nfnd = 1;
FD_ZERO(&mask);
fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
return((char *) 0);
}
- (void) strcpy(new, local);
+ (void) strncpy(new, local, sizeof(new) - 3);
+ new[sizeof(new) - 1] = '\0';
cp = new + strlen(new);
*cp++ = '.';
while (!d) {
return(new);
}
-#ifdef KERBEROS
+#ifdef KRB5_KRB4_COMPAT
char realm[REALM_SZ + 1];
-#endif /* KERBEROS */
+#endif /* KRB5_KRB4_COMPAT */
#ifdef GSSAPI
-/* for testing, we don't have an ftp key yet */
-char* gss_services[] = { "ftp", "host", 0 };
+struct {
+ const gss_OID_desc * const * mech_type;
+ char *service_name;
+} gss_trials[] = {
+ { &gss_mech_krb5, "ftp" },
+ { &gss_mech_krb5, "host" },
+};
+int n_gss_trials = sizeof(gss_trials)/sizeof(gss_trials[0]);
#endif /* GSSAPI */
do_auth()
{
extern int setsafe();
- int oldverbose;
-#ifdef KERBEROS
+ int oldverbose = verbose;
+#ifdef KRB5_KRB4_COMPAT
char *service, inst[INST_SZ];
u_long cksum, checksum = (u_long) getpid();
-#endif /* KERBEROS */
-#if defined(KERBEROS) || defined(GSSAPI)
+#endif /* KRB5_KRB4_COMPAT */
+#if defined(KRB5_KRB4_COMPAT) || defined(GSSAPI)
u_char out_buf[FTP_BUFSIZ];
int i;
-#endif /* KERBEROS */
+#endif /* KRB5_KRB4_COMPAT */
if (auth_type) return(1); /* auth already succeeded */
/* Other auth types go here ... */
-#ifdef KERBEROS
- if (command("AUTH %s", "KERBEROS_V4") == CONTINUE) {
- if (verbose)
- printf("%s accepted as authentication type\n", "KERBEROS_V4");
-
- strcpy(inst, (char *) krb_get_phost(hostname));
- if (realm[0] == '\0')
- strcpy(realm, (char *) krb_realmofhost(hostname));
- if ((kerror = krb_mk_req(&ticket, service = "ftp",
- inst, realm, checksum))
- && (kerror != KDC_PR_UNKNOWN ||
- (kerror = krb_mk_req(&ticket, service = "rcmd",
- inst, realm, checksum))))
- fprintf(stderr, "Kerberos V4 krb_mk_req failed: %s\n",
- krb_get_err_text(kerror));
- else if (kerror = krb_get_cred(service, inst, realm, &cred))
- fprintf(stderr, "Kerberos V4 krb_get_cred failed: %s\n",
- krb_get_err_text(kerror));
- else {
- key_sched(cred.session, schedule);
- reply_parse = "ADAT=";
- oldverbose = verbose;
- verbose = 0;
- i = ticket.length;
- if (kerror = radix_encode(ticket.dat, out_buf, &i, 0))
- fprintf(stderr, "Base 64 encoding failed: %s\n",
- radix_error(kerror));
- else if (command("ADAT %s", out_buf) != COMPLETE)
- fprintf(stderr, "Kerberos V4 authentication failed\n");
- else if (!reply_parse)
- fprintf(stderr,
- "No authentication data received from server\n");
- else if (kerror = radix_encode(reply_parse, out_buf, &i, 1))
- fprintf(stderr, "Base 64 decoding failed: %s\n",
- radix_error(kerror));
- else if (kerror = krb_rd_safe(out_buf, i, &cred.session,
- &hisctladdr, &myctladdr, &msg_data))
- fprintf(stderr, "Kerberos V4 krb_rd_safe failed: %s\n",
- krb_get_err_text(kerror));
- else {
- /* fetch the (modified) checksum */
- (void) memcpy(&cksum, msg_data.app_data, sizeof(cksum));
- if (ntohl(cksum) == checksum + 1) {
- verbose = oldverbose;
- if (verbose)
- printf("Kerberos V4 authentication succeeded\n");
- reply_parse = NULL;
- auth_type = "KERBEROS_V4";
- return(1);
- } else fprintf(stderr,
- "Kerberos V4 mutual authentication failed\n");
- }
- verbose = oldverbose;
- reply_parse = NULL;
- }
- } else fprintf(stderr, "%s rejected as an authentication type\n",
- "KERBEROS_V4");
-#endif /* KERBEROS */
#ifdef GSSAPI
if (command("AUTH %s", "GSSAPI") == CONTINUE) {
OM_uint32 maj_stat, min_stat;
gss_name_t target_name;
gss_buffer_desc send_tok, recv_tok, *token_ptr;
char stbuf[FTP_BUFSIZ];
- char **service_name, **end_service_name;
- int comcode;
+ int comcode, trial;
struct gss_channel_bindings_struct chan;
chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32 */
chan.initiator_address.length = 4;
chan.application_data.length = 0;
chan.application_data.value = 0;
- for (end_service_name = gss_services; *end_service_name; )
- end_service_name++;
- end_service_name--;
-
if (verbose)
- printf("%s accepted as authentication type\n", "GSSAPI");
+ printf("GSSAPI accepted as authentication type\n");
/* blob from gss-client */
-
- for (service_name = gss_services; *service_name; service_name++) {
-
+ for (trial = 0; trial < n_gss_trials; trial++) {
/* ftp@hostname first, the host@hostname */
/* the V5 GSSAPI binding canonicalizes this for us... */
- sprintf(stbuf, "%s@%s", *service_name, hostname);
+ sprintf(stbuf, "%s@%s", gss_trials[trial].service_name, hostname);
if (debug)
fprintf(stderr, "Trying to authenticate to <%s>\n", stbuf);
GSS_C_NO_CREDENTIAL,
&gcontext,
target_name,
- GSS_C_NULL_OID,
- GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+ *gss_trials[trial].mech_type,
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
+ (forward ? GSS_C_DELEG_FLAG : 0),
0,
&chan, /* channel bindings */
token_ptr,
if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED){
- user_gss_error(maj_stat, min_stat, "initializing context");
+ if (trial == n_gss_trials-1)
+ user_gss_error(maj_stat, min_stat, "initializing context");
(void) gss_release_name(&min_stat, &target_name);
/* could just be that we missed on the service name */
goto outer_loop;
int len = send_tok.length;
reply_parse = "ADAT="; /* for command() later */
oldverbose = verbose;
- verbose = 0;
+ verbose = (trial == n_gss_trials-1)?0:-1;
kerror = radix_encode(send_tok.value, out_buf, &len, 0);
if (kerror) {
fprintf(stderr, "Base 64 encoding failed: %s\n",
radix_error(kerror));
} else if ((comcode = command("ADAT %s", out_buf))!=COMPLETE
/* && comcode != 3 (335)*/) {
- fprintf(stderr, "GSSAPI ADAT failed\n");
- /* force out of loop */
- maj_stat = GSS_S_FAILURE;
+ if (trial == n_gss_trials-1) {
+ fprintf(stderr, "GSSAPI ADAT failed\n");
+ /* force out of loop */
+ maj_stat = GSS_S_FAILURE;
+ }
+ /* backoff to the v1 gssapi is still possible. Send
+ a new AUTH command. If that fails, terminate the
+ loop */
+ if (command("AUTH %s", "GSSAPI") != CONTINUE) {
+ fprintf(stderr,
+ "GSSAPI ADAT failed, AUTH restart failed\n");
+ /* force out of loop */
+ maj_stat = GSS_S_FAILURE;
+ }
+ goto outer_loop;
} else if (!reply_parse) {
fprintf(stderr,
"No authentication data received from server\n");
/* get out of loop clean */
gss_complete_loop:
- service_name = end_service_name;
+ trial = n_gss_trials-1;
gss_release_buffer(&min_stat, &send_tok);
gss_release_name(&min_stat, &target_name);
goto outer_loop;
}
verbose = oldverbose;
if (maj_stat == GSS_S_COMPLETE) {
- if (verbose)
- printf("GSSAPI authentication succeeded\n");
+ printf("GSSAPI authentication succeeded\n");
reply_parse = NULL;
auth_type = "GSSAPI";
return(1);
}
}
#endif /* GSSAPI */
+#ifdef KRB5_KRB4_COMPAT
+ if (command("AUTH %s", "KERBEROS_V4") == CONTINUE) {
+ if (verbose)
+ printf("%s accepted as authentication type\n", "KERBEROS_V4");
+
+ strncpy(inst, (char *) krb_get_phost(hostname), sizeof(inst) - 1);
+ inst[sizeof(inst) - 1] = '\0';
+ if (realm[0] == '\0')
+ strncpy(realm, (char *) krb_realmofhost(hostname), sizeof(realm) - 1);
+ realm[sizeof(realm) - 1] = '\0';
+ if ((kerror = krb_mk_req(&ticket, service = "ftp",
+ inst, realm, checksum))
+ && (kerror != KDC_PR_UNKNOWN ||
+ (kerror = krb_mk_req(&ticket, service = "rcmd",
+ inst, realm, checksum))))
+ fprintf(stderr, "Kerberos V4 krb_mk_req failed: %s\n",
+ krb_get_err_text(kerror));
+ else if (kerror = krb_get_cred(service, inst, realm, &cred))
+ fprintf(stderr, "Kerberos V4 krb_get_cred failed: %s\n",
+ krb_get_err_text(kerror));
+ else {
+ key_sched(cred.session, schedule);
+ reply_parse = "ADAT=";
+ oldverbose = verbose;
+ verbose = 0;
+ i = ticket.length;
+ if (kerror = radix_encode(ticket.dat, out_buf, &i, 0))
+ fprintf(stderr, "Base 64 encoding failed: %s\n",
+ radix_error(kerror));
+ else if (command("ADAT %s", out_buf) != COMPLETE)
+ fprintf(stderr, "Kerberos V4 authentication failed\n");
+ else if (!reply_parse)
+ fprintf(stderr,
+ "No authentication data received from server\n");
+ else if (kerror = radix_encode(reply_parse, out_buf, &i, 1))
+ fprintf(stderr, "Base 64 decoding failed: %s\n",
+ radix_error(kerror));
+ else if (kerror = krb_rd_safe(out_buf, i, &cred.session,
+ &hisctladdr, &myctladdr, &msg_data))
+ fprintf(stderr, "Kerberos V4 krb_rd_safe failed: %s\n",
+ krb_get_err_text(kerror));
+ else {
+ /* fetch the (modified) checksum */
+ (void) memcpy(&cksum, msg_data.app_data, sizeof(cksum));
+ if (ntohl(cksum) == checksum + 1) {
+ verbose = oldverbose;
+ if (verbose)
+ printf("Kerberos V4 authentication succeeded\n");
+ reply_parse = NULL;
+ auth_type = "KERBEROS_V4";
+ return(1);
+ } else fprintf(stderr,
+ "Kerberos V4 mutual authentication failed\n");
+ }
+ verbose = oldverbose;
+ reply_parse = NULL;
+ }
+ } else fprintf(stderr, "%s rejected as an authentication type\n",
+ "KERBEROS_V4");
+#endif /* KRB5_KRB4_COMPAT */
/* Other auth types go here ... */
{
char buf[FTP_BUFSIZ];
int nfnd;
- struct fd_set mask;
+ fd_set mask;
/*
* send IAC in urgent mode instead of DM because 4.3BSD places oob mark