Fix KRB-FX-CF2 for enctypes with non-dense keyspaces
[heimdal.git] / kdc / process.c
blob1dd0ea7e8a5952a4e46682c2f44afbcd0e596bd5
1 /*
2 * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the Institute nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 #include "kdc_locl.h"
41 void
42 krb5_kdc_update_time(struct timeval *tv)
44 if (tv == NULL)
45 gettimeofday(&_kdc_now, NULL);
46 else
47 _kdc_now = *tv;
50 static krb5_error_code
51 kdc_as_req(krb5_context context,
52 krb5_kdc_configuration *config,
53 krb5_data *req_buffer,
54 krb5_data *reply,
55 const char *from,
56 struct sockaddr *addr,
57 int datagram_reply,
58 int *claim)
60 struct kdc_request_desc r;
61 krb5_error_code ret;
62 size_t len;
64 memset(&r, 0, sizeof(r));
66 ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &r.req, &len);
67 if (ret)
68 return ret;
70 r.context = context;
71 r.config = config;
72 r.request.data = req_buffer->data;
73 r.request.length = req_buffer->length;
75 *claim = 1;
77 ret = _kdc_as_rep(&r, reply, from, addr, datagram_reply);
78 free_AS_REQ(&r.req);
79 return ret;
83 static krb5_error_code
84 kdc_tgs_req(krb5_context context,
85 krb5_kdc_configuration *config,
86 krb5_data *req_buffer,
87 krb5_data *reply,
88 const char *from,
89 struct sockaddr *addr,
90 int datagram_reply,
91 int *claim)
93 krb5_error_code ret;
94 KDC_REQ req;
95 size_t len;
97 ret = decode_TGS_REQ(req_buffer->data, req_buffer->length, &req, &len);
98 if (ret)
99 return ret;
101 *claim = 1;
103 ret = _kdc_tgs_rep(context, config, &req, reply,
104 from, addr, datagram_reply);
105 free_TGS_REQ(&req);
106 return ret;
109 #ifdef DIGEST
111 static krb5_error_code
112 kdc_digest(krb5_context context,
113 krb5_kdc_configuration *config,
114 krb5_data *req_buffer,
115 krb5_data *reply,
116 const char *from,
117 struct sockaddr *addr,
118 int datagram_reply,
119 int *claim)
121 DigestREQ digestreq;
122 krb5_error_code ret;
123 size_t len;
125 ret = decode_DigestREQ(req_buffer->data, req_buffer->length,
126 &digestreq, &len);
127 if (ret)
128 return ret;
130 *claim = 1;
132 ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr);
133 free_DigestREQ(&digestreq);
134 return ret;
137 #endif
139 #ifdef KX509
141 static krb5_error_code
142 kdc_kx509(krb5_context context,
143 krb5_kdc_configuration *config,
144 krb5_data *req_buffer,
145 krb5_data *reply,
146 const char *from,
147 struct sockaddr *addr,
148 int datagram_reply,
149 int *claim)
151 Kx509Request kx509req;
152 krb5_error_code ret;
153 size_t len;
155 ret = _kdc_try_kx509_request(req_buffer->data, req_buffer->length,
156 &kx509req, &len);
157 if (ret)
158 return ret;
160 *claim = 1;
162 ret = _kdc_do_kx509(context, config, &kx509req, reply, from, addr);
163 free_Kx509Request(&kx509req);
164 return ret;
167 #endif
170 static struct krb5_kdc_service services[] = {
171 { KS_KRB5, kdc_as_req },
172 { KS_KRB5, kdc_tgs_req },
173 #ifdef DIGEST
174 { 0, kdc_digest },
175 #endif
176 #ifdef KX509
177 { 0, kdc_kx509 },
178 #endif
179 { 0, NULL }
183 * handle the request in `buf, len', from `addr' (or `from' as a string),
184 * sending a reply in `reply'.
188 krb5_kdc_process_request(krb5_context context,
189 krb5_kdc_configuration *config,
190 unsigned char *buf,
191 size_t len,
192 krb5_data *reply,
193 krb5_boolean *prependlength,
194 const char *from,
195 struct sockaddr *addr,
196 int datagram_reply)
198 krb5_error_code ret;
199 unsigned int i;
200 krb5_data req_buffer;
201 int claim = 0;
202 heim_auto_release_t pool = heim_auto_release_create();
204 req_buffer.data = buf;
205 req_buffer.length = len;
207 for (i = 0; services[i].process != NULL; i++) {
208 ret = (*services[i].process)(context, config, &req_buffer,
209 reply, from, addr, datagram_reply,
210 &claim);
211 if (claim) {
212 if (services[i].flags & KS_NO_LENGTH)
213 *prependlength = 0;
215 heim_auto_release_drain(pool);
216 return ret;
220 heim_auto_release_drain(pool);
222 return -1;
226 * handle the request in `buf, len', from `addr' (or `from' as a string),
227 * sending a reply in `reply'.
229 * This only processes krb5 requests
233 krb5_kdc_process_krb5_request(krb5_context context,
234 krb5_kdc_configuration *config,
235 unsigned char *buf,
236 size_t len,
237 krb5_data *reply,
238 const char *from,
239 struct sockaddr *addr,
240 int datagram_reply)
242 krb5_error_code ret;
243 unsigned int i;
244 krb5_data req_buffer;
245 int claim = 0;
247 req_buffer.data = buf;
248 req_buffer.length = len;
250 for (i = 0; services[i].process != NULL; i++) {
251 if ((services[i].flags & KS_KRB5) == 0)
252 continue;
253 ret = (*services[i].process)(context, config, &req_buffer,
254 reply, from, addr, datagram_reply,
255 &claim);
256 if (claim)
257 return ret;
260 return -1;
268 krb5_kdc_save_request(krb5_context context,
269 const char *fn,
270 const unsigned char *buf,
271 size_t len,
272 const krb5_data *reply,
273 const struct sockaddr *sa)
275 krb5_storage *sp;
276 krb5_address a;
277 int fd, ret;
278 uint32_t t;
279 krb5_data d;
281 memset(&a, 0, sizeof(a));
283 d.data = rk_UNCONST(buf);
284 d.length = len;
285 t = _kdc_now.tv_sec;
287 fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600);
288 if (fd < 0) {
289 int saved_errno = errno;
290 krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn);
291 return saved_errno;
294 sp = krb5_storage_from_fd(fd);
295 close(fd);
296 if (sp == NULL) {
297 krb5_set_error_message(context, ENOMEM, "Storage failed to open fd");
298 return ENOMEM;
301 ret = krb5_sockaddr2address(context, sa, &a);
302 if (ret)
303 goto out;
305 krb5_store_uint32(sp, 1);
306 krb5_store_uint32(sp, t);
307 krb5_store_address(sp, a);
308 krb5_store_data(sp, d);
310 Der_class cl;
311 Der_type ty;
312 unsigned int tag;
313 ret = der_get_tag (reply->data, reply->length,
314 &cl, &ty, &tag, NULL);
315 if (ret) {
316 krb5_store_uint32(sp, 0xffffffff);
317 krb5_store_uint32(sp, 0xffffffff);
318 } else {
319 krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
320 krb5_store_uint32(sp, tag);
324 krb5_free_address(context, &a);
325 out:
326 krb5_storage_free(sp);
328 return 0;