300
284
int addrlen, c, on = 1, tos, port = -1;
301
285
extern char *optarg;
302
286
extern int optopt;
303
#ifdef KRB5_KRB4_COMPAT
304
char *option_string = "AaCcdElp:r:s:T:t:U:u:vw:";
305
#else /* !KRB5_KRB4_COMPAT */
306
char *option_string = "AaCcdElp:r:T:t:U:u:vw:";
307
#endif /* KRB5_KRB4_COMPAT */
287
char *option_string = "AaCcdElp:T:t:U:u:vw:";
308
288
ftpusers = _PATH_FTPUSERS_DEFAULT;
310
#ifdef KRB5_KRB4_COMPAT
312
#endif /* KRB5_KRB4_COMPAT */
314
291
#ifdef SETPROCTITLE
780
746
syslog(LOG_ERR, "user: username too long");
781
747
name = "[username too long]";
783
sprintf(buf, "GSSAPI user %s is%s authorized as %s",
749
snprintf(buf, sizeof(buf),
750
"GSSAPI user %s is%s authorized as %s",
784
751
(char *) client_name.value,
785
752
authorized ? "" : " not",
788
#ifdef KRB5_KRB4_COMPAT
790
#endif /* KRB5_KRB4_COMPAT */
791
755
#endif /* GSSAPI */
792
#ifdef KRB5_KRB4_COMPAT
793
if (auth_type && strcmp(auth_type, "KERBEROS_V4") == 0) {
796
authorized = kuserok(&kdata,name) == 0;
797
len = sizeof("Kerberos user .@ is not authorized as "
798
"; Password required.")
799
+ strlen(kdata.pname)
800
+ strlen(kdata.pinst)
801
+ strlen(kdata.prealm)
803
if (len >= sizeof(buf)) {
804
syslog(LOG_ERR, "user: username too long");
805
name = "[username too long]";
807
sprintf(buf, "Kerberos user %s%s%s@%s is%s authorized as %s",
808
kdata.pname, *kdata.pinst ? "." : "",
809
kdata.pinst, kdata.prealm,
810
authorized ? "" : " not", name);
812
#endif /* KRB5_KRB4_COMPAT */
814
757
if (!authorized && authlevel == AUTHLEVEL_AUTHORIZE) {
815
758
strncat(buf, "; Access denied.",
987
916
krb5_cc_destroy(kcontext, ccache);
992
#ifdef KRB5_KRB4_COMPAT
993
if (krb_get_lrealm(realm, 1) != KSUCCESS)
996
sprintf(ccname, "%s_ftpd%ld", TKT_ROOT, (long) getpid());
997
krb_set_tkt_string(ccname);
999
if (krb_get_pw_in_tkt(name, "", realm, "krbtgt", realm, 1, passwd))
1003
/* Verify the ticket since we didn't verify the krb5 one. */
1004
strncpy(instance, krb_get_phost(hostname), sizeof(instance));
1006
if ((hp = gethostbyname(instance)) == NULL)
1008
memcpy((char *) &faddr, (char *)hp->h_addr, sizeof(faddr));
1010
for (service = krb4_services; *service; service++) {
1011
if (!read_service_key(*service, instance,
1012
realm, 0, keyfile, key)) {
1013
(void) memset(key, 0, sizeof(key));
1014
if (krb_mk_req(&ticket, *service,
1015
instance, realm, 33) ||
1016
krb_rd_req(&ticket, *service, instance,
1017
faddr, &authdata,keyfile) ||
1018
kuserok(&authdata, name)) {
1036
#endif /* KRB5_KRB4_COMPAT */
1038
#if defined(GSSAPI) || defined(KRB5_KRB4_COMPAT)
1041
#endif /* GSSAPI || KRB5_KRB4_COMPAT */
1114
995
const char *ccname = krb5_cc_get_name(kcontext, ccache);
1115
996
chown(ccname, pw->pw_uid, pw->pw_gid);
1117
#ifdef KRB5_KRB4_COMPAT
1118
chown(tkt_string(), pw->pw_uid, pw->pw_gid);
1122
1000
(void) krb5_setegid((gid_t)pw->pw_gid);
1123
1001
(void) initgroups(pw->pw_name, pw->pw_gid);
1125
1003
/* open wtmp before chroot */
1126
(void) sprintf(ttyline, "ftp%ld", (long) getpid());
1004
(void) snprintf(ttyline, sizeof(ttyline), "ftp%ld", (long) getpid());
1127
1005
pty_logwtmp(ttyline, pw->pw_name, rhost_sane);
1176
1054
reply(230, "Guest login ok, access restrictions apply.");
1177
1055
#ifdef SETPROCTITLE
1178
sprintf(proctitle, "%s: anonymous/%.*s", rhost_sane,
1179
sizeof(proctitle) - strlen(rhost_sane) -
1180
sizeof(": anonymous/"), passwd);
1056
snprintf(proctitle, sizeof(proctitle), "%s: anonymous/%.*s",
1057
rhost_sane, passwd);
1181
1058
setproctitle(proctitle);
1182
1059
#endif /* SETPROCTITLE */
1190
1067
reply(230, "User %s logged in.", pw->pw_name);
1192
1069
#ifdef SETPROCTITLE
1193
sprintf(proctitle, "%s: %s", rhost_sane, pw->pw_name);
1070
snprintf(proctitle, sizeof(proctitle), "%s: %s",
1071
rhost_sane, pw->pw_name);
1194
1072
setproctitle(proctitle);
1195
1073
#endif /* SETPROCTITLE */
1472
1351
* XXX callers need to limit total length of output string to
1477
1355
secure_error(char *fmt, ...)
1481
secure_error(fmt, p1, p2, p3, p4, p5)
1485
1357
char buf[FTP_BUFSIZ];
1489
1360
va_start(ap, fmt);
1490
vsprintf(buf, fmt, ap);
1361
vsnprintf(buf, sizeof(buf), fmt, ap);
1493
sprintf(buf, fmt, p1, p2, p3, p4, p5);
1495
1363
reply(535, "%s", buf);
1496
1364
syslog(LOG_ERR, "%s", buf);
1683
1551
reply(501, "filename too long");
1686
(void) sprintf(line, "/bin/ls -lgA %s", filename);
1554
(void) snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
1687
1555
fin = ftpd_popen(line, "r");
1688
1556
lreply(211, "status of %s:", filename);
1733
1601
lreply(211, "%s FTP server status:", hostname);
1734
1602
reply(0, " %s", version);
1735
sprintf(str, " Connected to %s", remotehost[0] ? remotehost : "");
1736
sprintf(&str[strlen(str)], " (%s)", rhost_addra);
1603
snprintf(str, sizeof(str), " Connected to %s (%s)",
1604
remotehost[0] ? remotehost : "", rhost_addra);
1737
1605
reply(0, "%s", str);
1738
1606
if (auth_type) reply(0, " Authentication type: %s", auth_type);
1739
1607
if (logged_in) {
1749
1617
reply(0, " Waiting for user name");
1750
1618
reply(0, " Protection level: %s", levelnames[dlevel]);
1751
sprintf(str, " TYPE: %s", typenames[type]);
1752
if (type == TYPE_A || type == TYPE_E)
1753
sprintf(&str[strlen(str)], ", FORM: %s", formnames[form]);
1619
snprintf(str, sizeof(str), " TYPE: %s", typenames[type]);
1620
if (type == TYPE_A || type == TYPE_E) {
1621
snprintf(&str[strlen(str)], sizeof(str) - strlen(str),
1622
", FORM: %s", formnames[form]);
1754
1624
if (type == TYPE_L)
1756
1625
strncat(str, " 8", sizeof (str) - strlen(str) - 1);
1758
/* this is silly. -- eichin@cygnus.com */
1760
sprintf(&str[strlen(str)], " %d", NBBY);
1762
sprintf(&str[strlen(str)], " %d", bytesize); /* need definition! */
1765
sprintf(&str[strlen(str)], "; STRUcture: %s; transfer MODE: %s",
1766
strunames[stru], modenames[mode]);
1626
snprintf(&str[strlen(str)], sizeof(str) - strlen(str),
1627
"; STRUcture: %s; transfer MODE: %s",
1628
strunames[stru], modenames[mode]);
1767
1629
reply(0, "%s", str);
1768
1630
if (data != -1)
1769
strcpy(str, " Data connection open");
1631
strlcpy(str, " Data connection open", sizeof(str));
1770
1632
else if (pdata != -1) {
1771
strcpy(str, " in Passive mode");
1633
strlcpy(str, " in Passive mode", sizeof(str));
1772
1634
sin4 = &pasv_addr;
1773
1635
goto printaddr;
1774
1636
} else if (usedefault == 0) {
1775
strcpy(str, " PORT");
1776
1637
sin4 = &data_dest;
1778
1639
a = (u_char *) &sin4->sin_addr;
1779
1640
p = (u_char *) &sin4->sin_port;
1780
1641
#define UC(b) (((int) b) & 0xff)
1781
sprintf(&str[strlen(str)], " (%d,%d,%d,%d,%d,%d)", UC(a[0]),
1782
UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
1642
snprintf(str, sizeof(str), " PORT (%d,%d,%d,%d,%d,%d)",
1643
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]),
1785
strcpy(str, " No data connection");
1647
strlcpy(str, " No data connection", sizeof(str));
1786
1648
reply(0, "%s", str);
1787
1649
reply(211, "End of status");
1821
1683
va_start(ap, fmt);
1822
vsprintf(buf, fmt, ap);
1684
vsnprintf(buf, sizeof(buf), fmt, ap);
1825
sprintf(buf, fmt, p0, p1, p2, p3, p4, p5);
1687
snprintf(buf, sizeof(buf), fmt, p0, p1, p2, p3, p4, p5);
1828
1690
if (auth_type) {
1833
1695
char in[FTP_BUFSIZ*3/2], out[FTP_BUFSIZ*3/2];
1834
1696
int length = 0, kerror;
1835
if (n) sprintf(in, "%d%c", n, cont_char);
1697
if (n) snprintf(in, sizeof(in), "%d%c", n, cont_char);
1836
1698
else in[0] = '\0';
1837
1699
strncat(in, buf, sizeof (in) - strlen(in) - 1);
1838
#ifdef KRB5_KRB4_COMPAT
1839
if (strcmp(auth_type, "KERBEROS_V4") == 0) {
1840
if (clevel == PROT_P)
1841
length = krb_mk_priv((unsigned char *)in,
1842
(unsigned char *)out,
1844
schedule, &kdata.session,
1848
length = krb_mk_safe((unsigned char *)in,
1849
(unsigned char *)out,
1856
"krb_mk_%s failed for KERBEROS_V4",
1857
clevel == PROT_P ? "priv" : "safe");
1861
#endif /* KRB5_KRB4_COMPAT */
1863
1701
/* reply (based on level) */
1864
1702
if (strcmp(auth_type, "GSSAPI") == 0) {
1939
1777
va_start(ap, fmt);
1940
vsprintf(buf, fmt, ap);
1778
vsnprintf(buf, sizeof(buf), fmt, ap);
1943
sprintf(buf, fmt, p0, p1, p2, p3, p4, p5);
1781
snprintf(buf, sizeof(buf), fmt, p0, p1, p2, p3, p4, p5);
1945
1783
cont_char = '-';
1946
1784
reply(n, "%s", buf);
2292
2127
reply(534, "Authentication type already set to %s", auth_type);
2294
#ifdef KRB5_KRB4_COMPAT
2295
if (strcmp(atype, "KERBEROS_V4") == 0)
2296
reply(334, "Using authentication type %s; ADAT must follow",
2297
temp_auth_type = atype);
2299
#endif /* KRB5_KRB4_COMPAT */
2301
2130
if (strcmp(atype, "GSSAPI") == 0)
2302
2131
reply(334, "Using authentication type %s; ADAT must follow",
2328
2150
reply(503, "Must identify AUTH type before ADAT");
2331
#ifdef KRB5_KRB4_COMPAT
2332
if (strcmp(temp_auth_type, "KERBEROS_V4") == 0) {
2333
kerror = radix_encode(adata, out_buf, &length, 1);
2335
reply(501, "Couldn't decode ADAT (%s)",
2336
radix_error(kerror));
2337
syslog(LOG_ERR, "Couldn't decode ADAT (%s)",
2338
radix_error(kerror));
2341
(void) memcpy((char *)ticket.dat, (char *)out_buf, ticket.length = length);
2342
strcpy(instance, "*");
2345
for (service = krb4_services; *service; service++) {
2346
kerror = krb_rd_req(&ticket, *service, instance,
2347
his_addr.sin_addr.s_addr,
2352
/* rd_req failed.... */
2354
secure_error("ADAT: Kerberos V4 krb_rd_req: %s",
2355
krb_get_err_text(kerror));
2359
/* add one to the (formerly) sealed checksum, and re-seal it */
2360
cksum = kdata.checksum + 1;
2361
cksum = htonl(cksum);
2362
key_sched(kdata.session,schedule);
2363
if ((length = krb_mk_safe((u_char *)&cksum, out_buf, sizeof(cksum),
2364
&kdata.session,&ctrl_addr, &his_addr)) == -1) {
2365
secure_error("ADAT: krb_mk_safe failed");
2368
if (length >= (FTP_BUFSIZ - sizeof("ADAT=")) / 4 * 3) {
2369
secure_error("ADAT: reply too long");
2373
kerror = radix_encode(out_buf, buf, &length, 0);
2375
secure_error("Couldn't encode ADAT reply (%s)",
2376
radix_error(kerror));
2379
reply(235, "ADAT=%s", buf);
2380
/* Kerberos V4 authentication succeeded */
2381
auth_type = temp_auth_type;
2382
temp_auth_type = NULL;
2385
#endif /* KRB5_KRB4_COMPAT */
2387
2154
if (strcmp(temp_auth_type, "GSSAPI") == 0) {
2388
2155
int replied = 0;
2432
2199
localname[sizeof(localname) - 1] = '\0';
2434
2201
for (gservice = gss_services; *gservice; gservice++) {
2435
sprintf(service_name, "%s@%s", *gservice, localname);
2202
snprintf(service_name, sizeof(service_name),
2203
"%s@%s", *gservice, localname);
2436
2204
name_buf.value = service_name;
2437
2205
name_buf.length = strlen(name_buf.value) + 1;
2620
2388
* XXX callers need to limit total length of output string to
2625
2392
secure_fprintf(FILE *stream, char *fmt, ...)
2628
secure_fprintf(stream, fmt, p1, p2, p3, p4, p5)
2393
#if !defined(__cplusplus) && (__GNUC__ > 2)
2394
__attribute__((__format__(__printf__, 2, 3)))
2399
secure_fprintf(FILE *stream, char *fmt, ...)
2633
2401
char s[FTP_BUFSIZ];
2638
2405
va_start(ap, fmt);
2639
2406
if (dlevel == PROT_C) rval = vfprintf(stream, fmt, ap);
2641
vsprintf(s, fmt, ap);
2408
vsnprintf(s, sizeof(s), fmt, ap);
2642
2409
rval = secure_write(fileno(stream), s, strlen(s));
2648
if (dlevel == PROT_C)
2649
return(fprintf(stream, fmt, p1, p2, p3, p4, p5));
2650
sprintf(s, fmt, p1, p2, p3, p4, p5);
2651
return(secure_write(fileno(stream), s, strlen(s)));
2944
2706
OM_uint32 major_status, minor_status;
2945
2707
krb5_principal me;
2946
2708
char ccname[MAXPATHLEN];
2947
#ifdef KRB5_KRB4_COMPAT
2948
krb5_principal kpcserver;
2949
krb5_creds increds, *v5creds;
2950
CREDENTIALS v4creds;
2953
2710
/* Set up ccache */
2954
2711
if (krb5_parse_name(kcontext, name, &me))
2957
sprintf(ccname, "FILE:/tmp/krb5cc_ftpd%ld", (long) getpid());
2714
snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_ftpd%ld",
2958
2716
if (krb5_cc_resolve(kcontext, ccname, &ccache))
2960
2718
if (krb5_cc_initialize(kcontext, ccache, me))
2965
2723
if (major_status != GSS_S_COMPLETE)
2968
#ifdef KRB5_KRB4_COMPAT
2969
/* Convert krb5 creds to krb4 */
2971
if (krb5_build_principal_ext(kcontext, &kpcserver,
2972
krb5_princ_realm(kcontext, me)->length,
2973
krb5_princ_realm(kcontext, me)->data,
2975
krb5_princ_realm(kcontext, me)->length,
2976
krb5_princ_realm(kcontext, me)->data,
2980
memset((char *) &increds, 0, sizeof(increds));
2981
increds.client = me;
2982
increds.server = kpcserver;
2983
increds.times.endtime = 0;
2984
increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2985
if (krb5_get_credentials(kcontext, 0, ccache, &increds, &v5creds))
2987
if (krb524_convert_creds_kdc(kcontext, v5creds, &v4creds))
2990
sprintf(ccname, "%s_ftpd%ld", TKT_ROOT, (long) getpid());
2991
krb_set_tkt_string(ccname);
2993
if (in_tkt(v4creds.pname, v4creds.pinst) != KSUCCESS)
2996
if (krb_save_credentials(v4creds.service, v4creds.instance,
2997
v4creds.realm, v4creds.session,
2998
v4creds.lifetime, v4creds.kvno,
2999
&(v4creds.ticket_st), v4creds.issue_date))
3001
#endif /* KRB5_KRB4_COMPAT */
3002
2726
have_creds = 1;
3005
#ifdef KRB5_KRB4_COMPAT
3010
2730
krb5_cc_destroy(kcontext, ccache);