1b528cefcSMark Murray /* 2*ae771770SStanislav Sedov * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "hprop.h" 35b528cefcSMark Murray 36b528cefcSMark Murray static int inetd_flag = -1; 37b528cefcSMark Murray static int help_flag; 38b528cefcSMark Murray static int version_flag; 39b528cefcSMark Murray static int print_dump; 40c19800e8SDoug Rabson static const char *database; 41b528cefcSMark Murray static int from_stdin; 424137ff4cSJacques Vidrine static char *local_realm; 435e9cd1aeSAssar Westerlund static char *ktname = NULL; 44b528cefcSMark Murray 45b528cefcSMark Murray struct getargs args[] = { 46*ae771770SStanislav Sedov { "database", 'd', arg_string, rk_UNCONST(&database), "database", "file" }, 47*ae771770SStanislav Sedov { "stdin", 'n', arg_flag, &from_stdin, "read from stdin", NULL }, 48*ae771770SStanislav Sedov { "print", 0, arg_flag, &print_dump, "print dump to stdout", NULL }, 49*ae771770SStanislav Sedov #ifdef SUPPORT_INETD 50b528cefcSMark Murray { "inetd", 'i', arg_negative_flag, &inetd_flag, 51*ae771770SStanislav Sedov "Not started from inetd", NULL }, 52*ae771770SStanislav Sedov #endif 535e9cd1aeSAssar Westerlund { "keytab", 'k', arg_string, &ktname, "keytab to use for authentication", "keytab" }, 54*ae771770SStanislav Sedov { "realm", 'r', arg_string, &local_realm, "realm to use", NULL }, 55b528cefcSMark Murray { "version", 0, arg_flag, &version_flag, NULL, NULL }, 56b528cefcSMark Murray { "help", 'h', arg_flag, &help_flag, NULL, NULL} 57b528cefcSMark Murray }; 58b528cefcSMark Murray 59b528cefcSMark Murray static int num_args = sizeof(args) / sizeof(args[0]); 60*ae771770SStanislav Sedov static char unparseable_name[] = "unparseable name"; 61b528cefcSMark Murray 62b528cefcSMark Murray static void 63b528cefcSMark Murray usage(int ret) 64b528cefcSMark Murray { 65b528cefcSMark Murray arg_printusage (args, num_args, NULL, ""); 66b528cefcSMark Murray exit (ret); 67b528cefcSMark Murray } 68b528cefcSMark Murray 69b528cefcSMark Murray int 70b528cefcSMark Murray main(int argc, char **argv) 71b528cefcSMark Murray { 72b528cefcSMark Murray krb5_error_code ret; 73b528cefcSMark Murray krb5_context context; 74b528cefcSMark Murray krb5_auth_context ac = NULL; 75b528cefcSMark Murray krb5_principal c1, c2; 76b528cefcSMark Murray krb5_authenticator authent; 77b528cefcSMark Murray krb5_keytab keytab; 78*ae771770SStanislav Sedov krb5_socket_t sock = rk_INVALID_SOCKET; 79*ae771770SStanislav Sedov HDB *db = NULL; 80c19800e8SDoug Rabson int optidx = 0; 81b528cefcSMark Murray char *tmp_db; 82b528cefcSMark Murray krb5_log_facility *fac; 83b528cefcSMark Murray int nprincs; 84b528cefcSMark Murray 85adb0ddaeSAssar Westerlund setprogname(argv[0]); 86b528cefcSMark Murray 87b528cefcSMark Murray ret = krb5_init_context(&context); 88b528cefcSMark Murray if(ret) 89b528cefcSMark Murray exit(1); 90b528cefcSMark Murray 91b528cefcSMark Murray ret = krb5_openlog(context, "hpropd", &fac); 92b528cefcSMark Murray if(ret) 93*ae771770SStanislav Sedov errx(1, "krb5_openlog"); 94b528cefcSMark Murray krb5_set_warn_dest(context, fac); 95b528cefcSMark Murray 96c19800e8SDoug Rabson if(getarg(args, num_args, argc, argv, &optidx)) 97b528cefcSMark Murray usage(1); 98b528cefcSMark Murray 994137ff4cSJacques Vidrine if(local_realm != NULL) 1004137ff4cSJacques Vidrine krb5_set_default_realm(context, local_realm); 1014137ff4cSJacques Vidrine 102b528cefcSMark Murray if(help_flag) 103b528cefcSMark Murray usage(0); 104b528cefcSMark Murray if(version_flag) { 105b528cefcSMark Murray print_version(NULL); 106b528cefcSMark Murray exit(0); 107b528cefcSMark Murray } 108b528cefcSMark Murray 109c19800e8SDoug Rabson argc -= optidx; 110c19800e8SDoug Rabson argv += optidx; 111b528cefcSMark Murray 112b528cefcSMark Murray if (argc != 0) 113b528cefcSMark Murray usage(1); 114b528cefcSMark Murray 115c19800e8SDoug Rabson if (database == NULL) 116c19800e8SDoug Rabson database = hdb_default_db(context); 117c19800e8SDoug Rabson 118*ae771770SStanislav Sedov if(from_stdin) { 119*ae771770SStanislav Sedov sock = STDIN_FILENO; 120*ae771770SStanislav Sedov } else { 121b528cefcSMark Murray struct sockaddr_storage ss; 122b528cefcSMark Murray struct sockaddr *sa = (struct sockaddr *)&ss; 1235e9cd1aeSAssar Westerlund socklen_t sin_len = sizeof(ss); 124b528cefcSMark Murray char addr_name[256]; 1255e9cd1aeSAssar Westerlund krb5_ticket *ticket; 1265e9cd1aeSAssar Westerlund char *server; 127b528cefcSMark Murray 128*ae771770SStanislav Sedov sock = STDIN_FILENO; 129*ae771770SStanislav Sedov #ifdef SUPPORT_INETD 130b528cefcSMark Murray if (inetd_flag == -1) { 131*ae771770SStanislav Sedov if (getpeername (sock, sa, &sin_len) < 0) { 132b528cefcSMark Murray inetd_flag = 0; 133*ae771770SStanislav Sedov } else { 134b528cefcSMark Murray inetd_flag = 1; 135b528cefcSMark Murray } 136*ae771770SStanislav Sedov } 137*ae771770SStanislav Sedov #else 138*ae771770SStanislav Sedov inetd_flag = 0; 139*ae771770SStanislav Sedov #endif 140b528cefcSMark Murray if (!inetd_flag) { 141b528cefcSMark Murray mini_inetd (krb5_getportbyname (context, "hprop", "tcp", 142*ae771770SStanislav Sedov HPROP_PORT), &sock); 143b528cefcSMark Murray } 144b528cefcSMark Murray sin_len = sizeof(ss); 145*ae771770SStanislav Sedov if(getpeername(sock, sa, &sin_len) < 0) 146b528cefcSMark Murray krb5_err(context, 1, errno, "getpeername"); 147b528cefcSMark Murray 148b528cefcSMark Murray if (inet_ntop(sa->sa_family, 149b528cefcSMark Murray socket_get_address (sa), 150b528cefcSMark Murray addr_name, 151b528cefcSMark Murray sizeof(addr_name)) == NULL) 152b528cefcSMark Murray strlcpy (addr_name, "unknown address", 153b528cefcSMark Murray sizeof(addr_name)); 154b528cefcSMark Murray 155b528cefcSMark Murray krb5_log(context, fac, 0, "Connection from %s", addr_name); 156b528cefcSMark Murray 1575e9cd1aeSAssar Westerlund ret = krb5_kt_register(context, &hdb_kt_ops); 158b528cefcSMark Murray if(ret) 1595e9cd1aeSAssar Westerlund krb5_err(context, 1, ret, "krb5_kt_register"); 160b528cefcSMark Murray 1615e9cd1aeSAssar Westerlund if (ktname != NULL) { 1625e9cd1aeSAssar Westerlund ret = krb5_kt_resolve(context, ktname, &keytab); 1635e9cd1aeSAssar Westerlund if (ret) 1645e9cd1aeSAssar Westerlund krb5_err (context, 1, ret, "krb5_kt_resolve %s", ktname); 1655e9cd1aeSAssar Westerlund } else { 166b528cefcSMark Murray ret = krb5_kt_default (context, &keytab); 167b528cefcSMark Murray if (ret) 168b528cefcSMark Murray krb5_err (context, 1, ret, "krb5_kt_default"); 1695e9cd1aeSAssar Westerlund } 170b528cefcSMark Murray 171*ae771770SStanislav Sedov ret = krb5_recvauth(context, &ac, &sock, HPROP_VERSION, NULL, 1725e9cd1aeSAssar Westerlund 0, keytab, &ticket); 173b528cefcSMark Murray if(ret) 174b528cefcSMark Murray krb5_err(context, 1, ret, "krb5_recvauth"); 175b528cefcSMark Murray 1765e9cd1aeSAssar Westerlund ret = krb5_unparse_name(context, ticket->server, &server); 1775e9cd1aeSAssar Westerlund if (ret) 1785e9cd1aeSAssar Westerlund krb5_err(context, 1, ret, "krb5_unparse_name"); 1795e9cd1aeSAssar Westerlund if (strncmp(server, "hprop/", 5) != 0) 1805e9cd1aeSAssar Westerlund krb5_errx(context, 1, "ticket not for hprop (%s)", server); 1815e9cd1aeSAssar Westerlund 1825e9cd1aeSAssar Westerlund free(server); 1835e9cd1aeSAssar Westerlund krb5_free_ticket (context, ticket); 1845e9cd1aeSAssar Westerlund 1854137ff4cSJacques Vidrine ret = krb5_auth_con_getauthenticator(context, ac, &authent); 186b528cefcSMark Murray if(ret) 1874137ff4cSJacques Vidrine krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator"); 188b528cefcSMark Murray 189b528cefcSMark Murray ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL); 190b528cefcSMark Murray if(ret) 191b528cefcSMark Murray krb5_err(context, 1, ret, "krb5_make_principal"); 192c19800e8SDoug Rabson _krb5_principalname2krb5_principal(context, &c2, 193c19800e8SDoug Rabson authent->cname, authent->crealm); 194b528cefcSMark Murray if(!krb5_principal_compare(context, c1, c2)) { 195b528cefcSMark Murray char *s; 196c19800e8SDoug Rabson ret = krb5_unparse_name(context, c2, &s); 197c19800e8SDoug Rabson if (ret) 198*ae771770SStanislav Sedov s = unparseable_name; 199b528cefcSMark Murray krb5_errx(context, 1, "Unauthorized connection from %s", s); 200b528cefcSMark Murray } 201b528cefcSMark Murray krb5_free_principal(context, c1); 202b528cefcSMark Murray krb5_free_principal(context, c2); 203b528cefcSMark Murray 204b528cefcSMark Murray ret = krb5_kt_close(context, keytab); 205b528cefcSMark Murray if(ret) 206b528cefcSMark Murray krb5_err(context, 1, ret, "krb5_kt_close"); 207b528cefcSMark Murray } 208b528cefcSMark Murray 209b528cefcSMark Murray if(!print_dump) { 210b528cefcSMark Murray asprintf(&tmp_db, "%s~", database); 211c19800e8SDoug Rabson 212b528cefcSMark Murray ret = hdb_create(context, &db, tmp_db); 213b528cefcSMark Murray if(ret) 214b528cefcSMark Murray krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db); 215c19800e8SDoug Rabson ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600); 216b528cefcSMark Murray if(ret) 217b528cefcSMark Murray krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db); 218b528cefcSMark Murray } 219b528cefcSMark Murray 220b528cefcSMark Murray nprincs = 0; 221b528cefcSMark Murray while(1){ 222b528cefcSMark Murray krb5_data data; 223c19800e8SDoug Rabson hdb_entry_ex entry; 224b528cefcSMark Murray 225b528cefcSMark Murray if(from_stdin) { 226*ae771770SStanislav Sedov ret = krb5_read_message(context, &sock, &data); 2275e9cd1aeSAssar Westerlund if(ret != 0 && ret != HEIM_ERR_EOF) 2285e9cd1aeSAssar Westerlund krb5_err(context, 1, ret, "krb5_read_message"); 229b528cefcSMark Murray } else { 230*ae771770SStanislav Sedov ret = krb5_read_priv_message(context, ac, &sock, &data); 231b528cefcSMark Murray if(ret) 2325e9cd1aeSAssar Westerlund krb5_err(context, 1, ret, "krb5_read_priv_message"); 233b528cefcSMark Murray } 234b528cefcSMark Murray 2355e9cd1aeSAssar Westerlund if(ret == HEIM_ERR_EOF || data.length == 0) { 236b528cefcSMark Murray if(!from_stdin) { 237b528cefcSMark Murray data.data = NULL; 238b528cefcSMark Murray data.length = 0; 239*ae771770SStanislav Sedov krb5_write_priv_message(context, ac, &sock, &data); 240b528cefcSMark Murray } 241b528cefcSMark Murray if(!print_dump) { 242c19800e8SDoug Rabson ret = db->hdb_close(context, db); 243b528cefcSMark Murray if(ret) 244b528cefcSMark Murray krb5_err(context, 1, ret, "db_close"); 245*ae771770SStanislav Sedov ret = db->hdb_rename(context, db, database); 246*ae771770SStanislav Sedov if(ret) 247*ae771770SStanislav Sedov krb5_err(context, 1, ret, "db_rename"); 248b528cefcSMark Murray } 249b528cefcSMark Murray break; 250b528cefcSMark Murray } 251c19800e8SDoug Rabson memset(&entry, 0, sizeof(entry)); 252c19800e8SDoug Rabson ret = hdb_value2entry(context, &data, &entry.entry); 253c19800e8SDoug Rabson krb5_data_free(&data); 254b528cefcSMark Murray if(ret) 255b528cefcSMark Murray krb5_err(context, 1, ret, "hdb_value2entry"); 256b528cefcSMark Murray if(print_dump) 257b528cefcSMark Murray hdb_print_entry(context, db, &entry, stdout); 258b528cefcSMark Murray else { 259c19800e8SDoug Rabson ret = db->hdb_store(context, db, 0, &entry); 260b528cefcSMark Murray if(ret == HDB_ERR_EXISTS) { 261b528cefcSMark Murray char *s; 262c19800e8SDoug Rabson ret = krb5_unparse_name(context, entry.entry.principal, &s); 263c19800e8SDoug Rabson if (ret) 264*ae771770SStanislav Sedov s = strdup(unparseable_name); 265b528cefcSMark Murray krb5_warnx(context, "Entry exists: %s", s); 266b528cefcSMark Murray free(s); 267b528cefcSMark Murray } else if(ret) 268b528cefcSMark Murray krb5_err(context, 1, ret, "db_store"); 269b528cefcSMark Murray else 270b528cefcSMark Murray nprincs++; 271b528cefcSMark Murray } 272b528cefcSMark Murray hdb_free_entry(context, &entry); 273b528cefcSMark Murray } 274b528cefcSMark Murray if (!print_dump) 275b528cefcSMark Murray krb5_log(context, fac, 0, "Received %d principals", nprincs); 276*ae771770SStanislav Sedov 277*ae771770SStanislav Sedov if (inetd_flag == 0) 278*ae771770SStanislav Sedov rk_closesocket(sock); 279*ae771770SStanislav Sedov 280b528cefcSMark Murray exit(0); 281b528cefcSMark Murray } 282