2 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include "ftpd_locl.h"
44 #define LOCAL_ADDR ctrl_addr
45 #define REMOTE_ADDR his_addr
47 #define LOCAL_ADDR myctladdr
48 #define REMOTE_ADDR hisctladdr
51 extern struct sockaddr
*LOCAL_ADDR
, *REMOTE_ADDR
;
55 des_key_schedule schedule
;
57 char instance
[INST_SZ
];
62 krb4_check_prot(void *app_data
, int level
)
64 if(level
== prot_confidential
)
70 krb4_decode(void *app_data
, void *buf
, int len
, int level
)
74 struct krb4_data
*d
= app_data
;
76 if(level
== prot_safe
)
77 e
= krb_rd_safe(buf
, len
, &d
->key
,
78 (struct sockaddr_in
*)REMOTE_ADDR
,
79 (struct sockaddr_in
*)LOCAL_ADDR
, &m
);
81 e
= krb_rd_priv(buf
, len
, d
->schedule
, &d
->key
,
82 (struct sockaddr_in
*)REMOTE_ADDR
,
83 (struct sockaddr_in
*)LOCAL_ADDR
, &m
);
85 syslog(LOG_ERR
, "krb4_decode: %s", krb_get_err_text(e
));
88 memmove(buf
, m
.app_data
, m
.app_length
);
93 krb4_overhead(void *app_data
, int level
, int len
)
99 krb4_encode(void *app_data
, void *from
, int length
, int level
, void **to
)
101 struct krb4_data
*d
= app_data
;
102 *to
= malloc(length
+ 31);
103 if(level
== prot_safe
)
104 return krb_mk_safe(from
, *to
, length
, &d
->key
,
105 (struct sockaddr_in
*)LOCAL_ADDR
,
106 (struct sockaddr_in
*)REMOTE_ADDR
);
107 else if(level
== prot_private
)
108 return krb_mk_priv(from
, *to
, length
, d
->schedule
, &d
->key
,
109 (struct sockaddr_in
*)LOCAL_ADDR
,
110 (struct sockaddr_in
*)REMOTE_ADDR
);
118 krb4_adat(void *app_data
, void *buf
, size_t len
)
125 char msg
[35]; /* size of encrypted block */
127 struct krb4_data
*d
= app_data
;
129 struct sockaddr_in
*his_addr_sin
= (struct sockaddr_in
*)his_addr
;
131 memcpy(tkt
.dat
, buf
, len
);
134 k_getsockinst(0, inst
, sizeof(inst
));
135 kerror
= krb_rd_req(&tkt
, "ftp", inst
,
136 his_addr_sin
->sin_addr
.s_addr
, &auth_dat
, "");
137 if(kerror
== RD_AP_UNDEC
){
138 k_getsockinst(0, inst
, sizeof(inst
));
139 kerror
= krb_rd_req(&tkt
, "rcmd", inst
,
140 his_addr_sin
->sin_addr
.s_addr
, &auth_dat
, "");
144 reply(535, "Error reading request: %s.", krb_get_err_text(kerror
));
148 memcpy(d
->key
, auth_dat
.session
, sizeof(d
->key
));
149 des_set_key(&d
->key
, d
->schedule
);
151 strlcpy(d
->name
, auth_dat
.pname
, sizeof(d
->name
));
152 strlcpy(d
->instance
, auth_dat
.pinst
, sizeof(d
->instance
));
153 strlcpy(d
->realm
, auth_dat
.prealm
, sizeof(d
->instance
));
155 cs
= auth_dat
.checksum
+ 1;
157 unsigned char tmp
[4];
158 KRB_PUT_INT(cs
, tmp
, 4, sizeof(tmp
));
159 tmp_len
= krb_mk_safe(tmp
, msg
, 4, &d
->key
,
160 (struct sockaddr_in
*)LOCAL_ADDR
,
161 (struct sockaddr_in
*)REMOTE_ADDR
);
164 reply(535, "Error creating reply: %s.", strerror(errno
));
168 if(base64_encode(msg
, len
, &p
) < 0) {
169 reply(535, "Out of memory base64-encoding.");
172 reply(235, "ADAT=%s", p
);
179 krb4_userok(void *app_data
, char *user
)
181 struct krb4_data
*d
= app_data
;
182 return krb_kuserok(d
->name
, d
->instance
, d
->realm
, user
);
185 struct sec_server_mech krb4_server_mech
= {
187 sizeof(struct krb4_data
),
202 #else /* FTP_SERVER */
205 krb4_init(void *app_data
)
207 return !use_kerberos
;
211 mk_auth(struct krb4_data
*d
, KTEXT adat
,
212 char *service
, char *host
, int checksum
)
216 char sname
[SNAME_SZ
], inst
[INST_SZ
], realm
[REALM_SZ
];
218 strlcpy(sname
, service
, sizeof(sname
));
219 strlcpy(inst
, krb_get_phost(host
), sizeof(inst
));
220 strlcpy(realm
, krb_realmofhost(host
), sizeof(realm
));
221 ret
= krb_mk_req(adat
, sname
, inst
, realm
, checksum
);
224 strlcpy(sname
, service
, sizeof(sname
));
225 strlcpy(inst
, krb_get_phost(host
), sizeof(inst
));
226 strlcpy(realm
, krb_realmofhost(host
), sizeof(realm
));
227 ret
= krb_get_cred(sname
, inst
, realm
, &cred
);
228 memmove(&d
->key
, &cred
.session
, sizeof(des_cblock
));
229 des_key_sched(&d
->key
, d
->schedule
);
230 memset(&cred
, 0, sizeof(cred
));
235 krb4_auth(void *app_data
, char *host
)
244 struct krb4_data
*d
= app_data
;
245 struct sockaddr_in
*localaddr
= (struct sockaddr_in
*)LOCAL_ADDR
;
246 struct sockaddr_in
*remoteaddr
= (struct sockaddr_in
*)REMOTE_ADDR
;
249 ret
= mk_auth(d
, &adat
, "ftp", host
, checksum
);
250 if(ret
== KDC_PR_UNKNOWN
)
251 ret
= mk_auth(d
, &adat
, "rcmd", host
, checksum
);
253 printf("%s\n", krb_get_err_text(ret
));
254 return AUTH_CONTINUE
;
257 #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
258 if (krb_get_config_bool("nat_in_use")) {
259 struct in_addr natAddr
;
261 if (krb_get_our_ip_for_realm(krb_realmofhost(host
),
262 &natAddr
) != KSUCCESS
263 && krb_get_our_ip_for_realm(NULL
, &natAddr
) != KSUCCESS
)
264 printf("Can't get address for realm %s\n",
265 krb_realmofhost(host
));
267 if (natAddr
.s_addr
!= localaddr
->sin_addr
.s_addr
) {
268 printf("Using NAT IP address (%s) for kerberos 4\n",
270 localaddr
->sin_addr
= natAddr
;
273 * This not the best place to do this, but it
274 * is here we know that (probably) NAT is in
279 printf("Setting: Passive mode on.\n");
285 printf("Local address is %s\n", inet_ntoa(localaddr
->sin_addr
));
286 printf("Remote address is %s\n", inet_ntoa(remoteaddr
->sin_addr
));
288 if(base64_encode(adat
.dat
, adat
.length
, &p
) < 0) {
289 printf("Out of memory base64-encoding.\n");
290 return AUTH_CONTINUE
;
292 ret
= command("ADAT %s", p
);
296 printf("Server didn't accept auth data.\n");
300 p
= strstr(reply_string
, "ADAT=");
302 printf("Remote host didn't send adat reply.\n");
306 len
= base64_decode(p
, adat
.dat
);
308 printf("Failed to decode base64 from server.\n");
312 ret
= krb_rd_safe(adat
.dat
, adat
.length
, &d
->key
,
313 (struct sockaddr_in
*)hisctladdr
,
314 (struct sockaddr_in
*)myctladdr
, &msg_data
);
316 printf("Error reading reply from server: %s.\n",
317 krb_get_err_text(ret
));
320 krb_get_int(msg_data
.app_data
, &cs
, 4, 0);
321 if(cs
- checksum
!= 1){
322 printf("Bad checksum returned from server.\n");
328 struct sec_client_mech krb4_client_mech
= {
330 sizeof(struct krb4_data
),
331 krb4_init
, /* init */
340 #endif /* FTP_SERVER */