From 56cabb896e728815caf1cbf3afe77848ed1c213e Mon Sep 17 00:00:00 2001 From: Geoffrey King Date: Wed, 12 Aug 1998 06:53:38 +0000 Subject: [PATCH] * ftp.c, cmds.c, cmdtab.c, main.c, secure.c, ftp_var.h: Replace global variable level with separate variables clevel and dlevel for the control channel and data channel protection levels, respectively, so that the user may specify separate protection levels for each channel. Similarly, functions such as getlevel and setlevel are now getclevel/getdlevel, and setclevel/setdlevel. * cmdtab.c: Add new FTP commands "cprotect" to allow the user to set the control channel protection level (similar to "protect"), and "ccc" (Clear Command Channel) which sets the control channel protection level to clear (per the RFC). git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@10804 dc483132-0cff-0310-8789-dd5450dbe970 --- src/appl/gssftp/ftp/ChangeLog | 14 ++++ src/appl/gssftp/ftp/cmds.c | 125 +++++++++++++++++++++++++++------- src/appl/gssftp/ftp/cmdtab.c | 9 ++- src/appl/gssftp/ftp/ftp.c | 49 ++++++------- src/appl/gssftp/ftp/ftp_var.h | 3 +- src/appl/gssftp/ftp/main.c | 7 +- src/appl/gssftp/ftp/secure.c | 28 ++++---- 7 files changed, 166 insertions(+), 69 deletions(-) diff --git a/src/appl/gssftp/ftp/ChangeLog b/src/appl/gssftp/ftp/ChangeLog index 780ab4587..6c0321c06 100644 --- a/src/appl/gssftp/ftp/ChangeLog +++ b/src/appl/gssftp/ftp/ChangeLog @@ -1,3 +1,17 @@ +Wed Aug 12 02:26:26 1998 Geoffrey King + + * ftp.c, cmds.c, cmdtab.c, main.c, secure.c, ftp_var.h: Replace + global variable level with separate variables clevel and dlevel + for the control channel and data channel protection levels, + respectively, so that the user may specify separate protection + levels for each channel. Similarly, functions such as getlevel + and setlevel are now getclevel/getdlevel, and setclevel/setdlevel. + + * cmdtab.c: Add new FTP commands "cprotect" to allow the user to + set the control channel protection level (similar to "protect"), + and "ccc" (Clear Command Channel) which sets the control channel + protection level to clear (per the RFC). + Fri Aug 7 22:39:47 1998 Matthew D Hancher * ftp.c (do_auth): Make verbosity not disappear if GSSAPI fails. diff --git a/src/appl/gssftp/ftp/cmds.c b/src/appl/gssftp/ftp/cmds.c index 81e6fee1c..d1dfc9c09 100644 --- a/src/appl/gssftp/ftp/cmds.c +++ b/src/appl/gssftp/ftp/cmds.c @@ -160,7 +160,7 @@ setpeer(argc, argv) /* * Set up defaults for FTP. */ - level = PROT_C; + clevel = dlevel = PROT_C; type = TYPE_A; curtype = TYPE_A; form = FORM_N; @@ -169,15 +169,17 @@ setpeer(argc, argv) (void) strcpy(bytename, "8"), bytesize = 8; if (autoauth) { if (do_auth() && autoencrypt) { + clevel = PROT_P; setpbsz(1<<20); if (command("PROT P") == COMPLETE) - level = PROT_P; + dlevel = PROT_P; else fprintf(stderr, "ftp: couldn't enable encryption\n"); } - + if(auth_type && clevel == PROT_C) + clevel = PROT_S; if(autologin) - (void) login(argv[1]); + (void) login(argv[1]); } #ifndef unix @@ -259,18 +261,85 @@ struct levels { }; char * -getlevel() +getclevel() { register struct levels *p; - for (p = levels; p->p_level != level; p++); + for (p = levels; p->p_level != clevel; p++); return(p->p_name); } +char * +getdlevel() +{ + register struct levels *p; + + for (p = levels; p->p_level != dlevel; p++); + return(p->p_name); +} + +char *plevel[] = { + "protect", + "", + 0 +}; + +/* + * Set control channel protection level. + */ +setclevel(argc, argv) + char *argv[]; +{ + register struct levels *p; + int comret; + + if (argc > 2) { + char *sep; + + printf("usage: %s [", argv[0]); + sep = " "; + for (p = levels; p->p_name; p++) { + printf("%s%s", sep, p->p_name); + if (*sep == ' ') + sep = " | "; + } + printf(" ]\n"); + code = -1; + return; + } + if (argc < 2) { + printf("Using %s protection level for commands.\n", + getclevel()); + code = 0; + return; + } + for (p = levels; p->p_name; p++) + if (strcmp(argv[1], p->p_name) == 0) + break; + if (p->p_name == 0) { + printf("%s: unknown protection level\n", argv[1]); + code = -1; + return; + } + if (!auth_type) { + if (strcmp(p->p_name, "clear")) + printf("Cannot set protection level to %s\n", argv[1]); + return; + } + if (!strcmp(p->p_name, "clear")) { + comret = command("CCC"); + if (comret == COMPLETE) + clevel = PROT_C; + return; + } + clevel = p->p_level; + printf("Control channel protection level set to %s.\n", p->p_name); +} + /* - * Set protection level. + * Set data channel protection level. */ -setlevel(argc, argv) +setdlevel(argc, argv) char *argv[]; { register struct levels *p; @@ -292,7 +361,7 @@ setlevel(argc, argv) } if (argc < 2) { printf("Using %s protection level to transfer files.\n", - getlevel()); + getdlevel()); code = 0; return; } @@ -313,44 +382,49 @@ setlevel(argc, argv) if (p->p_level != PROT_C) setpbsz(1<<20); comret = command("PROT %s", p->p_mode); if (comret == COMPLETE) - level = p->p_level; + dlevel = p->p_level; } -char *plevel[] = { - "protect", - "", - 0 -}; /* - * Set clear protection level. + * Set clear command protection level. + */ +/*VARARGS*/ +ccc() +{ + plevel[1] = "clear"; + setclevel(2, plevel); +} + +/* + * Set clear data protection level. */ /*VARARGS*/ setclear() { plevel[1] = "clear"; - setlevel(2, plevel); + setdlevel(2, plevel); } /* - * Set safe protection level. + * Set safe data protection level. */ /*VARARGS*/ setsafe() { plevel[1] = "safe"; - setlevel(2, plevel); + setdlevel(2, plevel); } #ifndef NOENCRYPTION /* - * Set private protection level. + * Set private data protection level. */ /*VARARGS*/ setprivate() { plevel[1] = "private"; - setlevel(2, plevel); + setdlevel(2, plevel); } #endif @@ -1021,7 +1095,8 @@ cstatus() printf("Connected %sto %s.\n", proxy ? "for proxy commands " : "", hostname); if (auth_type) printf("Authentication type: %s\n", auth_type); - printf("Protection Level: %s\n", getlevel()); + printf("Control Channel Protection Level: %s\n", getclevel()); + printf("Data Channel Protection Level: %s\n", getdlevel()); printf("Passive mode %s\n", onoff(passivemode)); printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", getmode(), gettype(), getform(), getstruct()); @@ -1494,12 +1569,12 @@ user(argc, argv) if (argc < 3 ) argv[2] = mygetpass("Password: "), argc++; #ifndef NOENCRYPTION - if ((oldlevel = level) == PROT_S) level = PROT_P; + if ((oldlevel = dlevel) == PROT_S) dlevel = PROT_P; #endif n = command("PASS %s", argv[2]); #ifndef NOENCRYPTION /* level may have changed */ - if (level == PROT_P) level = oldlevel; + if (dlevel == PROT_P) dlevel = oldlevel; #endif } if (n == CONTINUE) { @@ -1730,7 +1805,7 @@ disconnect() macnum = 0; } auth_type = NULL; - level = PROT_C; + dlevel = PROT_C; } confirm(cmd, file) diff --git a/src/appl/gssftp/ftp/cmdtab.c b/src/appl/gssftp/ftp/cmdtab.c index f20660cac..cb61fc811 100644 --- a/src/appl/gssftp/ftp/cmdtab.c +++ b/src/appl/gssftp/ftp/cmdtab.c @@ -45,7 +45,7 @@ int setascii(), setbell(), setbinary(), setdebug(), setform(); int setglob(), sethash(), setmode(), setpeer(), setport(); int setprompt(), setstruct(); int settenex(), settrace(), settype(), setverbose(); -int setlevel(), setclear(), setsafe(); +int setclevel(), setdlevel(), setclear(), setsafe(), ccc(); #ifndef NOENCRYPTION int setprivate(); #endif @@ -69,6 +69,7 @@ char asciihelp[] = "set ascii transfer type"; char beephelp[] = "beep when command completed"; char binaryhelp[] = "set binary transfer type"; char casehelp[] = "toggle mget upper/lower case id mapping"; +char ccchelp[] = "set clear protection level for commands"; char cdhelp[] = "change remote working directory"; char cduphelp[] = "change remote working directory to parent directory"; char chmodhelp[] = "change file permissions of remote file"; @@ -87,6 +88,7 @@ char helphelp[] = "print local help information"; char idlehelp[] = "get (set) idle timer on remote side"; char lcdhelp[] = "change local working directory"; char levelhelp[] = "set protection level for file transfer"; +char clevelhelp[] = "set protection level for commands"; char lshelp[] = "list contents of remote directory"; char macdefhelp[] = "define a macro"; char mdeletehelp[] = "delete multiple files"; @@ -148,11 +150,13 @@ struct cmd cmdtab[] = { { "binary", binaryhelp, 0, 1, 1, setbinary }, { "bye", quithelp, 0, 0, 0, quit }, { "case", casehelp, 0, 0, 1, setcase }, + { "ccc", ccchelp, 0, 1, 1, ccc }, { "cd", cdhelp, 0, 1, 1, cd }, { "cdup", cduphelp, 0, 1, 1, cdup }, { "chmod", chmodhelp, 0, 1, 1, do_chmod }, { "clear", clearhelp, 0, 1, 1, setclear }, { "close", disconhelp, 0, 1, 1, disconnect }, + { "cprotect", clevelhelp, 0, 1, 1, setclevel }, { "cr", crhelp, 0, 0, 0, setcr }, { "delete", deletehelp, 0, 1, 1, delete_file }, { "debug", debughelp, 0, 0, 0, setdebug }, @@ -188,7 +192,7 @@ struct cmd cmdtab[] = { { "private", privatehelp, 0, 1, 1, setprivate }, #endif { "prompt", prompthelp, 0, 0, 0, setprompt }, - { "protect", levelhelp, 0, 1, 1, setlevel }, + { "protect", levelhelp, 0, 1, 1, setdlevel }, { "proxy", proxyhelp, 0, 0, 1, doproxy }, { "sendport", porthelp, 0, 0, 0, setport }, { "put", sendhelp, 1, 1, 1, put }, @@ -223,3 +227,4 @@ struct cmd cmdtab[] = { }; int NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1; + diff --git a/src/appl/gssftp/ftp/ftp.c b/src/appl/gssftp/ftp/ftp.c index 66f1a1f26..b2e7ebd3b 100644 --- a/src/appl/gssftp/ftp/ftp.c +++ b/src/appl/gssftp/ftp/ftp.c @@ -293,17 +293,17 @@ login(host) n = command("PASS dummy"); 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; + if ((oldclevel = clevel) == PROT_S) 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) { @@ -349,14 +349,10 @@ secure_command(cmd) 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 ... - */ + 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) @@ -364,7 +360,7 @@ secure_command(cmd) 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 /* KRB5_KRB4_COMPAT */ @@ -374,27 +370,27 @@ secure_command(cmd) 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); @@ -408,10 +404,10 @@ secure_command(cmd) 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); @@ -472,10 +468,10 @@ again: if (secure_command(in) == 0) 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 @@ -1541,7 +1537,8 @@ pswitch(flag) char mi[MAXPATHLEN]; char mo[MAXPATHLEN]; char *authtype; - int lvl; + int clvl; + int dlvl; #ifdef KRB5_KRB4_COMPAT C_Block session; Key_schedule schedule; @@ -1610,10 +1607,14 @@ pswitch(flag) (void) strcpy(mapout, op->mo); ip->authtype = auth_type; auth_type = op->authtype; - ip->lvl = level; - level = op->lvl; - if (!level) - level = 1; + 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)); diff --git a/src/appl/gssftp/ftp/ftp_var.h b/src/appl/gssftp/ftp/ftp_var.h index dcc19f206..c2c03f39e 100644 --- a/src/appl/gssftp/ftp/ftp_var.h +++ b/src/appl/gssftp/ftp/ftp_var.h @@ -77,7 +77,8 @@ extern char ntout[17]; /* output translation table */ #include extern char mapin[MAXPATHLEN]; /* input map template */ extern char mapout[MAXPATHLEN]; /* output map template */ -extern int level; /* protection level */ +extern int clevel; /* command channel protection level */ +extern int dlevel; /* data channel protection level */ extern int type; /* requested file transfer type */ extern int curtype; /* current file transfer type */ extern int stru; /* file transfer structure */ diff --git a/src/appl/gssftp/ftp/main.c b/src/appl/gssftp/ftp/main.c index 1eac2ff2a..2ba3a4cf7 100644 --- a/src/appl/gssftp/ftp/main.c +++ b/src/appl/gssftp/ftp/main.c @@ -225,7 +225,8 @@ lostpeer(sig) extern FILE *cout; extern int data; extern char *auth_type; - extern int level; + extern int clevel; + extern int dlevel; if (connected) { if (cout != NULL) { @@ -240,7 +241,7 @@ lostpeer(sig) } connected = 0; auth_type = NULL; - level = PROT_C; + clevel = dlevel = PROT_C; } pswitch(1); if (connected) { @@ -251,7 +252,7 @@ lostpeer(sig) } connected = 0; auth_type = NULL; - level = PROT_C; + clevel = dlevel = PROT_C; } proxflag = 0; pswitch(0); diff --git a/src/appl/gssftp/ftp/secure.c b/src/appl/gssftp/ftp/secure.c index cc707ffd3..57653b628 100644 --- a/src/appl/gssftp/ftp/secure.c +++ b/src/appl/gssftp/ftp/secure.c @@ -49,7 +49,7 @@ typedef long ftp_int32; extern struct sockaddr_in hisaddr; extern struct sockaddr_in myaddr; -extern int level; +extern int dlevel; extern char *auth_type; #define MAX maxbuf @@ -171,7 +171,7 @@ int fd; { int ret; - if (level == PROT_C) + if (dlevel == PROT_C) return(0); if (nout) if (ret = secure_putbuf(fd, ucbuf, nout)) @@ -188,7 +188,7 @@ secure_putc(c, stream) char c; FILE *stream; { - if (level == PROT_C) + if (dlevel == PROT_C) return(putc(c,stream)); return(secure_putbyte(fileno(stream), (unsigned char) c)); } @@ -206,7 +206,7 @@ unsigned int nbyte; unsigned int i; int c; - if (level == PROT_C) + if (dlevel == PROT_C) return(write(fd,buf,nbyte)); for (i=0; nbyte>0; nbyte--) if ((c = secure_putbyte(fd, buf[i++])) < 0) @@ -245,13 +245,13 @@ unsigned int nbyte; } if (strcmp(auth_type, "KERBEROS_V4") == 0) - if ((length = level == PROT_P ? + if ((length = dlevel == PROT_P ? krb_mk_priv(buf, (unsigned char *) outbuf, nbyte, schedule, SESSION, &myaddr, &hisaddr) : krb_mk_safe(buf, (unsigned char *) outbuf, nbyte, SESSION, &myaddr, &hisaddr)) == -1) { secure_error("krb_mk_%s failed for KERBEROS_V4", - level == PROT_P ? "priv" : "safe"); + dlevel == PROT_P ? "priv" : "safe"); return(ERR); } #endif /* KRB5_KRB4_COMPAT */ @@ -264,7 +264,7 @@ unsigned int nbyte; in_buf.value = buf; in_buf.length = nbyte; maj_stat = gss_seal(&min_stat, gcontext, - (level == PROT_P), /* confidential */ + (dlevel == PROT_P), /* confidential */ GSS_C_QOP_DEFAULT, &in_buf, &conf_state, &out_buf); @@ -272,7 +272,7 @@ unsigned int nbyte; /* generally need to deal */ /* ie. should loop, but for now just fail */ secure_gss_error(maj_stat, min_stat, - level == PROT_P? + dlevel == PROT_P? "GSSAPI seal failed": "GSSAPI sign failed"); return(ERR); @@ -333,13 +333,13 @@ int fd; /* Other auth types go here ... */ #ifdef KRB5_KRB4_COMPAT if (strcmp(auth_type, "KERBEROS_V4") == 0) { - if (kerror = level == PROT_P ? + if (kerror = dlevel == PROT_P ? krb_rd_priv(ucbuf, length, schedule, SESSION, &hisaddr, &myaddr, &msg_data) : krb_rd_safe(ucbuf, length, SESSION, &hisaddr, &myaddr, &msg_data)) { secure_error("krb_rd_%s failed for KERBEROS_V4 (%s)", - level == PROT_P ? "priv" : "safe", + dlevel == PROT_P ? "priv" : "safe", krb_get_err_text(kerror)); return(ERR); } @@ -355,13 +355,13 @@ int fd; xmit_buf.value = ucbuf; xmit_buf.length = length; - conf_state = (level == PROT_P); + conf_state = (dlevel == PROT_P); /* decrypt/verify the message */ maj_stat = gss_unseal(&min_stat, gcontext, &xmit_buf, &msg_buf, &conf_state, NULL); if (maj_stat != GSS_S_COMPLETE) { secure_gss_error(maj_stat, min_stat, - (level == PROT_P)? + (dlevel == PROT_P)? "failed unsealing ENC message": "failed unsealing MIC message"); return ERR; @@ -386,7 +386,7 @@ int fd; secure_getc(stream) FILE *stream; { - if (level == PROT_C) + if (dlevel == PROT_C) return(getc(stream)); return(secure_getbyte(fileno(stream))); } @@ -405,7 +405,7 @@ int nbyte; static int c; int i; - if (level == PROT_C) + if (dlevel == PROT_C) return(read(fd,buf,nbyte)); if (c == EOF) return(c = 0); -- 2.26.2