* ftp.c, cmds.c, cmdtab.c, main.c, secure.c, ftp_var.h: Replace
authorGeoffrey King <gjking@mit.edu>
Wed, 12 Aug 1998 06:53:38 +0000 (06:53 +0000)
committerGeoffrey King <gjking@mit.edu>
Wed, 12 Aug 1998 06:53:38 +0000 (06:53 +0000)
        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
src/appl/gssftp/ftp/cmds.c
src/appl/gssftp/ftp/cmdtab.c
src/appl/gssftp/ftp/ftp.c
src/appl/gssftp/ftp/ftp_var.h
src/appl/gssftp/ftp/main.c
src/appl/gssftp/ftp/secure.c

index 780ab45872271e2fafcbc2131347d210e0a23c8c..6c0321c06e88baab3fd9f5d715f9ca9d42a3d0f4 100644 (file)
@@ -1,3 +1,17 @@
+Wed Aug 12 02:26:26 1998  Geoffrey King  <gjking@mit.edu>
+
+       * 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  <mdh@mit.edu>
 
        * ftp.c (do_auth): Make verbosity not disappear if GSSAPI fails.
index 81e6fee1ceb27b7b742ad0bc0fc9b435b23ab467..d1dfc9c09fb8bd9301a923aeef325ee876fa77a7 100644 (file)
@@ -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)
index f20660cac824ea694d5055bbd2ce2569a34458c2..cb61fc811c8d8e271778ad365f55d08cef9638bb 100644 (file)
@@ -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;
+
index 66f1a1f26f8b20bb48ac94ff2664fc040f1afac9..b2e7ebd3b5163badc34950934a2dc97550ee4d85 100644 (file)
@@ -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));
index dcc19f206ecd0ac83b71c2f33250c0db965f53c1..c2c03f39e81172ca501ec28b56e4aacf8d31e789 100644 (file)
@@ -77,7 +77,8 @@ extern char   ntout[17];      /* output translation table */
 #include <sys/param.h>
 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 */
index 1eac2ff2af5ca7a08f5c21a015d5dffe04990c51..2ba3a4cf7886a4d3fbb367294768a583e9a8e275 100644 (file)
@@ -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);
index cc707ffd3ef383b0cfe5d4d033e969cf31e8b522..57653b62817c43e7da496d56d479b264b2a1733e 100644 (file)
@@ -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);