1178825Sdfr/* 2233294Sstas * Copyright (c) 1997-2005 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4178825Sdfr * 5233294Sstas * All rights reserved. 6178825Sdfr * 7233294Sstas * Redistribution and use in source and binary forms, with or without 8233294Sstas * modification, are permitted provided that the following conditions 9233294Sstas * are met: 10178825Sdfr * 11233294Sstas * 1. Redistributions of source code must retain the above copyright 12233294Sstas * notice, this list of conditions and the following disclaimer. 13178825Sdfr * 14233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 15233294Sstas * notice, this list of conditions and the following disclaimer in the 16233294Sstas * documentation and/or other materials provided with the distribution. 17178825Sdfr * 18233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 19233294Sstas * may be used to endorse or promote products derived from this software 20233294Sstas * without specific prior written permission. 21178825Sdfr * 22233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 23233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 26233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32233294Sstas * SUCH DAMAGE. 33178825Sdfr */ 34178825Sdfr 35178825Sdfr#include "kdc_locl.h" 36178825Sdfr 37178825Sdfr/* 38178825Sdfr * 39178825Sdfr */ 40178825Sdfr 41178825Sdfrvoid 42178825Sdfrkrb5_kdc_update_time(struct timeval *tv) 43178825Sdfr{ 44178825Sdfr if (tv == NULL) 45178825Sdfr gettimeofday(&_kdc_now, NULL); 46178825Sdfr else 47178825Sdfr _kdc_now = *tv; 48178825Sdfr} 49178825Sdfr 50233294Sstasstatic krb5_error_code 51233294Sstaskdc_as_req(krb5_context context, 52233294Sstas krb5_kdc_configuration *config, 53233294Sstas krb5_data *req_buffer, 54233294Sstas krb5_data *reply, 55233294Sstas const char *from, 56233294Sstas struct sockaddr *addr, 57233294Sstas int datagram_reply, 58233294Sstas int *claim) 59233294Sstas{ 60233294Sstas krb5_error_code ret; 61233294Sstas KDC_REQ req; 62233294Sstas size_t len; 63233294Sstas 64233294Sstas ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &req, &len); 65233294Sstas if (ret) 66233294Sstas return ret; 67233294Sstas 68233294Sstas *claim = 1; 69233294Sstas 70233294Sstas ret = _kdc_as_rep(context, config, &req, req_buffer, 71233294Sstas reply, from, addr, datagram_reply); 72233294Sstas free_AS_REQ(&req); 73233294Sstas return ret; 74233294Sstas} 75233294Sstas 76233294Sstas 77233294Sstasstatic krb5_error_code 78233294Sstaskdc_tgs_req(krb5_context context, 79233294Sstas krb5_kdc_configuration *config, 80233294Sstas krb5_data *req_buffer, 81233294Sstas krb5_data *reply, 82233294Sstas const char *from, 83233294Sstas struct sockaddr *addr, 84233294Sstas int datagram_reply, 85233294Sstas int *claim) 86233294Sstas{ 87233294Sstas krb5_error_code ret; 88233294Sstas KDC_REQ req; 89233294Sstas size_t len; 90233294Sstas 91233294Sstas ret = decode_TGS_REQ(req_buffer->data, req_buffer->length, &req, &len); 92233294Sstas if (ret) 93233294Sstas return ret; 94233294Sstas 95233294Sstas *claim = 1; 96233294Sstas 97233294Sstas ret = _kdc_tgs_rep(context, config, &req, reply, 98233294Sstas from, addr, datagram_reply); 99233294Sstas free_TGS_REQ(&req); 100233294Sstas return ret; 101233294Sstas} 102233294Sstas 103233294Sstas#ifdef DIGEST 104233294Sstas 105233294Sstasstatic krb5_error_code 106233294Sstaskdc_digest(krb5_context context, 107233294Sstas krb5_kdc_configuration *config, 108233294Sstas krb5_data *req_buffer, 109233294Sstas krb5_data *reply, 110233294Sstas const char *from, 111233294Sstas struct sockaddr *addr, 112233294Sstas int datagram_reply, 113233294Sstas int *claim) 114233294Sstas{ 115233294Sstas DigestREQ digestreq; 116233294Sstas krb5_error_code ret; 117233294Sstas size_t len; 118233294Sstas 119233294Sstas ret = decode_DigestREQ(req_buffer->data, req_buffer->length, 120233294Sstas &digestreq, &len); 121233294Sstas if (ret) 122233294Sstas return ret; 123233294Sstas 124233294Sstas *claim = 1; 125233294Sstas 126233294Sstas ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr); 127233294Sstas free_DigestREQ(&digestreq); 128233294Sstas return ret; 129233294Sstas} 130233294Sstas 131233294Sstas#endif 132233294Sstas 133233294Sstas#ifdef KX509 134233294Sstas 135233294Sstasstatic krb5_error_code 136233294Sstaskdc_kx509(krb5_context context, 137233294Sstas krb5_kdc_configuration *config, 138233294Sstas krb5_data *req_buffer, 139233294Sstas krb5_data *reply, 140233294Sstas const char *from, 141233294Sstas struct sockaddr *addr, 142233294Sstas int datagram_reply, 143233294Sstas int *claim) 144233294Sstas{ 145233294Sstas Kx509Request kx509req; 146233294Sstas krb5_error_code ret; 147233294Sstas size_t len; 148233294Sstas 149233294Sstas ret = _kdc_try_kx509_request(req_buffer->data, req_buffer->length, 150233294Sstas &kx509req, &len); 151233294Sstas if (ret) 152233294Sstas return ret; 153233294Sstas 154233294Sstas *claim = 1; 155233294Sstas 156233294Sstas ret = _kdc_do_kx509(context, config, &kx509req, reply, from, addr); 157233294Sstas free_Kx509Request(&kx509req); 158233294Sstas return ret; 159233294Sstas} 160233294Sstas 161233294Sstas#endif 162233294Sstas 163233294Sstas 164233294Sstasstatic struct krb5_kdc_service services[] = { 165233294Sstas { KS_KRB5, kdc_as_req }, 166233294Sstas { KS_KRB5, kdc_tgs_req }, 167233294Sstas#ifdef DIGEST 168233294Sstas { 0, kdc_digest }, 169233294Sstas#endif 170233294Sstas#ifdef KX509 171233294Sstas { 0, kdc_kx509 }, 172233294Sstas#endif 173233294Sstas { 0, NULL } 174233294Sstas}; 175233294Sstas 176178825Sdfr/* 177178825Sdfr * handle the request in `buf, len', from `addr' (or `from' as a string), 178178825Sdfr * sending a reply in `reply'. 179178825Sdfr */ 180178825Sdfr 181178825Sdfrint 182233294Sstaskrb5_kdc_process_request(krb5_context context, 183178825Sdfr krb5_kdc_configuration *config, 184233294Sstas unsigned char *buf, 185233294Sstas size_t len, 186178825Sdfr krb5_data *reply, 187178825Sdfr krb5_boolean *prependlength, 188178825Sdfr const char *from, 189178825Sdfr struct sockaddr *addr, 190178825Sdfr int datagram_reply) 191178825Sdfr{ 192178825Sdfr krb5_error_code ret; 193233294Sstas unsigned int i; 194233294Sstas krb5_data req_buffer; 195233294Sstas int claim = 0; 196178825Sdfr 197233294Sstas req_buffer.data = buf; 198233294Sstas req_buffer.length = len; 199178825Sdfr 200233294Sstas for (i = 0; services[i].process != NULL; i++) { 201233294Sstas ret = (*services[i].process)(context, config, &req_buffer, 202233294Sstas reply, from, addr, datagram_reply, 203233294Sstas &claim); 204233294Sstas if (claim) { 205233294Sstas if (services[i].flags & KS_NO_LENGTH) 206233294Sstas *prependlength = 0; 207233294Sstas return ret; 208233294Sstas } 209233294Sstas } 210178825Sdfr 211178825Sdfr return -1; 212178825Sdfr} 213178825Sdfr 214178825Sdfr/* 215178825Sdfr * handle the request in `buf, len', from `addr' (or `from' as a string), 216178825Sdfr * sending a reply in `reply'. 217178825Sdfr * 218178825Sdfr * This only processes krb5 requests 219178825Sdfr */ 220178825Sdfr 221178825Sdfrint 222233294Sstaskrb5_kdc_process_krb5_request(krb5_context context, 223178825Sdfr krb5_kdc_configuration *config, 224233294Sstas unsigned char *buf, 225233294Sstas size_t len, 226178825Sdfr krb5_data *reply, 227178825Sdfr const char *from, 228178825Sdfr struct sockaddr *addr, 229178825Sdfr int datagram_reply) 230178825Sdfr{ 231178825Sdfr krb5_error_code ret; 232233294Sstas unsigned int i; 233233294Sstas krb5_data req_buffer; 234233294Sstas int claim = 0; 235178825Sdfr 236233294Sstas req_buffer.data = buf; 237233294Sstas req_buffer.length = len; 238178825Sdfr 239233294Sstas for (i = 0; services[i].process != NULL; i++) { 240233294Sstas if ((services[i].flags & KS_KRB5) == 0) 241233294Sstas continue; 242233294Sstas ret = (*services[i].process)(context, config, &req_buffer, 243233294Sstas reply, from, addr, datagram_reply, 244233294Sstas &claim); 245233294Sstas if (claim) 246233294Sstas return ret; 247233294Sstas } 248178825Sdfr 249178825Sdfr return -1; 250178825Sdfr} 251178825Sdfr 252178825Sdfr/* 253178825Sdfr * 254178825Sdfr */ 255178825Sdfr 256178825Sdfrint 257233294Sstaskrb5_kdc_save_request(krb5_context context, 258178825Sdfr const char *fn, 259178825Sdfr const unsigned char *buf, 260178825Sdfr size_t len, 261178825Sdfr const krb5_data *reply, 262178825Sdfr const struct sockaddr *sa) 263178825Sdfr{ 264178825Sdfr krb5_storage *sp; 265178825Sdfr krb5_address a; 266178825Sdfr int fd, ret; 267178825Sdfr uint32_t t; 268178825Sdfr krb5_data d; 269178825Sdfr 270178825Sdfr memset(&a, 0, sizeof(a)); 271178825Sdfr 272178825Sdfr d.data = rk_UNCONST(buf); 273178825Sdfr d.length = len; 274178825Sdfr t = _kdc_now.tv_sec; 275178825Sdfr 276178825Sdfr fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0600); 277178825Sdfr if (fd < 0) { 278233294Sstas int saved_errno = errno; 279233294Sstas krb5_set_error_message(context, saved_errno, "Failed to open: %s", fn); 280233294Sstas return saved_errno; 281178825Sdfr } 282233294Sstas 283178825Sdfr sp = krb5_storage_from_fd(fd); 284178825Sdfr close(fd); 285178825Sdfr if (sp == NULL) { 286233294Sstas krb5_set_error_message(context, ENOMEM, "Storage failed to open fd"); 287178825Sdfr return ENOMEM; 288178825Sdfr } 289178825Sdfr 290178825Sdfr ret = krb5_sockaddr2address(context, sa, &a); 291178825Sdfr if (ret) 292178825Sdfr goto out; 293178825Sdfr 294178825Sdfr krb5_store_uint32(sp, 1); 295178825Sdfr krb5_store_uint32(sp, t); 296178825Sdfr krb5_store_address(sp, a); 297178825Sdfr krb5_store_data(sp, d); 298178825Sdfr { 299178825Sdfr Der_class cl; 300178825Sdfr Der_type ty; 301178825Sdfr unsigned int tag; 302178825Sdfr ret = der_get_tag (reply->data, reply->length, 303178825Sdfr &cl, &ty, &tag, NULL); 304178825Sdfr if (ret) { 305178825Sdfr krb5_store_uint32(sp, 0xffffffff); 306178825Sdfr krb5_store_uint32(sp, 0xffffffff); 307178825Sdfr } else { 308178825Sdfr krb5_store_uint32(sp, MAKE_TAG(cl, ty, 0)); 309178825Sdfr krb5_store_uint32(sp, tag); 310178825Sdfr } 311178825Sdfr } 312178825Sdfr 313178825Sdfr krb5_free_address(context, &a); 314178825Sdfrout: 315178825Sdfr krb5_storage_free(sp); 316178825Sdfr 317178825Sdfr return 0; 318178825Sdfr} 319