1 /* $NetBSD: process.c,v 1.1.1.1 2011/04/13 18:14:37 elric 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 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 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 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 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 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 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 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 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