~ubuntu-branches/ubuntu/maverick/krb5/maverick

« back to all changes in this revision

Viewing changes to src/appl/gssftp/ftpd/ftpd.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2009-05-07 16:16:34 UTC
  • mfrom: (13.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090507161634-xqyk0s9na0le4flj
Tags: 1.7dfsg~beta1-4
When  decrypting the TGS response fails with the subkey, try with the
session key to work around Heimdal bug, Closes: #527353 

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
#include <sys/param.h>
48
48
#include <sys/stat.h>
49
49
#include <sys/ioctl.h>
50
 
#ifndef KRB5_KRB4_COMPAT
51
 
/* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
52
50
#include <sys/socket.h>
53
 
#endif
54
51
#include <sys/wait.h>
55
52
#include <sys/file.h>
56
53
#include <netinet/in.h>
80
77
#define sigsetjmp(j,s)  setjmp(j)
81
78
#define siglongjmp      longjmp
82
79
#endif
83
 
#ifndef KRB5_KRB4_COMPAT
84
 
/* krb.h gets this, and Ultrix doesn't protect vs multiple inclusion */
85
80
#include <netdb.h>
86
 
#endif
87
81
#include <errno.h>
88
82
#include <syslog.h>
89
83
#include <unistd.h>
102
96
#include "pathnames.h"
103
97
#include <libpty.h>
104
98
 
 
99
#include <k5-platform.h>
 
100
 
105
101
#ifdef NEED_SETENV
106
102
extern int setenv(char *, char *, int);
107
103
#endif
127
123
#include <k5-util.h>
128
124
#include "port-sockets.h"
129
125
 
130
 
#ifdef KRB5_KRB4_COMPAT
131
 
#include <krb5.h>
132
 
#include <krb.h>
133
 
 
134
 
AUTH_DAT kdata;
135
 
KTEXT_ST ticket;
136
 
MSG_DAT msg_data;
137
 
Key_schedule schedule;
138
 
char *keyfile;
139
 
static char *krb4_services[] = { "ftp", "rcmd", NULL };
140
 
#endif /* KRB5_KRB4_COMPAT */
141
 
 
142
126
#ifdef GSSAPI
143
127
#include <gssapi/gssapi.h>
144
128
#include <gssapi/gssapi_generic.h>
160
144
 
161
145
char *auth_type;        /* Authentication succeeded?  If so, what type? */
162
146
static char *temp_auth_type;
163
 
int authorized;         /* Auth succeeded and was accepted by krb4 or gssapi */
 
147
int authorized;         /* Auth succeeded and was accepted by gssapi */
164
148
int have_creds;         /* User has credentials on disk */
165
149
 
166
150
/*
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;
309
289
 
310
 
#ifdef KRB5_KRB4_COMPAT
311
 
        keyfile = KEYFILE;
312
 
#endif /* KRB5_KRB4_COMPAT */
313
290
        debug = 0;
314
291
#ifdef SETPROCTITLE
315
292
        /*
365
342
                        port = atoi(optarg);
366
343
                        break;
367
344
 
368
 
                case 'r':
369
 
                        setenv("KRB_CONF", optarg, 1);
370
 
                        break;
371
 
 
372
 
#ifdef KRB5_KRB4_COMPAT
373
 
                case 's':
374
 
                        keyfile = optarg;
375
 
                        break;
376
 
#endif /* KRB5_KRB4_COMPAT */
377
 
 
378
345
                case 't':
379
346
                        timeout = atoi(optarg);
380
347
                        if (maxtimeout < timeout)
580
547
sgetsave(s)
581
548
        char *s;
582
549
{
583
 
        char *new = malloc((unsigned) strlen(s) + 1);
 
550
        char *new = strdup(s);
584
551
 
585
552
        if (new == NULL) {
586
553
                perror_reply(421, "Local resource failure: malloc");
587
554
                dologout(1);
588
555
                /* NOTREACHED */
589
556
        }
590
 
        (void) strcpy(new, s);
591
557
        return (new);
592
558
}
593
559
 
780
746
                                syslog(LOG_ERR, "user: username too long");
781
747
                                name = "[username too long]";
782
748
                        }
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",
786
753
                                name);
787
754
                }
788
 
#ifdef KRB5_KRB4_COMPAT
789
 
                else
790
 
#endif /* KRB5_KRB4_COMPAT */
791
755
#endif /* GSSAPI */
792
 
#ifdef KRB5_KRB4_COMPAT
793
 
                if (auth_type && strcmp(auth_type, "KERBEROS_V4") == 0) {
794
 
                        int len;
795
 
 
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)
802
 
                                + strlen(name);
803
 
                        if (len >= sizeof(buf)) {
804
 
                                syslog(LOG_ERR, "user: username too long");
805
 
                                name = "[username too long]";
806
 
                        }
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);
811
 
                }
812
 
#endif /* KRB5_KRB4_COMPAT */
813
756
 
814
757
                if (!authorized && authlevel == AUTHLEVEL_AUTHORIZE) {
815
758
                        strncat(buf, "; Access denied.",
915
858
#ifdef GSSAPI
916
859
                krb5_cc_destroy(kcontext, ccache);
917
860
#endif
918
 
#ifdef KRB5_KRB4_COMPAT
919
 
                dest_tkt();
920
 
#endif
921
861
                have_creds = 0;
922
862
        }
923
863
        pw = NULL;
934
874
        krb5_creds my_creds;
935
875
        krb5_timestamp now;
936
876
#endif /* GSSAPI */
937
 
#ifdef KRB5_KRB4_COMPAT
938
 
        char realm[REALM_SZ];
939
 
#ifndef GSSAPI
940
 
        char **service;
941
 
        KTEXT_ST ticket;
942
 
        AUTH_DAT authdata;
943
 
        des_cblock key;
944
 
        char instance[INST_SZ];
945
 
        unsigned long faddr;
946
 
        struct hostent *hp;
947
 
#endif /* GSSAPI */
948
 
#endif /* KRB5_KRB4_COMPAT */
949
877
        char ccname[MAXPATHLEN];
950
878
 
951
879
#ifdef GSSAPI
954
882
                return 0;
955
883
        my_creds.client = me;
956
884
 
957
 
        sprintf(ccname, "FILE:/tmp/krb5cc_ftpd%ld", (long) getpid());
 
885
        snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_ftpd%ld",
 
886
                 (long) getpid());
958
887
        if (krb5_cc_resolve(kcontext, ccname, &ccache))
959
888
                return(0);
960
889
        if (krb5_cc_initialize(kcontext, ccache, me))
987
916
                krb5_cc_destroy(kcontext, ccache);
988
917
                return(1);
989
918
        }
990
 
#endif /* GSSAPI */
991
 
 
992
 
#ifdef KRB5_KRB4_COMPAT
993
 
        if (krb_get_lrealm(realm, 1) != KSUCCESS)
994
 
                goto nuke_ccache;
995
 
 
996
 
        sprintf(ccname, "%s_ftpd%ld", TKT_ROOT, (long) getpid());
997
 
        krb_set_tkt_string(ccname);
998
 
 
999
 
        if (krb_get_pw_in_tkt(name, "", realm, "krbtgt", realm, 1, passwd))
1000
 
                goto nuke_ccache;
1001
 
 
1002
 
#ifndef GSSAPI
1003
 
        /* Verify the ticket since we didn't verify the krb5 one. */
1004
 
        strncpy(instance, krb_get_phost(hostname), sizeof(instance));
1005
 
 
1006
 
        if ((hp = gethostbyname(instance)) == NULL)
1007
 
                goto nuke_ccache;
1008
 
        memcpy((char *) &faddr, (char *)hp->h_addr, sizeof(faddr));
1009
 
 
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)) {
1019
 
                                dest_tkt();
1020
 
                                goto nuke_ccache;
1021
 
                        } else
1022
 
                                break;
1023
 
                }
1024
 
        }
1025
 
 
1026
 
        if (!*service) {
1027
 
                dest_tkt();
1028
 
                goto nuke_ccache;
1029
 
        }
1030
 
 
1031
 
        if (!want_creds) {
1032
 
                dest_tkt();
1033
 
                return(1);
1034
 
        }
1035
 
#endif /* GSSAPI */
1036
 
#endif /* KRB5_KRB4_COMPAT */
1037
 
 
1038
 
#if defined(GSSAPI) || defined(KRB5_KRB4_COMPAT)
 
919
 
1039
920
        have_creds = 1;
1040
921
        return(1);
1041
 
#endif /* GSSAPI || KRB5_KRB4_COMPAT */
 
922
#endif /* GSSAPI */
1042
923
 
1043
924
nuke_ccache:
1044
925
#ifdef GSSAPI
1114
995
                const char *ccname = krb5_cc_get_name(kcontext, ccache);
1115
996
                chown(ccname, pw->pw_uid, pw->pw_gid);
1116
997
#endif
1117
 
#ifdef KRB5_KRB4_COMPAT
1118
 
                chown(tkt_string(), pw->pw_uid, pw->pw_gid);
1119
 
#endif
1120
998
        }
1121
999
 
1122
1000
        (void) krb5_setegid((gid_t)pw->pw_gid);
1123
1001
        (void) initgroups(pw->pw_name, pw->pw_gid);
1124
1002
 
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);
1128
1006
        logged_in = 1;
1129
1007
 
1175
1053
        if (guest) {
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 */
1183
1060
                if (logging)
1190
1067
                        reply(230, "User %s logged in.", pw->pw_name);
1191
1068
                }
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 */
1196
1074
                if (logging)
1226
1104
                        reply(501, "filename too long");
1227
1105
                        return;
1228
1106
                }
1229
 
                (void) sprintf(line, cmd, name), name = line;
 
1107
                (void) snprintf(line, sizeof(line), cmd, name), name = line;
1230
1108
                fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1231
1109
                st.st_size = -1;
1232
1110
#ifndef NOSTBLKSIZE
1408
1286
        byte_count = 0;
1409
1287
        if (size != (off_t) -1)
1410
1288
                /* cast size to long in case sizeof(off_t) > sizeof(long) */
1411
 
                (void) sprintf (sizebuf, " (%ld bytes)", (long)size);
 
1289
                (void) snprintf (sizebuf, sizeof(sizebuf), " (%ld bytes)",
 
1290
                                 (long)size);
1412
1291
        else
1413
 
                (void) strcpy(sizebuf, "");
 
1292
                sizebuf[0] = '\0';
1414
1293
        if (pdata >= 0) {
1415
1294
                int s, fromlen = sizeof(data_dest);
1416
1295
 
1472
1351
 * XXX callers need to limit total length of output string to
1473
1352
 * FTP_BUFSIZ
1474
1353
 */
1475
 
#ifdef STDARG
1476
1354
void
1477
1355
secure_error(char *fmt, ...)
1478
 
#else
1479
 
/* VARARGS1 */
1480
 
void
1481
 
secure_error(fmt, p1, p2, p3, p4, p5)
1482
 
        char *fmt;
1483
 
#endif
1484
1356
{
1485
1357
        char buf[FTP_BUFSIZ];
1486
 
#ifdef STDARG
1487
1358
        va_list ap;
1488
1359
 
1489
1360
        va_start(ap, fmt);
1490
 
        vsprintf(buf, fmt, ap);
 
1361
        vsnprintf(buf, sizeof(buf), fmt, ap);
1491
1362
        va_end(ap);
1492
 
#else
1493
 
        sprintf(buf, fmt, p1, p2, p3, p4, p5);
1494
 
#endif
1495
1363
        reply(535, "%s", buf);
1496
1364
        syslog(LOG_ERR, "%s", buf);
1497
1365
}
1683
1551
                reply(501, "filename too long");
1684
1552
                return;
1685
1553
        }
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);
1689
1557
        p = str;
1732
1600
 
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) {
1748
1616
        else
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]);
 
1623
        }
1754
1624
        if (type == TYPE_L)
1755
 
#if 1
1756
1625
                strncat(str, " 8", sizeof (str) - strlen(str) - 1);
1757
 
#else
1758
 
/* this is silly. -- eichin@cygnus.com */
1759
 
#if NBBY == 8
1760
 
                sprintf(&str[strlen(str)], " %d", NBBY);
1761
 
#else
1762
 
                sprintf(&str[strlen(str)], " %d", bytesize);    /* need definition! */
1763
 
#endif
1764
 
#endif
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;
1777
1638
printaddr:
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]),
 
1644
                         UC(p[1]));
1783
1645
#undef UC
1784
1646
        } else
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");
1788
1650
}
1819
1681
        va_list ap;
1820
1682
 
1821
1683
        va_start(ap, fmt);
1822
 
        vsprintf(buf, fmt, ap);
 
1684
        vsnprintf(buf, sizeof(buf), fmt, ap);
1823
1685
        va_end(ap);
1824
1686
#else
1825
 
        sprintf(buf, fmt, p0, p1, p2, p3, p4, p5);
 
1687
        snprintf(buf, sizeof(buf), fmt, p0, p1, p2, p3, p4, p5);
1826
1688
#endif
1827
1689
 
1828
1690
        if (auth_type) {
1832
1694
                 */
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,
1843
 
                                                     strlen(in),
1844
 
                                                     schedule, &kdata.session,
1845
 
                                                     &ctrl_addr,
1846
 
                                                     &his_addr);
1847
 
                        else
1848
 
                                length = krb_mk_safe((unsigned char *)in,
1849
 
                                                     (unsigned char *)out,
1850
 
                                                     strlen(in),
1851
 
                                                     &kdata.session,
1852
 
                                                     &ctrl_addr,
1853
 
                                                     &his_addr);
1854
 
                        if (length == -1) {
1855
 
                                syslog(LOG_ERR,
1856
 
                                       "krb_mk_%s failed for KERBEROS_V4",
1857
 
                                       clevel == PROT_P ? "priv" : "safe");
1858
 
                                fputs(in,stdout);
1859
 
                        }
1860
 
                } else
1861
 
#endif /* KRB5_KRB4_COMPAT */
1862
1700
#ifdef GSSAPI
1863
1701
                /* reply (based on level) */
1864
1702
                if (strcmp(auth_type, "GSSAPI") == 0) {
1937
1775
        va_list ap;
1938
1776
 
1939
1777
        va_start(ap, fmt);
1940
 
        vsprintf(buf, fmt, ap);
 
1778
        vsnprintf(buf, sizeof(buf), fmt, ap);
1941
1779
        va_end(ap);
1942
1780
#else
1943
 
        sprintf(buf, fmt, p0, p1, p2, p3, p4, p5);
 
1781
        snprintf(buf, sizeof(buf), fmt, p0, p1, p2, p3, p4, p5);
1944
1782
#endif
1945
1783
        cont_char = '-';
1946
1784
        reply(n, "%s", buf);
2102
1940
                exit(1);
2103
1941
        }
2104
1942
#ifdef SETPROCTITLE
2105
 
        sprintf(proctitle, "%s: connected", rhost_sane);
 
1943
        snprintf(proctitle, sizeof(proctitle), "%s: connected", rhost_sane);
2106
1944
        setproctitle(proctitle);
2107
1945
#endif /* SETPROCTITLE */
2108
1946
 
2129
1967
#ifdef GSSAPI
2130
1968
                krb5_cc_destroy(kcontext, ccache);
2131
1969
#endif
2132
 
#ifdef KRB5_KRB4_COMPAT
2133
 
                dest_tkt();
2134
 
#endif
2135
1970
        }
2136
1971
        /* beware of flushing buffers after a SIGPIPE */
2137
1972
        _exit(status);
2249
2084
        cp = new + strlen(new);
2250
2085
        *cp++ = '.';
2251
2086
        for (count = 1; count < 100; count++) {
2252
 
                (void) sprintf(cp, "%d", count);
 
2087
                (void) snprintf(cp, sizeof(new) - (cp - new), "%d", count);
2253
2088
                if (stat(new, &st) < 0)
2254
2089
                        return(new);
2255
2090
        }
2291
2126
        if (auth_type)
2292
2127
                reply(534, "Authentication type already set to %s", auth_type);
2293
2128
        else
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);
2298
 
        else
2299
 
#endif /* KRB5_KRB4_COMPAT */
2300
2129
#ifdef GSSAPI
2301
2130
        if (strcmp(atype, "GSSAPI") == 0)
2302
2131
                reply(334, "Using authentication type %s; ADAT must follow",
2312
2141
char *adata;
2313
2142
{
2314
2143
        int kerror, length;
2315
 
#ifdef KRB5_KRB4_COMPAT
2316
 
        static char **service=NULL;
2317
 
        char instance[INST_SZ];
2318
 
        KRB4_32 cksum;
2319
 
        char buf[FTP_BUFSIZ];
2320
 
        u_char out_buf[sizeof(buf)];
2321
 
#endif /* KRB5_KRB4_COMPAT */
2322
2144
 
2323
2145
        if (auth_type) {
2324
2146
                reply(503, "Authentication already established");
2328
2150
                reply(503, "Must identify AUTH type before ADAT");
2329
2151
                return(0);
2330
2152
        }
2331
 
#ifdef KRB5_KRB4_COMPAT
2332
 
        if (strcmp(temp_auth_type, "KERBEROS_V4") == 0) {
2333
 
                kerror = radix_encode(adata, out_buf, &length, 1);
2334
 
                if (kerror) {
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));
2339
 
                        return(0);
2340
 
                }
2341
 
                (void) memcpy((char *)ticket.dat, (char *)out_buf, ticket.length = length);
2342
 
                strcpy(instance, "*");
2343
 
 
2344
 
                kerror = 255;
2345
 
                for (service = krb4_services; *service; service++) {
2346
 
                  kerror = krb_rd_req(&ticket, *service, instance,
2347
 
                                      his_addr.sin_addr.s_addr, 
2348
 
                                      &kdata, keyfile);
2349
 
                  /* Success */
2350
 
                  if(!kerror) break;
2351
 
                } 
2352
 
                /* rd_req failed.... */
2353
 
                if(kerror) {
2354
 
                  secure_error("ADAT: Kerberos V4 krb_rd_req: %s",
2355
 
                               krb_get_err_text(kerror));
2356
 
                  return(0);
2357
 
                }
2358
 
 
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");
2366
 
                        return(0);
2367
 
                }
2368
 
                if (length >= (FTP_BUFSIZ - sizeof("ADAT=")) / 4 * 3) {
2369
 
                        secure_error("ADAT: reply too long");
2370
 
                        return(0);
2371
 
                }
2372
 
 
2373
 
                kerror = radix_encode(out_buf, buf, &length, 0);
2374
 
                if (kerror) {
2375
 
                        secure_error("Couldn't encode ADAT reply (%s)",
2376
 
                                     radix_error(kerror));
2377
 
                        return(0);
2378
 
                }
2379
 
                reply(235, "ADAT=%s", buf);
2380
 
                /* Kerberos V4 authentication succeeded */
2381
 
                auth_type = temp_auth_type;
2382
 
                temp_auth_type = NULL;
2383
 
                return(1);
2384
 
        }
2385
 
#endif /* KRB5_KRB4_COMPAT */
2386
2153
#ifdef GSSAPI
2387
2154
        if (strcmp(temp_auth_type, "GSSAPI") == 0) {
2388
2155
                int replied = 0;
2432
2199
                localname[sizeof(localname) - 1] = '\0';
2433
2200
 
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;
2438
2206
                        if (debug)
2620
2388
 * XXX callers need to limit total length of output string to
2621
2389
 * FTP_BUFSIZ
2622
2390
 */
2623
 
#ifdef STDARG
2624
2391
static int
2625
2392
secure_fprintf(FILE *stream, char *fmt, ...)
2626
 
#else
2627
 
static int
2628
 
secure_fprintf(stream, fmt, p1, p2, p3, p4, p5)
2629
 
FILE *stream;
2630
 
char *fmt;
 
2393
#if !defined(__cplusplus) && (__GNUC__ > 2)
 
2394
    __attribute__((__format__(__printf__, 2, 3)))
2631
2395
#endif
 
2396
    ;
 
2397
 
 
2398
static int
 
2399
secure_fprintf(FILE *stream, char *fmt, ...)
2632
2400
{
2633
2401
        char s[FTP_BUFSIZ];
2634
2402
        int rval;
2635
 
#ifdef STDARG
2636
2403
        va_list ap;
2637
2404
 
2638
2405
        va_start(ap, fmt);
2639
2406
        if (dlevel == PROT_C) rval = vfprintf(stream, fmt, ap);
2640
2407
        else {
2641
 
                vsprintf(s, fmt, ap);
 
2408
                vsnprintf(s, sizeof(s), fmt, ap);
2642
2409
                rval = secure_write(fileno(stream), s, strlen(s));
2643
2410
        }
2644
2411
        va_end(ap);
2645
2412
 
2646
2413
        return(rval);
2647
 
#else
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)));
2652
 
#endif
2653
2414
}
2654
2415
 
2655
2416
void
2748
2509
                                ret = -2; /* XXX */
2749
2510
                                goto data_err;
2750
2511
                        }
2751
 
                        sprintf(nbuf, "%s/%s", dirname, dir->d_name);
 
2512
                        snprintf(nbuf, sizeof(nbuf), "%s/%s",
 
2513
                                 dirname, dir->d_name);
2752
2514
 
2753
2515
                        /*
2754
2516
                         * We have to do a stat to insure it'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;
2951
 
#endif
2952
2709
 
2953
2710
        /* Set up ccache */
2954
2711
        if (krb5_parse_name(kcontext, name, &me))
2955
2712
                return;
2956
2713
 
2957
 
        sprintf(ccname, "FILE:/tmp/krb5cc_ftpd%ld", (long) getpid());
 
2714
        snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_ftpd%ld",
 
2715
                 (long) getpid());
2958
2716
        if (krb5_cc_resolve(kcontext, ccname, &ccache))
2959
2717
                return;
2960
2718
        if (krb5_cc_initialize(kcontext, ccache, me))
2965
2723
        if (major_status != GSS_S_COMPLETE)
2966
2724
                goto cleanup;
2967
2725
 
2968
 
#ifdef KRB5_KRB4_COMPAT
2969
 
        /* Convert krb5 creds to krb4 */
2970
 
 
2971
 
        if (krb5_build_principal_ext(kcontext, &kpcserver, 
2972
 
                                     krb5_princ_realm(kcontext, me)->length,
2973
 
                                     krb5_princ_realm(kcontext, me)->data,
2974
 
                                     6, "krbtgt",
2975
 
                                     krb5_princ_realm(kcontext, me)->length,
2976
 
                                     krb5_princ_realm(kcontext, me)->data,
2977
 
                                     0))
2978
 
                goto cleanup;
2979
 
 
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))
2986
 
                goto cleanup;
2987
 
        if (krb524_convert_creds_kdc(kcontext, v5creds, &v4creds))
2988
 
                goto cleanup;
2989
 
 
2990
 
        sprintf(ccname, "%s_ftpd%ld", TKT_ROOT, (long) getpid());
2991
 
        krb_set_tkt_string(ccname);
2992
 
 
2993
 
        if (in_tkt(v4creds.pname, v4creds.pinst) != KSUCCESS)
2994
 
                goto cleanup;
2995
 
 
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))
3000
 
                goto cleanup_v4;
3001
 
#endif /* KRB5_KRB4_COMPAT */
3002
2726
        have_creds = 1;
3003
2727
        return;
3004
2728
 
3005
 
#ifdef KRB5_KRB4_COMPAT
3006
 
cleanup_v4:
3007
 
        dest_tkt();
3008
 
#endif
3009
2729
cleanup:
3010
2730
        krb5_cc_destroy(kcontext, ccache);
3011
2731
}