1 /* $NetBSD: process.c,v 1.2 2017/01/28 21:31:44 christos 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 struct kdc_request_desc r; 63 krb5_error_code ret; 64 size_t len; 65 66 memset(&r, 0, sizeof(r)); 67 68 ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &r.req, &len); 69 if (ret) 70 return ret; 71 72 r.context = context; 73 r.config = config; 74 r.request.data = req_buffer->data; 75 r.request.length = req_buffer->length; 76 77 *claim = 1; 78 79 ret = _kdc_as_rep(&r, reply, from, addr, datagram_reply); 80 free_AS_REQ(&r.req); 81 return ret; 82 } 83 84 85 static krb5_error_code 86 kdc_tgs_req(krb5_context context, 87 krb5_kdc_configuration *config, 88 krb5_data *req_buffer, 89 krb5_data *reply, 90 const char *from, 91 struct sockaddr *addr, 92 int datagram_reply, 93 int *claim) 94 { 95 krb5_error_code ret; 96 KDC_REQ req; 97 size_t len; 98 99 ret = decode_TGS_REQ(req_buffer->data, req_buffer->length, &req, &len); 100 if (ret) 101 return ret; 102 103 *claim = 1; 104 105 ret = _kdc_tgs_rep(context, config, &req, reply, 106 from, addr, datagram_reply); 107 free_TGS_REQ(&req); 108 return ret; 109 } 110 111 #ifdef DIGEST 112 113 static krb5_error_code 114 kdc_digest(krb5_context context, 115 krb5_kdc_configuration *config, 116 krb5_data *req_buffer, 117 krb5_data *reply, 118 const char *from, 119 struct sockaddr *addr, 120 int datagram_reply, 121 int *claim) 122 { 123 DigestREQ digestreq; 124 krb5_error_code ret; 125 size_t len; 126 127 ret = decode_DigestREQ(req_buffer->data, req_buffer->length, 128 &digestreq, &len); 129 if (ret) 130 return ret; 131 132 *claim = 1; 133 134 ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr); 135 free_DigestREQ(&digestreq); 136 return ret; 137 } 138 139 #endif 140 141 #ifdef KX509 142 143 static krb5_error_code 144 kdc_kx509(krb5_context context, 145 krb5_kdc_configuration *config, 146 krb5_data *req_buffer, 147 krb5_data *reply, 148 const char *from, 149 struct sockaddr *addr, 150 int datagram_reply, 151 int *claim) 152 { 153 Kx509Request kx509req; 154 krb5_error_code ret; 155 size_t len; 156 157 ret = _kdc_try_kx509_request(req_buffer->data, req_buffer->length, 158 &kx509req, &len); 159 if (ret) 160 return ret; 161 162 *claim = 1; 163 164 ret = _kdc_do_kx509(context, config, &kx509req, reply, from, addr); 165 free_Kx509Request(&kx509req); 166 return ret; 167 } 168 169 #endif 170 171 172 static struct krb5_kdc_service services[] = { 173 { KS_KRB5, kdc_as_req }, 174 { KS_KRB5, kdc_tgs_req }, 175 #ifdef DIGEST 176 { 0, kdc_digest }, 177 #endif 178 #ifdef KX509 179 { 0, kdc_kx509 }, 180 #endif 181 { 0, NULL } 182 }; 183 184 /* 185 * handle the request in `buf, len', from `addr' (or `from' as a string), 186 * sending a reply in `reply'. 187 */ 188 189 int 190 krb5_kdc_process_request(krb5_context context, 191 krb5_kdc_configuration *config, 192 unsigned char *buf, 193 size_t len, 194 krb5_data *reply, 195 krb5_boolean *prependlength, 196 const char *from, 197 struct sockaddr *addr, 198 int datagram_reply) 199 { 200 krb5_error_code ret; 201 unsigned int i; 202 krb5_data req_buffer; 203 int claim = 0; 204 heim_auto_release_t pool = heim_auto_release_create(); 205 206 req_buffer.data = buf; 207 req_buffer.length = len; 208 209 for (i = 0; services[i].process != NULL; i++) { 210 ret = (*services[i].process)(context, config, &req_buffer, 211 reply, from, addr, datagram_reply, 212 &claim); 213 if (claim) { 214 if (services[i].flags & KS_NO_LENGTH) 215 *prependlength = 0; 216 217 heim_release(pool); 218 return ret; 219 } 220 } 221 222 heim_release(pool); 223 224 return -1; 225 } 226 227 /* 228 * handle the request in `buf, len', from `addr' (or `from' as a string), 229 * sending a reply in `reply'. 230 * 231 * This only processes krb5 requests 232 */ 233 234 int 235 krb5_kdc_process_krb5_request(krb5_context context, 236 krb5_kdc_configuration *config, 237 unsigned char *buf, 238 size_t len, 239 krb5_data *reply, 240 const char *from, 241 struct sockaddr *addr, 242 int datagram_reply) 243 { 244 krb5_error_code ret; 245 unsigned int i; 246 krb5_data req_buffer; 247 int claim = 0; 248 249 req_buffer.data = buf; 250 req_buffer.length = len; 251 252 for (i = 0; services[i].process != NULL; i++) { 253 if ((services[i].flags & KS_KRB5) == 0) 254 continue; 255 ret = (*services[i].process)(context, config, &req_buffer, 256 reply, from, addr, datagram_reply, 257 &claim); 258 if (claim) 259 return ret; 260 } 261 262 return -1; 263 } 264 265 /* 266 * 267 */ 268 269 int 270 krb5_kdc_save_request(krb5_context context, 271 const char *fn, 272 const unsigned char *buf, 273 size_t len, 274 const krb5_data *reply, 275 const struct sockaddr *sa) 276 { 277 krb5_storage *sp; 278 krb5_address a; 279 int fd, ret; 280 uint32_t t; 281 krb5_data d; 282 283 memset(&a, 0, sizeof(a)); 284 285 d.data = rk_UNCONST(buf); 286 d.length = len; 287 t = _kdc_now.tv_sec; 288 289 fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600); 290 if (fd < 0) { 291 int saved_errno = errno; 292 krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn); 293 return saved_errno; 294 } 295 296 sp = krb5_storage_from_fd(fd); 297 close(fd); 298 if (sp == NULL) { 299 krb5_set_error_message(context, ENOMEM, "Storage failed to open fd"); 300 return ENOMEM; 301 } 302 303 ret = krb5_sockaddr2address(context, sa, &a); 304 if (ret) 305 goto out; 306 307 krb5_store_uint32(sp, 1); 308 krb5_store_uint32(sp, t); 309 krb5_store_address(sp, a); 310 krb5_store_data(sp, d); 311 { 312 Der_class cl; 313 Der_type ty; 314 unsigned int tag; 315 ret = der_get_tag (reply->data, reply->length, 316 &cl, &ty, &tag, NULL); 317 if (ret) { 318 krb5_store_uint32(sp, 0xffffffff); 319 krb5_store_uint32(sp, 0xffffffff); 320 } else { 321 krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0)); 322 krb5_store_uint32(sp, tag); 323 } 324 } 325 326 krb5_free_address(context, &a); 327 out: 328 krb5_storage_free(sp); 329 330 return 0; 331 } 332