Index: ftpcmd.y =================================================================== RCS file: /cvs/krbdev/krb5/src/appl/gssftp/ftpd/ftpcmd.y,v retrieving revision 1.14.4.2 diff -c -r1.14.4.2 ftpcmd.y *** ftpcmd.y 2001/01/17 23:25:16 1.14.4.2 --- ftpcmd.y 2001/04/25 20:16:45 *************** *** 805,815 **** * This is a valid reply in some cases but not in others. */ if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) { ! *(char **)&($$) = *ftpglob((char *) $1); ! if (globerr != NULL) { reply(550, globerr); $$ = NULL; ! } free((char *) $1); } else $$ = $1; --- 805,819 ---- * This is a valid reply in some cases but not in others. */ if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) { ! char **vv; ! ! vv = ftpglob((char *) $1); ! if (vv == NULL || globerr != NULL) { reply(550, globerr); $$ = NULL; ! } else ! $$ = *vv; ! free((char *) $1); } else $$ = $1; Index: ftpd.c =================================================================== RCS file: /cvs/krbdev/krb5/src/appl/gssftp/ftpd/ftpd.c,v retrieving revision 1.43.2.1 diff -c -r1.43.2.1 ftpd.c *** ftpd.c 2000/05/23 21:39:07 1.43.2.1 --- ftpd.c 2001/04/25 20:16:48 *************** *** 761,767 **** --- 761,777 ---- int result; #ifdef GSSAPI if (auth_type && strcmp(auth_type, "GSSAPI") == 0) { + int len; + authorized = ftpd_gss_userok(&client_name, name) == 0; + len = sizeof("GSSAPI user is not authorized as " + "; Password required.") + + strlen(client_name.value) + + strlen(name); + if (len >= sizeof(buf)) { + syslog(LOG_ERR, "user: username too long"); + name = "[username too long]"; + } sprintf(buf, "GSSAPI user %s is%s authorized as %s", client_name.value, authorized ? "" : " not", name); *************** *** 772,778 **** --- 782,800 ---- #endif /* GSSAPI */ #ifdef KRB5_KRB4_COMPAT if (auth_type && strcmp(auth_type, "KERBEROS_V4") == 0) { + int len; + authorized = kuserok(&kdata,name) == 0; + len = sizeof("Kerberos user .@ is not authorized as " + "; Password required.") + + strlen(kdata.pname) + + strlen(kdata.pinst) + + strlen(kdata.prealm) + + strlen(name); + if (len >= sizeof(buf)) { + syslog(LOG_ERR, "user: username too long"); + name = "[username too long]"; + } sprintf(buf, "Kerberos user %s%s%s@%s is%s authorized as %s", kdata.pname, *kdata.pinst ? "." : "", kdata.pinst, kdata.prealm, *************** *** 1179,1184 **** --- 1201,1211 ---- } else { char line[FTP_BUFSIZ]; + if (strlen(cmd) + strlen(name) + 1 >= sizeof(line)) { + syslog(LOG_ERR, "retrieve: filename too long"); + reply(501, "filename too long"); + return; + } (void) sprintf(line, cmd, name), name = line; fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; st.st_size = -1; *************** *** 1417,1422 **** --- 1444,1453 ---- return (file); } + /* + * XXX callers need to limit total length of output string to + * FTP_BUFSIZ + */ #ifdef STDARG secure_error(char *fmt, ...) #else *************** *** 1616,1628 **** { char line[FTP_BUFSIZ]; FILE *fin; ! int c; char str[FTP_BUFSIZ], *p; (void) sprintf(line, "/bin/ls -lgA %s", filename); fin = ftpd_popen(line, "r"); lreply(211, "status of %s:", filename); p = str; while ((c = getc(fin)) != EOF) { if (c == '\n') { if (ferror(stdout)){ --- 1647,1665 ---- { char line[FTP_BUFSIZ]; FILE *fin; ! int c, n; char str[FTP_BUFSIZ], *p; + if (strlen(filename) + sizeof("/bin/ls -lgA ") + >= sizeof(line)) { + reply(501, "filename too long"); + return; + } (void) sprintf(line, "/bin/ls -lgA %s", filename); fin = ftpd_popen(line, "r"); lreply(211, "status of %s:", filename); p = str; + n = 0; while ((c = getc(fin)) != EOF) { if (c == '\n') { if (ferror(stdout)){ *************** *** 1639,1645 **** *p = '\0'; reply(0, "%s", str); p = str; ! } else *p++ = c; } if (p != str) { *p = '\0'; --- 1676,1691 ---- *p = '\0'; reply(0, "%s", str); p = str; ! n = 0; ! } else { ! *p++ = c; ! n++; ! if (n >= sizeof(str)) { ! reply(551, "output line too long"); ! (void) ftpd_pclose(fin); ! return; ! } ! } } if (p != str) { *p = '\0'; *************** *** 1723,1728 **** --- 1769,1778 ---- char cont_char = ' '; + /* + * XXX callers need to limit total length of output string to + * FTP_BUFSIZ bytes for now. + */ #ifdef STDARG reply(int n, char *fmt, ...) #else *************** *** 1744,1765 **** #endif if (auth_type) { ! char in[FTP_BUFSIZ], out[FTP_BUFSIZ]; int length, kerror; if (n) sprintf(in, "%d%c", n, cont_char); else in[0] = '\0'; strncat(in, buf, sizeof (in) - strlen(in) - 1); #ifdef KRB5_KRB4_COMPAT if (strcmp(auth_type, "KERBEROS_V4") == 0) { ! if ((length = clevel == PROT_P ? ! krb_mk_priv((unsigned char *)in, ! (unsigned char *)out, ! strlen(in), schedule, &kdata.session, ! &ctrl_addr, &his_addr) ! : krb_mk_safe((unsigned char *)in, ! (unsigned char *)out, ! strlen(in), &kdata.session, ! &ctrl_addr, &his_addr)) == -1) { syslog(LOG_ERR, "krb_mk_%s failed for KERBEROS_V4", clevel == PROT_P ? "priv" : "safe"); --- 1794,1825 ---- #endif if (auth_type) { ! /* ! * Deal with expansion in mk_{safe,priv}, ! * radix_encode, gss_seal, plus slop. ! */ ! char in[FTP_BUFSIZ*3/2], out[FTP_BUFSIZ*3/2]; int length, kerror; if (n) sprintf(in, "%d%c", n, cont_char); else in[0] = '\0'; strncat(in, buf, sizeof (in) - strlen(in) - 1); #ifdef KRB5_KRB4_COMPAT if (strcmp(auth_type, "KERBEROS_V4") == 0) { ! if (clevel == PROT_P) ! length = krb_mk_priv((unsigned char *)in, ! (unsigned char *)out, ! strlen(in), ! schedule, &kdata.session, ! &ctrl_addr, ! &his_addr); ! else ! length = krb_mk_safe((unsigned char *)in, ! (unsigned char *)out, ! strlen(in), ! &kdata.session, ! &ctrl_addr, ! &his_addr); ! if (length == -1) { syslog(LOG_ERR, "krb_mk_%s failed for KERBEROS_V4", clevel == PROT_P ? "priv" : "safe"); *************** *** 1803,1815 **** } #endif /* GSSAPI */ /* Other auth types go here ... */ ! if (kerror = radix_encode(out, in, &length, 0)) { syslog(LOG_ERR, "Couldn't encode reply (%s)", radix_error(kerror)); fputs(in,stdout); } else ! printf("%s%c%s", clevel == PROT_P ? "632" : "631", ! n ? cont_char : '-', in); } else { if (n) printf("%d%c", n, cont_char); fputs(buf, stdout); --- 1863,1878 ---- } #endif /* GSSAPI */ /* Other auth types go here ... */ ! if (length >= sizeof(in) / 4 * 3) { ! syslog(LOG_ERR, "input to radix_encode too long"); ! fputs(in, stdout); ! } else if (kerror = radix_encode(out, in, &length, 0)) { syslog(LOG_ERR, "Couldn't encode reply (%s)", radix_error(kerror)); fputs(in,stdout); } else ! printf("%s%c%s", clevel == PROT_P ? "632" : "631", ! n ? cont_char : '-', in); } else { if (n) printf("%d%c", n, cont_char); fputs(buf, stdout); *************** *** 1822,1827 **** --- 1885,1894 ---- } } + /* + * XXX callers need to limit total length of output string to + * FTP_BUFSIZ + */ #ifdef STDARG lreply(int n, char *fmt, ...) #else *************** *** 1866,1872 **** if (cp = strchr(cbuf,'\n')) *cp = '\0'; ! reply(500, "'%s': command not understood.", cbuf); } delete_file(name) --- 1933,1940 ---- if (cp = strchr(cbuf,'\n')) *cp = '\0'; ! reply(500, "'%.*s': command not understood.", ! FTP_BUFSIZ - sizeof("'': command not understood."), cbuf); } delete_file(name) *************** *** 2143,2149 **** int code; char *string; { ! reply(code, "%s: %s.", string, strerror(errno)); } auth(type) --- 2211,2233 ---- int code; char *string; { ! char *err_string; ! size_t extra_len; ! ! err_string = strerror(errno); ! if (err_string == NULL) ! err_string = "(unknown error)"; ! extra_len = strlen(err_string) + sizeof("(truncated): ."); ! ! /* ! * XXX knows about FTP_BUFSIZ in reply() ! */ ! if (strlen(string) + extra_len > FTP_BUFSIZ) { ! reply(code, "(truncated)%.*s: %s.", ! FTP_BUFSIZ - extra_len, string, err_string); ! } else { ! reply(code, "%s: %s.", string, err_string); ! } } auth(type) *************** *** 2226,2231 **** --- 2310,2319 ---- secure_error("ADAT: krb_mk_safe failed"); return(0); } + if (length >= (FTP_BUFSIZ - sizeof("ADAT=")) / 4 * 3) { + secure_error("ADAT: reply too long"); + return(0); + } if (kerror = radix_encode(out_buf, buf, &length, 0)) { secure_error("Couldn't encode ADAT reply (%s)", radix_error(kerror)); *************** *** 2360,2365 **** --- 2448,2463 ---- } if (out_tok.length) { + if (out_tok.length >= ((FTP_BUFSIZ - sizeof("ADAT=")) + / 4 * 3)) { + secure_error("ADAT: reply too long"); + syslog(LOG_ERR, "ADAT: reply too long"); + (void) gss_release_cred(&stat_min, &server_creds); + if (ret_flags & GSS_C_DELEG_FLAG) + (void) gss_release_cred(&stat_min, + &deleg_creds); + return(0); + } if (kerror = radix_encode(out_tok.value, gbuf, &out_tok.length, 0)) { secure_error("Couldn't encode ADAT reply (%s)", radix_error(kerror)); *************** *** 2458,2463 **** --- 2556,2564 ---- * n>=0 on success * -1 on error * -2 on security error + * + * XXX callers need to limit total length of output string to + * FTP_BUFSIZ */ #ifdef STDARG secure_fprintf(FILE *stream, char *fmt, ...) *************** *** 2575,2580 **** --- 2676,2690 ---- dir->d_name[2] == '\0') continue; + if (strlen(dirname) + strlen(dir->d_name) + + 1 /* slash */ + + 2 /* CRLF */ + + 1 > sizeof(nbuf)) { + syslog(LOG_ERR, + "send_file_list: pathname too long"); + ret = -2; /* XXX */ + goto data_err; + } sprintf(nbuf, "%s/%s", dirname, dir->d_name); /*