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