fill in more bits
[heimdal.git] / kdc / process.c
blobc6535bb222b7b56955ee88d88ffa97a028b0eb26
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;
203 req_buffer.data = buf;
204 req_buffer.length = len;
206 for (i = 0; services[i].process != NULL; i++) {
207 ret = (*services[i].process)(context, config, &req_buffer,
208 reply, from, addr, datagram_reply,
209 &claim);
210 if (claim) {
211 if (services[i].flags & KS_NO_LENGTH)
212 *prependlength = 0;
213 return ret;
217 return -1;
221 * handle the request in `buf, len', from `addr' (or `from' as a string),
222 * sending a reply in `reply'.
224 * This only processes krb5 requests
228 krb5_kdc_process_krb5_request(krb5_context context,
229 krb5_kdc_configuration *config,
230 unsigned char *buf,
231 size_t len,
232 krb5_data *reply,
233 const char *from,
234 struct sockaddr *addr,
235 int datagram_reply)
237 krb5_error_code ret;
238 unsigned int i;
239 krb5_data req_buffer;
240 int claim = 0;
242 req_buffer.data = buf;
243 req_buffer.length = len;
245 for (i = 0; services[i].process != NULL; i++) {
246 if ((services[i].flags & KS_KRB5) == 0)
247 continue;
248 ret = (*services[i].process)(context, config, &req_buffer,
249 reply, from, addr, datagram_reply,
250 &claim);
251 if (claim)
252 return ret;
255 return -1;
263 krb5_kdc_save_request(krb5_context context,
264 const char *fn,
265 const unsigned char *buf,
266 size_t len,
267 const krb5_data *reply,
268 const struct sockaddr *sa)
270 krb5_storage *sp;
271 krb5_address a;
272 int fd, ret;
273 uint32_t t;
274 krb5_data d;
276 memset(&a, 0, sizeof(a));
278 d.data = rk_UNCONST(buf);
279 d.length = len;
280 t = _kdc_now.tv_sec;
282 fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600);
283 if (fd < 0) {
284 int saved_errno = errno;
285 krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn);
286 return saved_errno;
289 sp = krb5_storage_from_fd(fd);
290 close(fd);
291 if (sp == NULL) {
292 krb5_set_error_message(context, ENOMEM, "Storage failed to open fd");
293 return ENOMEM;
296 ret = krb5_sockaddr2address(context, sa, &a);
297 if (ret)
298 goto out;
300 krb5_store_uint32(sp, 1);
301 krb5_store_uint32(sp, t);
302 krb5_store_address(sp, a);
303 krb5_store_data(sp, d);
305 Der_class cl;
306 Der_type ty;
307 unsigned int tag;
308 ret = der_get_tag (reply->data, reply->length,
309 &cl, &ty, &tag, NULL);
310 if (ret) {
311 krb5_store_uint32(sp, 0xffffffff);
312 krb5_store_uint32(sp, 0xffffffff);
313 } else {
314 krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
315 krb5_store_uint32(sp, tag);
319 krb5_free_address(context, &a);
320 out:
321 krb5_storage_free(sp);
323 return 0;