155682Smarkm/* 2178825Sdfr * Copyright (c) 1997 - 2007 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "iprop.h" 3555682Smarkm 36178825SdfrRCSID("$Id: ipropd_slave.c 22211 2007-12-07 19:27:27Z lha $"); 3755682Smarkm 3872445Sassarstatic krb5_log_facility *log_facility; 39178825Sdfrstatic char *server_time_lost = "5 min"; 40178825Sdfrstatic int time_before_lost; 41178825Sdfrconst char *slave_str = NULL; 4272445Sassar 4355682Smarkmstatic int 44178825Sdfrconnect_to_master (krb5_context context, const char *master, 45178825Sdfr const char *port_str) 4655682Smarkm{ 4755682Smarkm int fd; 4855682Smarkm struct sockaddr_in addr; 4955682Smarkm struct hostent *he; 5055682Smarkm 5155682Smarkm fd = socket (AF_INET, SOCK_STREAM, 0); 5255682Smarkm if (fd < 0) 5355682Smarkm krb5_err (context, 1, errno, "socket AF_INET"); 5455682Smarkm memset (&addr, 0, sizeof(addr)); 5555682Smarkm addr.sin_family = AF_INET; 56178825Sdfr if (port_str) { 57178825Sdfr addr.sin_port = krb5_getportbyname (context, 58178825Sdfr port_str, "tcp", 59178825Sdfr 0); 60178825Sdfr if (addr.sin_port == 0) { 61178825Sdfr char *ptr; 62178825Sdfr long port; 63178825Sdfr 64178825Sdfr port = strtol (port_str, &ptr, 10); 65178825Sdfr if (port == 0 && ptr == port_str) 66178825Sdfr krb5_errx (context, 1, "bad port `%s'", port_str); 67178825Sdfr addr.sin_port = htons(port); 68178825Sdfr } 69178825Sdfr } else { 70178825Sdfr addr.sin_port = krb5_getportbyname (context, IPROP_SERVICE, 71178825Sdfr "tcp", IPROP_PORT); 72178825Sdfr } 7355682Smarkm he = roken_gethostbyname (master); 7455682Smarkm if (he == NULL) 7555682Smarkm krb5_errx (context, 1, "gethostbyname: %s", hstrerror(h_errno)); 7655682Smarkm memcpy (&addr.sin_addr, he->h_addr, sizeof(addr.sin_addr)); 7755682Smarkm if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) 7855682Smarkm krb5_err (context, 1, errno, "connect"); 7955682Smarkm return fd; 8055682Smarkm} 8155682Smarkm 8255682Smarkmstatic void 8372445Sassarget_creds(krb5_context context, const char *keytab_str, 84178825Sdfr krb5_ccache *cache, const char *serverhost) 8555682Smarkm{ 8655682Smarkm krb5_keytab keytab; 8755682Smarkm krb5_principal client; 8855682Smarkm krb5_error_code ret; 89178825Sdfr krb5_get_init_creds_opt *init_opts; 9055682Smarkm krb5_creds creds; 9155682Smarkm char *server; 9272445Sassar char keytab_buf[256]; 9355682Smarkm 9472445Sassar if (keytab_str == NULL) { 9572445Sassar ret = krb5_kt_default_name (context, keytab_buf, sizeof(keytab_buf)); 9672445Sassar if (ret) 9772445Sassar krb5_err (context, 1, ret, "krb5_kt_default_name"); 9872445Sassar keytab_str = keytab_buf; 9972445Sassar } 10072445Sassar 10172445Sassar ret = krb5_kt_resolve(context, keytab_str, &keytab); 10272445Sassar if(ret) 10372445Sassar krb5_err(context, 1, ret, "%s", keytab_str); 10472445Sassar 105178825Sdfr 106178825Sdfr ret = krb5_sname_to_principal (context, slave_str, IPROP_NAME, 10755682Smarkm KRB5_NT_SRV_HST, &client); 10855682Smarkm if (ret) krb5_err(context, 1, ret, "krb5_sname_to_principal"); 10955682Smarkm 110178825Sdfr ret = krb5_get_init_creds_opt_alloc(context, &init_opts); 111178825Sdfr if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); 11255682Smarkm 113178825Sdfr asprintf (&server, "%s/%s", IPROP_NAME, serverhost); 11455682Smarkm if (server == NULL) 11555682Smarkm krb5_errx (context, 1, "malloc: no memory"); 11655682Smarkm 11755682Smarkm ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 118178825Sdfr 0, server, init_opts); 11955682Smarkm free (server); 120178825Sdfr krb5_get_init_creds_opt_free(context, init_opts); 12155682Smarkm if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds"); 12255682Smarkm 12355682Smarkm ret = krb5_kt_close(context, keytab); 12455682Smarkm if(ret) krb5_err(context, 1, ret, "krb5_kt_close"); 12555682Smarkm 12655682Smarkm ret = krb5_cc_gen_new(context, &krb5_mcc_ops, cache); 12755682Smarkm if(ret) krb5_err(context, 1, ret, "krb5_cc_gen_new"); 12855682Smarkm 12955682Smarkm ret = krb5_cc_initialize(context, *cache, client); 13055682Smarkm if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); 13155682Smarkm 13255682Smarkm ret = krb5_cc_store_cred(context, *cache, &creds); 13355682Smarkm if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); 13455682Smarkm} 13555682Smarkm 13655682Smarkmstatic void 13755682Smarkmihave (krb5_context context, krb5_auth_context auth_context, 138178825Sdfr int fd, uint32_t version) 13955682Smarkm{ 14055682Smarkm int ret; 14155682Smarkm u_char buf[8]; 14255682Smarkm krb5_storage *sp; 143178825Sdfr krb5_data data; 14455682Smarkm 14555682Smarkm sp = krb5_storage_from_mem (buf, 8); 14655682Smarkm krb5_store_int32 (sp, I_HAVE); 14755682Smarkm krb5_store_int32 (sp, version); 14855682Smarkm krb5_storage_free (sp); 14955682Smarkm data.length = 8; 15055682Smarkm data.data = buf; 15155682Smarkm 152178825Sdfr ret = krb5_write_priv_message(context, auth_context, &fd, &data); 15355682Smarkm if (ret) 154178825Sdfr krb5_err (context, 1, ret, "krb5_write_priv_message"); 15555682Smarkm} 15655682Smarkm 15755682Smarkmstatic void 15872445Sassarreceive_loop (krb5_context context, 15972445Sassar krb5_storage *sp, 16072445Sassar kadm5_server_context *server_context) 16155682Smarkm{ 16255682Smarkm int ret; 16355682Smarkm off_t left, right; 16455682Smarkm void *buf; 165178825Sdfr int32_t vers, vers2; 166178825Sdfr ssize_t sret; 16755682Smarkm 168178825Sdfr /* 169178825Sdfr * Seek to the current version of the local database. 170178825Sdfr */ 17155682Smarkm do { 17255682Smarkm int32_t len, timestamp, tmp; 17355682Smarkm enum kadm_ops op; 17455682Smarkm 17555682Smarkm if(krb5_ret_int32 (sp, &vers) != 0) 17655682Smarkm return; 17755682Smarkm krb5_ret_int32 (sp, ×tamp); 17855682Smarkm krb5_ret_int32 (sp, &tmp); 17955682Smarkm op = tmp; 18055682Smarkm krb5_ret_int32 (sp, &len); 18155682Smarkm if (vers <= server_context->log_context.version) 182178825Sdfr krb5_storage_seek(sp, len + 8, SEEK_CUR); 18355682Smarkm } while(vers <= server_context->log_context.version); 18455682Smarkm 185178825Sdfr /* 186178825Sdfr * Read up rest of the entires into the memory... 187178825Sdfr */ 188102644Snectar left = krb5_storage_seek (sp, -16, SEEK_CUR); 189102644Snectar right = krb5_storage_seek (sp, 0, SEEK_END); 19055682Smarkm buf = malloc (right - left); 191178825Sdfr if (buf == NULL && (right - left) != 0) 192178825Sdfr krb5_errx (context, 1, "malloc: no memory"); 193178825Sdfr 194178825Sdfr /* 195178825Sdfr * ...and then write them out to the on-disk log. 196178825Sdfr */ 197102644Snectar krb5_storage_seek (sp, left, SEEK_SET); 198102644Snectar krb5_storage_read (sp, buf, right - left); 199178825Sdfr sret = write (server_context->log_context.log_fd, buf, right-left); 200178825Sdfr if (sret != right - left) 201178825Sdfr krb5_err(context, 1, errno, "Failed to write log to disk"); 202178825Sdfr ret = fsync (server_context->log_context.log_fd); 203178825Sdfr if (ret) 204178825Sdfr krb5_err(context, 1, errno, "Failed to sync log to disk"); 20555682Smarkm free (buf); 20655682Smarkm 207178825Sdfr /* 208178825Sdfr * Go back to the startpoint and start to commit the entires to 209178825Sdfr * the database. 210178825Sdfr */ 211102644Snectar krb5_storage_seek (sp, left, SEEK_SET); 21255682Smarkm 21355682Smarkm for(;;) { 214178825Sdfr int32_t len, len2, timestamp, tmp; 215178825Sdfr off_t cur, cur2; 21655682Smarkm enum kadm_ops op; 21755682Smarkm 21855682Smarkm if(krb5_ret_int32 (sp, &vers) != 0) 21955682Smarkm break; 220178825Sdfr ret = krb5_ret_int32 (sp, ×tamp); 221178825Sdfr if (ret) krb5_errx(context, 1, "entry %ld: too short", (long)vers); 222178825Sdfr ret = krb5_ret_int32 (sp, &tmp); 223178825Sdfr if (ret) krb5_errx(context, 1, "entry %ld: too short", (long)vers); 22455682Smarkm op = tmp; 225178825Sdfr ret = krb5_ret_int32 (sp, &len); 226178825Sdfr if (ret) krb5_errx(context, 1, "entry %ld: too short", (long)vers); 227178825Sdfr if (len < 0) 228178825Sdfr krb5_errx(context, 1, "log is corrupted, " 229178825Sdfr "negative length of entry version %ld: %ld", 230178825Sdfr (long)vers, (long)len); 231178825Sdfr cur = krb5_storage_seek(sp, 0, SEEK_CUR); 23255682Smarkm 233178825Sdfr krb5_warnx (context, "replaying entry %d", (int)vers); 234178825Sdfr 23555682Smarkm ret = kadm5_log_replay (server_context, 23655682Smarkm op, vers, len, sp); 237178825Sdfr if (ret) { 238178825Sdfr char *s = krb5_get_error_message(server_context->context, ret); 239178825Sdfr krb5_warnx (context, 240178825Sdfr "kadm5_log_replay: %ld. Lost entry entry, " 241178825Sdfr "Database out of sync ?: %s (%d)", 242178825Sdfr (long)vers, s ? s : "unknown error", ret); 243178825Sdfr krb5_xfree(s); 244178825Sdfr } 245178825Sdfr 246178825Sdfr { 247178825Sdfr /* 248178825Sdfr * Make sure the krb5_log_replay does the right thing wrt 249178825Sdfr * reading out data from the sp. 250178825Sdfr */ 251178825Sdfr cur2 = krb5_storage_seek(sp, 0, SEEK_CUR); 252178825Sdfr if (cur + len != cur2) 253178825Sdfr krb5_errx(context, 1, 254178825Sdfr "kadm5_log_reply version: %ld didn't read the whole entry", 255178825Sdfr (long)vers); 256178825Sdfr } 257178825Sdfr 258178825Sdfr if (krb5_ret_int32 (sp, &len2) != 0) 259178825Sdfr krb5_errx(context, 1, "entry %ld: postamble too short", (long)vers); 260178825Sdfr if(krb5_ret_int32 (sp, &vers2) != 0) 261178825Sdfr krb5_errx(context, 1, "entry %ld: postamble too short", (long)vers); 262178825Sdfr 263178825Sdfr if (len != len2) 264178825Sdfr krb5_errx(context, 1, "entry %ld: len != len2", (long)vers); 265178825Sdfr if (vers != vers2) 266178825Sdfr krb5_errx(context, 1, "entry %ld: vers != vers2", (long)vers); 26755682Smarkm } 268178825Sdfr 269178825Sdfr /* 270178825Sdfr * Update version 271178825Sdfr */ 272178825Sdfr 273178825Sdfr server_context->log_context.version = vers; 27472445Sassar} 27555682Smarkm 27672445Sassarstatic void 27772445Sassarreceive (krb5_context context, 27872445Sassar krb5_storage *sp, 27972445Sassar kadm5_server_context *server_context) 28072445Sassar{ 28172445Sassar int ret; 28272445Sassar 283178825Sdfr ret = server_context->db->hdb_open(context, 284178825Sdfr server_context->db, 285178825Sdfr O_RDWR | O_CREAT, 0600); 28672445Sassar if (ret) 28772445Sassar krb5_err (context, 1, ret, "db->open"); 28872445Sassar 28972445Sassar receive_loop (context, sp, server_context); 29072445Sassar 291178825Sdfr ret = server_context->db->hdb_close (context, server_context->db); 29255682Smarkm if (ret) 29355682Smarkm krb5_err (context, 1, ret, "db->close"); 29455682Smarkm} 29555682Smarkm 29672445Sassarstatic void 297178825Sdfrsend_im_here (krb5_context context, int fd, 298178825Sdfr krb5_auth_context auth_context) 299178825Sdfr{ 300178825Sdfr krb5_storage *sp; 301178825Sdfr krb5_data data; 302178825Sdfr int ret; 303178825Sdfr 304178825Sdfr ret = krb5_data_alloc (&data, 4); 305178825Sdfr if (ret) 306178825Sdfr krb5_err (context, 1, ret, "send_im_here"); 307178825Sdfr 308178825Sdfr sp = krb5_storage_from_data (&data); 309178825Sdfr if (sp == NULL) 310178825Sdfr krb5_errx (context, 1, "krb5_storage_from_data"); 311178825Sdfr krb5_store_int32(sp, I_AM_HERE); 312178825Sdfr krb5_storage_free(sp); 313178825Sdfr 314178825Sdfr ret = krb5_write_priv_message(context, auth_context, &fd, &data); 315178825Sdfr krb5_data_free(&data); 316178825Sdfr 317178825Sdfr if (ret) 318178825Sdfr krb5_err (context, 1, ret, "krb5_write_priv_message"); 319178825Sdfr} 320178825Sdfr 321178825Sdfrstatic void 32272445Sassarreceive_everything (krb5_context context, int fd, 32372445Sassar kadm5_server_context *server_context, 32472445Sassar krb5_auth_context auth_context) 32572445Sassar{ 32672445Sassar int ret; 32772445Sassar krb5_data data; 32872445Sassar int32_t vno; 32972445Sassar int32_t opcode; 330178825Sdfr krb5_storage *sp; 33172445Sassar 332107207Snectar char *dbname; 333107207Snectar HDB *mydb; 334107207Snectar 335178825Sdfr krb5_warnx(context, "receive complete database"); 336178825Sdfr 337178825Sdfr asprintf(&dbname, "%s-NEW", server_context->db->hdb_name); 338107207Snectar ret = hdb_create(context, &mydb, dbname); 339107207Snectar if(ret) 340107207Snectar krb5_err(context,1, ret, "hdb_create"); 341107207Snectar free(dbname); 342107207Snectar 343107207Snectar ret = hdb_set_master_keyfile (context, 344107207Snectar mydb, server_context->config.stash_file); 345107207Snectar if(ret) 346107207Snectar krb5_err(context,1, ret, "hdb_set_master_keyfile"); 347107207Snectar 348107207Snectar /* I really want to use O_EXCL here, but given that I can't easily clean 349107207Snectar up on error, I won't */ 350178825Sdfr ret = mydb->hdb_open(context, mydb, O_RDWR | O_CREAT | O_TRUNC, 0600); 35172445Sassar if (ret) 35272445Sassar krb5_err (context, 1, ret, "db->open"); 35372445Sassar 354178825Sdfr sp = NULL; 35572445Sassar do { 35672445Sassar ret = krb5_read_priv_message(context, auth_context, &fd, &data); 35772445Sassar 35872445Sassar if (ret) 35972445Sassar krb5_err (context, 1, ret, "krb5_read_priv_message"); 36072445Sassar 36172445Sassar sp = krb5_storage_from_data (&data); 362178825Sdfr if (sp == NULL) 363178825Sdfr krb5_errx (context, 1, "krb5_storage_from_data"); 36472445Sassar krb5_ret_int32 (sp, &opcode); 36572445Sassar if (opcode == ONE_PRINC) { 36672445Sassar krb5_data fake_data; 367178825Sdfr hdb_entry_ex entry; 36872445Sassar 369178825Sdfr krb5_storage_free(sp); 370178825Sdfr 37172445Sassar fake_data.data = (char *)data.data + 4; 37272445Sassar fake_data.length = data.length - 4; 37372445Sassar 374178825Sdfr memset(&entry, 0, sizeof(entry)); 375178825Sdfr 376178825Sdfr ret = hdb_value2entry (context, &fake_data, &entry.entry); 37772445Sassar if (ret) 37872445Sassar krb5_err (context, 1, ret, "hdb_value2entry"); 379178825Sdfr ret = mydb->hdb_store(server_context->context, 380178825Sdfr mydb, 381178825Sdfr 0, &entry); 38272445Sassar if (ret) 38372445Sassar krb5_err (context, 1, ret, "hdb_store"); 38472445Sassar 38572445Sassar hdb_free_entry (context, &entry); 38672445Sassar krb5_data_free (&data); 387178825Sdfr } else if (opcode == NOW_YOU_HAVE) 388178825Sdfr ; 389178825Sdfr else 390178825Sdfr krb5_errx (context, 1, "strange opcode %d", opcode); 39172445Sassar } while (opcode == ONE_PRINC); 39272445Sassar 39372445Sassar if (opcode != NOW_YOU_HAVE) 39472445Sassar krb5_errx (context, 1, "receive_everything: strange %d", opcode); 39572445Sassar 396178825Sdfr krb5_ret_int32 (sp, &vno); 397178825Sdfr krb5_storage_free(sp); 39872445Sassar 39972445Sassar ret = kadm5_log_reinit (server_context); 40072445Sassar if (ret) 40172445Sassar krb5_err(context, 1, ret, "kadm5_log_reinit"); 40272445Sassar 40372445Sassar ret = kadm5_log_set_version (server_context, vno - 1); 40472445Sassar if (ret) 40572445Sassar krb5_err (context, 1, ret, "kadm5_log_set_version"); 40672445Sassar 40772445Sassar ret = kadm5_log_nop (server_context); 40872445Sassar if (ret) 40972445Sassar krb5_err (context, 1, ret, "kadm5_log_nop"); 41072445Sassar 41172445Sassar krb5_data_free (&data); 41272445Sassar 413178825Sdfr ret = mydb->hdb_rename (context, mydb, server_context->db->hdb_name); 414127808Snectar if (ret) 415127808Snectar krb5_err (context, 1, ret, "db->rename"); 416127808Snectar 417178825Sdfr ret = mydb->hdb_close (context, mydb); 41872445Sassar if (ret) 41972445Sassar krb5_err (context, 1, ret, "db->close"); 420127808Snectar 421178825Sdfr ret = mydb->hdb_destroy (context, mydb); 422107207Snectar if (ret) 423107207Snectar krb5_err (context, 1, ret, "db->destroy"); 424178825Sdfr 425178825Sdfr krb5_warnx(context, "receive complete database, version %ld", (long)vno); 42672445Sassar} 42772445Sassar 428178825Sdfrstatic char *config_file; 42972445Sassarstatic char *realm; 43072445Sassarstatic int version_flag; 43172445Sassarstatic int help_flag; 43272445Sassarstatic char *keytab_str; 433178825Sdfrstatic char *port_str; 434178825Sdfrstatic int detach_from_console = 0; 43572445Sassar 43672445Sassarstatic struct getargs args[] = { 437178825Sdfr { "config-file", 'c', arg_string, &config_file }, 43855682Smarkm { "realm", 'r', arg_string, &realm }, 43972445Sassar { "keytab", 'k', arg_string, &keytab_str, 44072445Sassar "keytab to get authentication from", "kspec" }, 441178825Sdfr { "time-lost", 0, arg_string, &server_time_lost, 442178825Sdfr "time before server is considered lost", "time" }, 443178825Sdfr { "port", 0, arg_string, &port_str, 444178825Sdfr "port ipropd-slave will connect to", "port"}, 445178825Sdfr { "detach", 0, arg_flag, &detach_from_console, 446178825Sdfr "detach from console" }, 447178825Sdfr { "hostname", 0, arg_string, &slave_str, 448178825Sdfr "hostname of slave (if not same as hostname)", "hostname" }, 44955682Smarkm { "version", 0, arg_flag, &version_flag }, 45055682Smarkm { "help", 0, arg_flag, &help_flag } 45155682Smarkm}; 45255682Smarkm 45372445Sassarstatic int num_args = sizeof(args) / sizeof(args[0]); 45472445Sassar 45555682Smarkmint 45655682Smarkmmain(int argc, char **argv) 45755682Smarkm{ 45855682Smarkm krb5_error_code ret; 45955682Smarkm krb5_context context; 46055682Smarkm krb5_auth_context auth_context; 46155682Smarkm void *kadm_handle; 46255682Smarkm kadm5_server_context *server_context; 46355682Smarkm kadm5_config_params conf; 46455682Smarkm int master_fd; 46555682Smarkm krb5_ccache ccache; 46655682Smarkm krb5_principal server; 467178825Sdfr char **files; 468178825Sdfr int optidx; 46955682Smarkm 47072445Sassar const char *master; 47155682Smarkm 472178825Sdfr optidx = krb5_program_setup(&context, argc, argv, args, num_args, NULL); 47355682Smarkm 47455682Smarkm if(help_flag) 475178825Sdfr krb5_std_usage(0, args, num_args); 47655682Smarkm if(version_flag) { 47755682Smarkm print_version(NULL); 47855682Smarkm exit(0); 47955682Smarkm } 48055682Smarkm 481178825Sdfr setup_signal(); 48272445Sassar 483178825Sdfr if (config_file == NULL) { 484178825Sdfr asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); 485178825Sdfr if (config_file == NULL) 486178825Sdfr errx(1, "out of memory"); 487178825Sdfr } 488178825Sdfr 489178825Sdfr ret = krb5_prepend_config_files_default(config_file, &files); 490178825Sdfr if (ret) 491178825Sdfr krb5_err(context, 1, ret, "getting configuration files"); 492178825Sdfr 493178825Sdfr ret = krb5_set_config_files(context, files); 494178825Sdfr krb5_free_config_files(files); 495178825Sdfr if (ret) 496178825Sdfr krb5_err(context, 1, ret, "reading configuration files"); 497178825Sdfr 498178825Sdfr argc -= optidx; 499178825Sdfr argv += optidx; 500178825Sdfr 50172445Sassar if (argc != 1) 502178825Sdfr krb5_std_usage(1, args, num_args); 50372445Sassar 50472445Sassar master = argv[0]; 50572445Sassar 506178825Sdfr if (detach_from_console) 507178825Sdfr daemon(0, 0); 50890926Snectar pidfile (NULL); 50990926Snectar krb5_openlog (context, "ipropd-slave", &log_facility); 51072445Sassar krb5_set_warn_dest(context, log_facility); 51172445Sassar 51272445Sassar ret = krb5_kt_register(context, &hdb_kt_ops); 51372445Sassar if(ret) 51472445Sassar krb5_err(context, 1, ret, "krb5_kt_register"); 51572445Sassar 516178825Sdfr time_before_lost = parse_time (server_time_lost, "s"); 517178825Sdfr if (time_before_lost < 0) 518178825Sdfr krb5_errx (context, 1, "couldn't parse time: %s", server_time_lost); 519178825Sdfr 52055682Smarkm memset(&conf, 0, sizeof(conf)); 52155682Smarkm if(realm) { 52255682Smarkm conf.mask |= KADM5_CONFIG_REALM; 52355682Smarkm conf.realm = realm; 52455682Smarkm } 52555682Smarkm ret = kadm5_init_with_password_ctx (context, 52655682Smarkm KADM5_ADMIN_SERVICE, 52755682Smarkm NULL, 52855682Smarkm KADM5_ADMIN_SERVICE, 52955682Smarkm &conf, 0, 0, 53055682Smarkm &kadm_handle); 53155682Smarkm if (ret) 53255682Smarkm krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); 53355682Smarkm 53455682Smarkm server_context = (kadm5_server_context *)kadm_handle; 53555682Smarkm 53655682Smarkm ret = kadm5_log_init (server_context); 53755682Smarkm if (ret) 53855682Smarkm krb5_err (context, 1, ret, "kadm5_log_init"); 53955682Smarkm 54072445Sassar get_creds(context, keytab_str, &ccache, master); 54155682Smarkm 542178825Sdfr master_fd = connect_to_master (context, master, port_str); 54355682Smarkm 54472445Sassar ret = krb5_sname_to_principal (context, master, IPROP_NAME, 54555682Smarkm KRB5_NT_SRV_HST, &server); 54655682Smarkm if (ret) 54755682Smarkm krb5_err (context, 1, ret, "krb5_sname_to_principal"); 54855682Smarkm 54955682Smarkm auth_context = NULL; 55055682Smarkm ret = krb5_sendauth (context, &auth_context, &master_fd, 55155682Smarkm IPROP_VERSION, NULL, server, 55255682Smarkm AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, 55355682Smarkm ccache, NULL, NULL, NULL); 55455682Smarkm if (ret) 55555682Smarkm krb5_err (context, 1, ret, "krb5_sendauth"); 55655682Smarkm 557178825Sdfr krb5_warnx(context, "ipropd-slave started at version: %ld", 558178825Sdfr (long)server_context->log_context.version); 559178825Sdfr 56055682Smarkm ihave (context, auth_context, master_fd, 56155682Smarkm server_context->log_context.version); 56255682Smarkm 563178825Sdfr while (exit_flag == 0) { 56472445Sassar krb5_data out; 56555682Smarkm krb5_storage *sp; 56655682Smarkm int32_t tmp; 567178825Sdfr fd_set readset; 568178825Sdfr struct timeval to; 56955682Smarkm 570178825Sdfr if (master_fd >= FD_SETSIZE) 571178825Sdfr krb5_errx (context, 1, "fd too large"); 572178825Sdfr 573178825Sdfr FD_ZERO(&readset); 574178825Sdfr FD_SET(master_fd, &readset); 575178825Sdfr 576178825Sdfr to.tv_sec = time_before_lost; 577178825Sdfr to.tv_usec = 0; 578178825Sdfr 579178825Sdfr ret = select (master_fd + 1, 580178825Sdfr &readset, NULL, NULL, &to); 581178825Sdfr if (ret < 0) { 582178825Sdfr if (errno == EINTR) 583178825Sdfr continue; 584178825Sdfr else 585178825Sdfr krb5_err (context, 1, errno, "select"); 586178825Sdfr } 587178825Sdfr if (ret == 0) 588178825Sdfr krb5_errx (context, 1, "server didn't send a message " 589178825Sdfr "in %d seconds", time_before_lost); 590178825Sdfr 59172445Sassar ret = krb5_read_priv_message(context, auth_context, &master_fd, &out); 59255682Smarkm 59355682Smarkm if (ret) 59472445Sassar krb5_err (context, 1, ret, "krb5_read_priv_message"); 59555682Smarkm 59655682Smarkm sp = krb5_storage_from_mem (out.data, out.length); 59755682Smarkm krb5_ret_int32 (sp, &tmp); 59855682Smarkm switch (tmp) { 59955682Smarkm case FOR_YOU : 60055682Smarkm receive (context, sp, server_context); 60155682Smarkm ihave (context, auth_context, master_fd, 60255682Smarkm server_context->log_context.version); 60355682Smarkm break; 60472445Sassar case TELL_YOU_EVERYTHING : 60572445Sassar receive_everything (context, master_fd, server_context, 60672445Sassar auth_context); 60772445Sassar break; 608178825Sdfr case ARE_YOU_THERE : 609178825Sdfr send_im_here (context, master_fd, auth_context); 610178825Sdfr break; 61172445Sassar case NOW_YOU_HAVE : 61255682Smarkm case I_HAVE : 61372445Sassar case ONE_PRINC : 614178825Sdfr case I_AM_HERE : 61555682Smarkm default : 61655682Smarkm krb5_warnx (context, "Ignoring command %d", tmp); 61755682Smarkm break; 61855682Smarkm } 61955682Smarkm krb5_storage_free (sp); 62055682Smarkm krb5_data_free (&out); 62155682Smarkm } 62272445Sassar 623178825Sdfr if(exit_flag == SIGXCPU) 624178825Sdfr krb5_warnx(context, "%s CPU time limit exceeded", getprogname()); 625178825Sdfr else if(exit_flag == SIGINT || exit_flag == SIGTERM) 626178825Sdfr krb5_warnx(context, "%s terminated", getprogname()); 627178825Sdfr else 628178825Sdfr krb5_warnx(context, "%s unexpected exit reason: %d", 629178825Sdfr getprogname(), exit_flag); 630178825Sdfr 63155682Smarkm return 0; 63290926Snectar} 633