155682Smarkm/* 2178825Sdfr * Copyright (c) 1997-2006 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 "hprop.h" 3555682Smarkm 36178825SdfrRCSID("$Id: hpropd.c 22245 2007-12-08 23:48:52Z lha $"); 3755682Smarkm 3855682Smarkmstatic int inetd_flag = -1; 3955682Smarkmstatic int help_flag; 4055682Smarkmstatic int version_flag; 4155682Smarkmstatic int print_dump; 42178825Sdfrstatic const char *database; 4355682Smarkmstatic int from_stdin; 4490926Snectarstatic char *local_realm; 4572445Sassarstatic char *ktname = NULL; 4655682Smarkm 4755682Smarkmstruct getargs args[] = { 4855682Smarkm { "database", 'd', arg_string, &database, "database", "file" }, 4955682Smarkm { "stdin", 'n', arg_flag, &from_stdin, "read from stdin" }, 5055682Smarkm { "print", 0, arg_flag, &print_dump, "print dump to stdout" }, 5155682Smarkm { "inetd", 'i', arg_negative_flag, &inetd_flag, 5255682Smarkm "Not started from inetd" }, 5372445Sassar { "keytab", 'k', arg_string, &ktname, "keytab to use for authentication", "keytab" }, 5490926Snectar { "realm", 'r', arg_string, &local_realm, "realm to use" }, 5555682Smarkm { "version", 0, arg_flag, &version_flag, NULL, NULL }, 5655682Smarkm { "help", 'h', arg_flag, &help_flag, NULL, NULL} 5755682Smarkm}; 5855682Smarkm 5955682Smarkmstatic int num_args = sizeof(args) / sizeof(args[0]); 6055682Smarkm 6155682Smarkmstatic void 6255682Smarkmusage(int ret) 6355682Smarkm{ 6455682Smarkm arg_printusage (args, num_args, NULL, ""); 6555682Smarkm exit (ret); 6655682Smarkm} 6755682Smarkm 6855682Smarkmint 6955682Smarkmmain(int argc, char **argv) 7055682Smarkm{ 7155682Smarkm krb5_error_code ret; 7255682Smarkm krb5_context context; 7355682Smarkm krb5_auth_context ac = NULL; 7455682Smarkm krb5_principal c1, c2; 7555682Smarkm krb5_authenticator authent; 7655682Smarkm krb5_keytab keytab; 7755682Smarkm int fd; 7855682Smarkm HDB *db; 79178825Sdfr int optidx = 0; 8055682Smarkm char *tmp_db; 8155682Smarkm krb5_log_facility *fac; 8255682Smarkm int nprincs; 8355682Smarkm 8478527Sassar setprogname(argv[0]); 8555682Smarkm 8655682Smarkm ret = krb5_init_context(&context); 8755682Smarkm if(ret) 8855682Smarkm exit(1); 8955682Smarkm 9055682Smarkm ret = krb5_openlog(context, "hpropd", &fac); 9155682Smarkm if(ret) 9255682Smarkm ; 9355682Smarkm krb5_set_warn_dest(context, fac); 9455682Smarkm 95178825Sdfr if(getarg(args, num_args, argc, argv, &optidx)) 9655682Smarkm usage(1); 9755682Smarkm 9890926Snectar if(local_realm != NULL) 9990926Snectar krb5_set_default_realm(context, local_realm); 10055682Smarkm 10155682Smarkm if(help_flag) 10255682Smarkm usage(0); 10355682Smarkm if(version_flag) { 10455682Smarkm print_version(NULL); 10555682Smarkm exit(0); 10655682Smarkm } 10755682Smarkm 108178825Sdfr argc -= optidx; 109178825Sdfr argv += optidx; 11055682Smarkm 11155682Smarkm if (argc != 0) 11255682Smarkm usage(1); 11355682Smarkm 114178825Sdfr if (database == NULL) 115178825Sdfr database = hdb_default_db(context); 116178825Sdfr 11755682Smarkm if(from_stdin) 11855682Smarkm fd = STDIN_FILENO; 11955682Smarkm else { 12055682Smarkm struct sockaddr_storage ss; 12155682Smarkm struct sockaddr *sa = (struct sockaddr *)&ss; 12272445Sassar socklen_t sin_len = sizeof(ss); 12355682Smarkm char addr_name[256]; 12472445Sassar krb5_ticket *ticket; 12572445Sassar char *server; 12655682Smarkm 12755682Smarkm fd = STDIN_FILENO; 12855682Smarkm if (inetd_flag == -1) { 12955682Smarkm if (getpeername (fd, sa, &sin_len) < 0) 13055682Smarkm inetd_flag = 0; 13155682Smarkm else 13255682Smarkm inetd_flag = 1; 13355682Smarkm } 13455682Smarkm if (!inetd_flag) { 13555682Smarkm mini_inetd (krb5_getportbyname (context, "hprop", "tcp", 13655682Smarkm HPROP_PORT)); 13755682Smarkm } 13855682Smarkm sin_len = sizeof(ss); 13955682Smarkm if(getpeername(fd, sa, &sin_len) < 0) 14055682Smarkm krb5_err(context, 1, errno, "getpeername"); 14155682Smarkm 14255682Smarkm if (inet_ntop(sa->sa_family, 14355682Smarkm socket_get_address (sa), 14455682Smarkm addr_name, 14555682Smarkm sizeof(addr_name)) == NULL) 14655682Smarkm strlcpy (addr_name, "unknown address", 147178825Sdfr sizeof(addr_name)); 14855682Smarkm 14955682Smarkm krb5_log(context, fac, 0, "Connection from %s", addr_name); 15055682Smarkm 15172445Sassar ret = krb5_kt_register(context, &hdb_kt_ops); 15255682Smarkm if(ret) 15372445Sassar krb5_err(context, 1, ret, "krb5_kt_register"); 15472445Sassar 15572445Sassar if (ktname != NULL) { 15672445Sassar ret = krb5_kt_resolve(context, ktname, &keytab); 15772445Sassar if (ret) 15872445Sassar krb5_err (context, 1, ret, "krb5_kt_resolve %s", ktname); 15972445Sassar } else { 16072445Sassar ret = krb5_kt_default (context, &keytab); 16172445Sassar if (ret) 16272445Sassar krb5_err (context, 1, ret, "krb5_kt_default"); 16372445Sassar } 16472445Sassar 16572445Sassar ret = krb5_recvauth(context, &ac, &fd, HPROP_VERSION, NULL, 16672445Sassar 0, keytab, &ticket); 16755682Smarkm if(ret) 16855682Smarkm krb5_err(context, 1, ret, "krb5_recvauth"); 16955682Smarkm 17072445Sassar ret = krb5_unparse_name(context, ticket->server, &server); 17172445Sassar if (ret) 17272445Sassar krb5_err(context, 1, ret, "krb5_unparse_name"); 17372445Sassar if (strncmp(server, "hprop/", 5) != 0) 17472445Sassar krb5_errx(context, 1, "ticket not for hprop (%s)", server); 17572445Sassar 17672445Sassar free(server); 17772445Sassar krb5_free_ticket (context, ticket); 17872445Sassar 17990926Snectar ret = krb5_auth_con_getauthenticator(context, ac, &authent); 18055682Smarkm if(ret) 18190926Snectar krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator"); 18255682Smarkm 18355682Smarkm ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL); 18455682Smarkm if(ret) 18555682Smarkm krb5_err(context, 1, ret, "krb5_make_principal"); 186178825Sdfr _krb5_principalname2krb5_principal(context, &c2, 187178825Sdfr authent->cname, authent->crealm); 18855682Smarkm if(!krb5_principal_compare(context, c1, c2)) { 18955682Smarkm char *s; 190178825Sdfr ret = krb5_unparse_name(context, c2, &s); 191178825Sdfr if (ret) 192178825Sdfr s = "unparseable name"; 19355682Smarkm krb5_errx(context, 1, "Unauthorized connection from %s", s); 19455682Smarkm } 19555682Smarkm krb5_free_principal(context, c1); 19655682Smarkm krb5_free_principal(context, c2); 19755682Smarkm 19855682Smarkm ret = krb5_kt_close(context, keytab); 19955682Smarkm if(ret) 20055682Smarkm krb5_err(context, 1, ret, "krb5_kt_close"); 20155682Smarkm } 20255682Smarkm 20355682Smarkm if(!print_dump) { 20455682Smarkm asprintf(&tmp_db, "%s~", database); 20555682Smarkm 206178825Sdfr ret = hdb_create(context, &db, tmp_db); 207178825Sdfr if(ret) 208178825Sdfr krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db); 209178825Sdfr ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600); 210178825Sdfr if(ret) 211178825Sdfr krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db); 21255682Smarkm } 21355682Smarkm 21455682Smarkm nprincs = 0; 21555682Smarkm while(1){ 21655682Smarkm krb5_data data; 217178825Sdfr hdb_entry_ex entry; 21855682Smarkm 21972445Sassar if(from_stdin) { 22072445Sassar ret = krb5_read_message(context, &fd, &data); 22172445Sassar if(ret != 0 && ret != HEIM_ERR_EOF) 22272445Sassar krb5_err(context, 1, ret, "krb5_read_message"); 22372445Sassar } else { 22472445Sassar ret = krb5_read_priv_message(context, ac, &fd, &data); 22555682Smarkm if(ret) 22672445Sassar krb5_err(context, 1, ret, "krb5_read_priv_message"); 22755682Smarkm } 22855682Smarkm 22972445Sassar if(ret == HEIM_ERR_EOF || data.length == 0) { 23055682Smarkm if(!from_stdin) { 23155682Smarkm data.data = NULL; 23255682Smarkm data.length = 0; 23372445Sassar krb5_write_priv_message(context, ac, &fd, &data); 23455682Smarkm } 23555682Smarkm if(!print_dump) { 236178825Sdfr ret = db->hdb_rename(context, db, database); 237178825Sdfr if(ret) 238178825Sdfr krb5_err(context, 1, ret, "db_rename"); 239178825Sdfr ret = db->hdb_close(context, db); 240178825Sdfr if(ret) 241178825Sdfr krb5_err(context, 1, ret, "db_close"); 24255682Smarkm } 24355682Smarkm break; 24455682Smarkm } 245178825Sdfr memset(&entry, 0, sizeof(entry)); 246178825Sdfr ret = hdb_value2entry(context, &data, &entry.entry); 247178825Sdfr krb5_data_free(&data); 24855682Smarkm if(ret) 24955682Smarkm krb5_err(context, 1, ret, "hdb_value2entry"); 25055682Smarkm if(print_dump) 25155682Smarkm hdb_print_entry(context, db, &entry, stdout); 25255682Smarkm else { 253178825Sdfr ret = db->hdb_store(context, db, 0, &entry); 254178825Sdfr if(ret == HDB_ERR_EXISTS) { 255178825Sdfr char *s; 256178825Sdfr ret = krb5_unparse_name(context, entry.entry.principal, &s); 257178825Sdfr if (ret) 258178825Sdfr s = strdup("unparseable name"); 259178825Sdfr krb5_warnx(context, "Entry exists: %s", s); 260178825Sdfr free(s); 261178825Sdfr } else if(ret) 262178825Sdfr krb5_err(context, 1, ret, "db_store"); 26355682Smarkm else 264178825Sdfr nprincs++; 26555682Smarkm } 26655682Smarkm hdb_free_entry(context, &entry); 26755682Smarkm } 26855682Smarkm if (!print_dump) 26955682Smarkm krb5_log(context, fac, 0, "Received %d principals", nprincs); 27055682Smarkm exit(0); 27155682Smarkm} 272