• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/heimdal/kdc/
1/*
2 * Copyright (c) 1997-2005 Kungliga Tekniska H��gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *
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.
17 *
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.
21 *
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.
33 */
34
35#include "kdc_locl.h"
36
37/*
38 *
39 */
40
41void
42krb5_kdc_update_time(struct timeval *tv)
43{
44    if (tv == NULL)
45	gettimeofday(&_kdc_now, NULL);
46    else
47	_kdc_now = *tv;
48}
49
50static krb5_error_code
51kdc_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)
59{
60    krb5_error_code ret;
61    KDC_REQ req;
62    size_t len;
63
64    ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &req, &len);
65    if (ret)
66	return ret;
67
68    *claim = 1;
69
70    ret = _kdc_as_rep(context, config, &req, req_buffer,
71		      reply, from, addr, datagram_reply);
72    free_AS_REQ(&req);
73    return ret;
74}
75
76
77static krb5_error_code
78kdc_tgs_req(krb5_context context,
79	    krb5_kdc_configuration *config,
80	    krb5_data *req_buffer,
81	    krb5_data *reply,
82	    const char *from,
83	    struct sockaddr *addr,
84	    int datagram_reply,
85	    int *claim)
86{
87    krb5_error_code ret;
88    KDC_REQ req;
89    size_t len;
90
91    ret = decode_TGS_REQ(req_buffer->data, req_buffer->length, &req, &len);
92    if (ret)
93	return ret;
94
95    *claim = 1;
96
97    ret = _kdc_tgs_rep(context, config, &req, reply,
98		       from, addr, datagram_reply);
99    free_TGS_REQ(&req);
100    return ret;
101}
102
103#ifdef DIGEST
104
105static krb5_error_code
106kdc_digest(krb5_context context,
107	   krb5_kdc_configuration *config,
108	   krb5_data *req_buffer,
109	   krb5_data *reply,
110	   const char *from,
111	   struct sockaddr *addr,
112	   int datagram_reply,
113	   int *claim)
114{
115    DigestREQ digestreq;
116    krb5_error_code ret;
117    size_t len;
118
119    ret = decode_DigestREQ(req_buffer->data, req_buffer->length,
120			   &digestreq, &len);
121    if (ret)
122	return ret;
123
124    *claim = 1;
125
126    ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr);
127    free_DigestREQ(&digestreq);
128    return ret;
129}
130
131#endif
132
133#ifdef KX509
134
135static krb5_error_code
136kdc_kx509(krb5_context context,
137	  krb5_kdc_configuration *config,
138	  krb5_data *req_buffer,
139	  krb5_data *reply,
140	  const char *from,
141	  struct sockaddr *addr,
142	  int datagram_reply,
143	  int *claim)
144{
145    Kx509Request kx509req;
146    krb5_error_code ret;
147    size_t len;
148
149    ret = _kdc_try_kx509_request(req_buffer->data, req_buffer->length,
150				 &kx509req, &len);
151    if (ret)
152	return ret;
153
154    *claim = 1;
155
156    ret = _kdc_do_kx509(context, config, &kx509req, reply, from, addr);
157    free_Kx509Request(&kx509req);
158    return ret;
159}
160
161#endif
162
163
164#ifdef KRB4
165
166static krb5_error_code
167kdc_524(krb5_context context,
168	krb5_kdc_configuration *config,
169	krb5_data *req_buffer,
170	krb5_data *reply,
171	const char *from,
172	struct sockaddr *addr,
173	int datagram_reply,
174	int *claim)
175{
176    krb5_error_code ret;
177    Ticket ticket;
178    size_t len;
179
180    ret = decode_Ticket(req_buffer->data, req_buffer->length, &ticket, &len);
181    if (ret)
182	return ret;
183
184    *claim = 1;
185
186    ret = _kdc_do_524(context, config, &ticket, reply, from, addr);
187    free_Ticket(&ticket);
188    return ret;
189}
190
191static krb5_error_code
192kdc_krb4(krb5_context context,
193	 krb5_kdc_configuration *config,
194	 krb5_data *req_buffer,
195	 krb5_data *reply,
196	 const char *from,
197	 struct sockaddr *addr,
198	 int datagram_reply,
199	 int *claim)
200{
201    if (_kdc_maybe_version4(req_buffer->data, req_buffer->length) == 0)
202	return -1;
203
204    *claim = 1;
205
206    return _kdc_do_version4(context, config,
207			   req_buffer->data, req_buffer->length,
208			   reply, from,
209			   (struct sockaddr_in*)addr);
210}
211
212static krb5_error_code
213kdc_kaserver(krb5_context context,
214	     krb5_kdc_configuration *config,
215	     krb5_data *req_buffer,
216	     krb5_data *reply,
217	     const char *from,
218	     struct sockaddr *addr,
219	     int datagram_reply,
220	     int *claim)
221{
222    if (config->enable_kaserver == 0)
223	return -1;
224
225    *claim = 1;
226
227    return _kdc_do_kaserver(context, config,
228			    req_buffer->data, req_buffer->length,
229			    reply, from,
230			    (struct sockaddr_in*)addr);
231}
232
233#endif /* KRB4 */
234
235
236static struct krb5_kdc_service services[] =  {
237    { KS_KRB5,		kdc_as_req },
238    { KS_KRB5,		kdc_tgs_req },
239#ifdef DIGEST
240    { 0,		kdc_digest },
241#endif
242#ifdef KX509
243    { 0,		kdc_kx509 },
244#endif
245#ifdef KRB4
246    { 0,		kdc_524 },
247    { KS_NO_LENGTH,	kdc_krb4 },
248    { 0,		kdc_kaserver },
249#endif
250    { 0, NULL }
251};
252
253/*
254 * handle the request in `buf, len', from `addr' (or `from' as a string),
255 * sending a reply in `reply'.
256 */
257
258int
259krb5_kdc_process_request(krb5_context context,
260			 krb5_kdc_configuration *config,
261			 unsigned char *buf,
262			 size_t len,
263			 krb5_data *reply,
264			 krb5_boolean *prependlength,
265			 const char *from,
266			 struct sockaddr *addr,
267			 int datagram_reply)
268{
269    krb5_error_code ret;
270    unsigned int i;
271    krb5_data req_buffer;
272    int claim = 0;
273
274    req_buffer.data = buf;
275    req_buffer.length = len;
276
277    for (i = 0; services[i].process != NULL; i++) {
278	ret = (*services[i].process)(context, config, &req_buffer,
279				     reply, from, addr, datagram_reply,
280				     &claim);
281	if (claim) {
282	    if (services[i].flags & KS_NO_LENGTH)
283		*prependlength = 0;
284	    return ret;
285	}
286    }
287
288    return -1;
289}
290
291/*
292 * handle the request in `buf, len', from `addr' (or `from' as a string),
293 * sending a reply in `reply'.
294 *
295 * This only processes krb5 requests
296 */
297
298int
299krb5_kdc_process_krb5_request(krb5_context context,
300			      krb5_kdc_configuration *config,
301			      unsigned char *buf,
302			      size_t len,
303			      krb5_data *reply,
304			      const char *from,
305			      struct sockaddr *addr,
306			      int datagram_reply)
307{
308    krb5_error_code ret;
309    unsigned int i;
310    krb5_data req_buffer;
311    int claim = 0;
312
313    req_buffer.data = buf;
314    req_buffer.length = len;
315
316    for (i = 0; services[i].process != NULL; i++) {
317	if ((services[i].flags & KS_KRB5) == 0)
318	    continue;
319	ret = (*services[i].process)(context, config, &req_buffer,
320				     reply, from, addr, datagram_reply,
321				     &claim);
322	if (claim)
323	    return ret;
324    }
325
326    return -1;
327}
328
329/*
330 *
331 */
332
333int
334krb5_kdc_save_request(krb5_context context,
335		      const char *fn,
336		      const unsigned char *buf,
337		      size_t len,
338		      const krb5_data *reply,
339		      const struct sockaddr *sa)
340{
341    krb5_storage *sp;
342    krb5_address a;
343    int fd, ret;
344    uint32_t t;
345    krb5_data d;
346
347    memset(&a, 0, sizeof(a));
348
349    d.data = rk_UNCONST(buf);
350    d.length = len;
351    t = _kdc_now.tv_sec;
352
353    fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600);
354    if (fd < 0) {
355	int saved_errno = errno;
356	krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn);
357	return saved_errno;
358    }
359
360    sp = krb5_storage_from_fd(fd);
361    close(fd);
362    if (sp == NULL) {
363	krb5_set_error_message(context, ENOMEM, "Storage failed to open fd");
364	return ENOMEM;
365    }
366
367    ret = krb5_sockaddr2address(context, sa, &a);
368    if (ret)
369	goto out;
370
371    krb5_store_uint32(sp, 1);
372    krb5_store_uint32(sp, t);
373    krb5_store_address(sp, a);
374    krb5_store_data(sp, d);
375    {
376	Der_class cl;
377	Der_type ty;
378	unsigned int tag;
379	ret = der_get_tag (reply->data, reply->length,
380			   &cl, &ty, &tag, NULL);
381	if (ret) {
382	    krb5_store_uint32(sp, 0xffffffff);
383	    krb5_store_uint32(sp, 0xffffffff);
384	} else {
385	    krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0));
386	    krb5_store_uint32(sp, tag);
387	}
388    }
389
390    krb5_free_address(context, &a);
391out:
392    krb5_storage_free(sp);
393
394    return 0;
395}
396