No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / appl / ftp / ftpd / krb4.c
blob2561ca72661aabe56c2fcf0832621faf83a903ee
1 /*
2 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
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
31 * SUCH DAMAGE.
34 #ifdef FTP_SERVER
35 #include "ftpd_locl.h"
36 #else
37 #include "ftp_locl.h"
38 #endif
39 #include <krb.h>
41 __RCSID("$Heimdal: krb4.c 17450 2006-05-05 11:11:43Z lha $"
42 "$NetBSD$");
44 #ifdef FTP_SERVER
45 #define LOCAL_ADDR ctrl_addr
46 #define REMOTE_ADDR his_addr
47 #else
48 #define LOCAL_ADDR myctladdr
49 #define REMOTE_ADDR hisctladdr
50 #endif
52 extern struct sockaddr *LOCAL_ADDR, *REMOTE_ADDR;
54 struct krb4_data {
55 des_cblock key;
56 des_key_schedule schedule;
57 char name[ANAME_SZ];
58 char instance[INST_SZ];
59 char realm[REALM_SZ];
62 static int
63 krb4_check_prot(void *app_data, int level)
65 if(level == prot_confidential)
66 return -1;
67 return 0;
70 static int
71 krb4_decode(void *app_data, void *buf, int len, int level)
73 MSG_DAT m;
74 int e;
75 struct krb4_data *d = app_data;
77 if(level == prot_safe)
78 e = krb_rd_safe(buf, len, &d->key,
79 (struct sockaddr_in *)REMOTE_ADDR,
80 (struct sockaddr_in *)LOCAL_ADDR, &m);
81 else
82 e = krb_rd_priv(buf, len, d->schedule, &d->key,
83 (struct sockaddr_in *)REMOTE_ADDR,
84 (struct sockaddr_in *)LOCAL_ADDR, &m);
85 if(e){
86 syslog(LOG_ERR, "krb4_decode: %s", krb_get_err_text(e));
87 return -1;
89 memmove(buf, m.app_data, m.app_length);
90 return m.app_length;
93 static int
94 krb4_overhead(void *app_data, int level, int len)
96 return 31;
99 static int
100 krb4_encode(void *app_data, void *from, int length, int level, void **to)
102 struct krb4_data *d = app_data;
103 *to = malloc(length + 31);
104 if(level == prot_safe)
105 return krb_mk_safe(from, *to, length, &d->key,
106 (struct sockaddr_in *)LOCAL_ADDR,
107 (struct sockaddr_in *)REMOTE_ADDR);
108 else if(level == prot_private)
109 return krb_mk_priv(from, *to, length, d->schedule, &d->key,
110 (struct sockaddr_in *)LOCAL_ADDR,
111 (struct sockaddr_in *)REMOTE_ADDR);
112 else
113 return -1;
116 #ifdef FTP_SERVER
118 static int
119 krb4_adat(void *app_data, void *buf, size_t len)
121 KTEXT_ST tkt;
122 AUTH_DAT auth_dat;
123 char *p;
124 int kerror;
125 uint32_t cs;
126 char msg[35]; /* size of encrypted block */
127 int tmp_len;
128 struct krb4_data *d = app_data;
129 char inst[INST_SZ];
130 struct sockaddr_in *his_addr_sin = (struct sockaddr_in *)his_addr;
132 memcpy(tkt.dat, buf, len);
133 tkt.length = len;
135 k_getsockinst(0, inst, sizeof(inst));
136 kerror = krb_rd_req(&tkt, "ftp", inst,
137 his_addr_sin->sin_addr.s_addr, &auth_dat, "");
138 if(kerror == RD_AP_UNDEC){
139 k_getsockinst(0, inst, sizeof(inst));
140 kerror = krb_rd_req(&tkt, "rcmd", inst,
141 his_addr_sin->sin_addr.s_addr, &auth_dat, "");
144 if(kerror){
145 reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
146 return -1;
149 memcpy(d->key, auth_dat.session, sizeof(d->key));
150 des_set_key(&d->key, d->schedule);
152 strlcpy(d->name, auth_dat.pname, sizeof(d->name));
153 strlcpy(d->instance, auth_dat.pinst, sizeof(d->instance));
154 strlcpy(d->realm, auth_dat.prealm, sizeof(d->instance));
156 cs = auth_dat.checksum + 1;
158 unsigned char tmp[4];
159 KRB_PUT_INT(cs, tmp, 4, sizeof(tmp));
160 tmp_len = krb_mk_safe(tmp, msg, 4, &d->key,
161 (struct sockaddr_in *)LOCAL_ADDR,
162 (struct sockaddr_in *)REMOTE_ADDR);
164 if(tmp_len < 0){
165 reply(535, "Error creating reply: %s.", strerror(errno));
166 return -1;
168 len = tmp_len;
169 if(base64_encode(msg, len, &p) < 0) {
170 reply(535, "Out of memory base64-encoding.");
171 return -1;
173 reply(235, "ADAT=%s", p);
174 sec_complete = 1;
175 free(p);
176 return 0;
179 static int
180 krb4_userok(void *app_data, char *user)
182 struct krb4_data *d = app_data;
183 return krb_kuserok(d->name, d->instance, d->realm, user);
186 struct sec_server_mech krb4_server_mech = {
187 "KERBEROS_V4",
188 sizeof(struct krb4_data),
189 NULL, /* init */
190 NULL, /* end */
191 krb4_check_prot,
192 krb4_overhead,
193 krb4_encode,
194 krb4_decode,
195 /* */
196 NULL,
197 krb4_adat,
198 NULL, /* pbsz */
199 NULL, /* ccc */
200 krb4_userok
203 #else /* FTP_SERVER */
205 static int
206 krb4_init(void *app_data)
208 return !use_kerberos;
211 static int
212 mk_auth(struct krb4_data *d, KTEXT adat,
213 char *service, char *host, int checksum)
215 int ret;
216 CREDENTIALS cred;
217 char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
219 strlcpy(sname, service, sizeof(sname));
220 strlcpy(inst, krb_get_phost(host), sizeof(inst));
221 strlcpy(realm, krb_realmofhost(host), sizeof(realm));
222 ret = krb_mk_req(adat, sname, inst, realm, checksum);
223 if(ret)
224 return ret;
225 strlcpy(sname, service, sizeof(sname));
226 strlcpy(inst, krb_get_phost(host), sizeof(inst));
227 strlcpy(realm, krb_realmofhost(host), sizeof(realm));
228 ret = krb_get_cred(sname, inst, realm, &cred);
229 memmove(&d->key, &cred.session, sizeof(des_cblock));
230 des_key_sched(&d->key, d->schedule);
231 memset(&cred, 0, sizeof(cred));
232 return ret;
235 static int
236 krb4_auth(void *app_data, char *host)
238 int ret;
239 char *p;
240 int len;
241 KTEXT_ST adat;
242 MSG_DAT msg_data;
243 int checksum;
244 uint32_t cs;
245 struct krb4_data *d = app_data;
246 struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
247 struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR;
249 checksum = getpid();
250 ret = mk_auth(d, &adat, "ftp", host, checksum);
251 if(ret == KDC_PR_UNKNOWN)
252 ret = mk_auth(d, &adat, "rcmd", host, checksum);
253 if(ret){
254 printf("%s\n", krb_get_err_text(ret));
255 return AUTH_CONTINUE;
258 #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
259 if (krb_get_config_bool("nat_in_use")) {
260 struct in_addr natAddr;
262 if (krb_get_our_ip_for_realm(krb_realmofhost(host),
263 &natAddr) != KSUCCESS
264 && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
265 printf("Can't get address for realm %s\n",
266 krb_realmofhost(host));
267 else {
268 if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
269 printf("Using NAT IP address (%s) for kerberos 4\n",
270 inet_ntoa(natAddr));
271 localaddr->sin_addr = natAddr;
274 * This not the best place to do this, but it
275 * is here we know that (probably) NAT is in
276 * use!
279 passivemode = 1;
280 printf("Setting: Passive mode on.\n");
284 #endif
286 printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));
287 printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));
289 if(base64_encode(adat.dat, adat.length, &p) < 0) {
290 printf("Out of memory base64-encoding.\n");
291 return AUTH_CONTINUE;
293 ret = command("ADAT %s", p);
294 free(p);
296 if(ret != COMPLETE){
297 printf("Server didn't accept auth data.\n");
298 return AUTH_ERROR;
301 p = strstr(reply_string, "ADAT=");
302 if(!p){
303 printf("Remote host didn't send adat reply.\n");
304 return AUTH_ERROR;
306 p += 5;
307 len = base64_decode(p, adat.dat);
308 if(len < 0){
309 printf("Failed to decode base64 from server.\n");
310 return AUTH_ERROR;
312 adat.length = len;
313 ret = krb_rd_safe(adat.dat, adat.length, &d->key,
314 (struct sockaddr_in *)hisctladdr,
315 (struct sockaddr_in *)myctladdr, &msg_data);
316 if(ret){
317 printf("Error reading reply from server: %s.\n",
318 krb_get_err_text(ret));
319 return AUTH_ERROR;
321 krb_get_int(msg_data.app_data, &cs, 4, 0);
322 if(cs - checksum != 1){
323 printf("Bad checksum returned from server.\n");
324 return AUTH_ERROR;
326 return AUTH_OK;
329 struct sec_client_mech krb4_client_mech = {
330 "KERBEROS_V4",
331 sizeof(struct krb4_data),
332 krb4_init, /* init */
333 krb4_auth,
334 NULL, /* end */
335 krb4_check_prot,
336 krb4_overhead,
337 krb4_encode,
338 krb4_decode
341 #endif /* FTP_SERVER */