17c478bd9Sstevel@tonic-gate /* 254925bf6Swillf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 77c478bd9Sstevel@tonic-gate 87c478bd9Sstevel@tonic-gate #include <sys/stat.h> 97c478bd9Sstevel@tonic-gate #include <sys/types.h> 107c478bd9Sstevel@tonic-gate #include <unistd.h> 117c478bd9Sstevel@tonic-gate #include <fcntl.h> 127c478bd9Sstevel@tonic-gate #include <sys/mman.h> 137c478bd9Sstevel@tonic-gate #include <k5-int.h> 147c478bd9Sstevel@tonic-gate #include <stdlib.h> 157c478bd9Sstevel@tonic-gate #include <limits.h> 167c478bd9Sstevel@tonic-gate #include <syslog.h> 177c478bd9Sstevel@tonic-gate #include "kdb_log.h" 187c478bd9Sstevel@tonic-gate 197c478bd9Sstevel@tonic-gate /* 207c478bd9Sstevel@tonic-gate * This modules includes all the necessary functions that create and 217c478bd9Sstevel@tonic-gate * modify the Kerberos principal update and header logs. 227c478bd9Sstevel@tonic-gate */ 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate #define getpagesize() sysconf(_SC_PAGESIZE) 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate static int pagesize = 0; 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #define INIT_ULOG(ctx) log_ctx = ctx->kdblog_context; \ 297c478bd9Sstevel@tonic-gate ulog = log_ctx->ulog 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Sync update entry to disk. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate krb5_error_code 347c478bd9Sstevel@tonic-gate ulog_sync_update(kdb_hlog_t *ulog, kdb_ent_header_t *upd) 357c478bd9Sstevel@tonic-gate { 367c478bd9Sstevel@tonic-gate ulong_t start, end, size; 377c478bd9Sstevel@tonic-gate krb5_error_code retval; 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate if (ulog == NULL) 407c478bd9Sstevel@tonic-gate return (KRB5_LOG_ERROR); 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate if (!pagesize) 437c478bd9Sstevel@tonic-gate pagesize = getpagesize(); 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate start = ((ulong_t)upd) & (~(pagesize-1)); 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate end = (((ulong_t)upd) + ulog->kdb_block + 487c478bd9Sstevel@tonic-gate (pagesize-1)) & (~(pagesize-1)); 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate size = end - start; 517c478bd9Sstevel@tonic-gate if (retval = msync((caddr_t)start, size, MS_SYNC)) { 527c478bd9Sstevel@tonic-gate return (retval); 537c478bd9Sstevel@tonic-gate } 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate return (0); 567c478bd9Sstevel@tonic-gate } 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* 597c478bd9Sstevel@tonic-gate * Sync memory to disk for the update log header. 607c478bd9Sstevel@tonic-gate */ 617c478bd9Sstevel@tonic-gate void 627c478bd9Sstevel@tonic-gate ulog_sync_header(kdb_hlog_t *ulog) 637c478bd9Sstevel@tonic-gate { 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate if (!pagesize) 667c478bd9Sstevel@tonic-gate pagesize = getpagesize(); 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate if (msync((caddr_t)ulog, pagesize, MS_SYNC)) { 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * Couldn't sync to disk, let's panic 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "ulog_sync_header: could not sync to disk"); 737c478bd9Sstevel@tonic-gate abort(); 747c478bd9Sstevel@tonic-gate } 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * Resizes the array elements. We reinitialize the update log rather than 797c478bd9Sstevel@tonic-gate * unrolling the the log and copying it over to a temporary log for obvious 807c478bd9Sstevel@tonic-gate * performance reasons. Slaves will subsequently do a full resync, but 817c478bd9Sstevel@tonic-gate * the need for resizing should be very small. 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate krb5_error_code 847c478bd9Sstevel@tonic-gate ulog_resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd, uint_t recsize) 857c478bd9Sstevel@tonic-gate { 867c478bd9Sstevel@tonic-gate uint_t new_block, new_size; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate if (ulog == NULL) 897c478bd9Sstevel@tonic-gate return (KRB5_LOG_ERROR); 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate new_size = sizeof (kdb_hlog_t); 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate new_block = (recsize / ULOG_BLOCK) + 1; 947c478bd9Sstevel@tonic-gate new_block *= ULOG_BLOCK; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate new_size += ulogentries * new_block; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (new_size <= MAXLOGLEN) { 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * Reinit log with new block size 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate (void) memset(ulog, 0, sizeof (kdb_hlog_t)); 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate ulog->kdb_hmagic = KDB_HMAGIC; 1057c478bd9Sstevel@tonic-gate ulog->db_version_num = KDB_VERSION; 1067c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_STABLE; 1077c478bd9Sstevel@tonic-gate ulog->kdb_block = new_block; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate ulog_sync_header(ulog); 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * Time to expand log considering new block size 1137c478bd9Sstevel@tonic-gate */ 1147c478bd9Sstevel@tonic-gate if (lseek(ulogfd, new_size, SEEK_SET) == -1) { 1157c478bd9Sstevel@tonic-gate return (errno); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate if (write(ulogfd, "+", 1) != 1) { 1197c478bd9Sstevel@tonic-gate return (errno); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate } else { 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * Can't map into file larger than MAXLOGLEN 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate return (KRB5_LOG_ERROR); 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate return (0); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Adds an entry to the update log. 1337c478bd9Sstevel@tonic-gate * The layout of the update log looks like: 1347c478bd9Sstevel@tonic-gate * 1357c478bd9Sstevel@tonic-gate * header log -> [ update header -> xdr(kdb_incr_update_t) ], ... 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate krb5_error_code 1387c478bd9Sstevel@tonic-gate ulog_add_update(krb5_context context, kdb_incr_update_t *upd) 1397c478bd9Sstevel@tonic-gate { 1407c478bd9Sstevel@tonic-gate XDR xdrs; 1417c478bd9Sstevel@tonic-gate kdbe_time_t ktime; 1427c478bd9Sstevel@tonic-gate struct timeval timestamp; 1437c478bd9Sstevel@tonic-gate kdb_ent_header_t *indx_log; 1447c478bd9Sstevel@tonic-gate uint_t i, recsize; 1457c478bd9Sstevel@tonic-gate ulong_t upd_size; 1467c478bd9Sstevel@tonic-gate krb5_error_code retval; 1477c478bd9Sstevel@tonic-gate kdb_sno_t cur_sno; 1487c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 1497c478bd9Sstevel@tonic-gate kdb_hlog_t *ulog = NULL; 1507c478bd9Sstevel@tonic-gate uint32_t ulogentries; 1517c478bd9Sstevel@tonic-gate int ulogfd; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate INIT_ULOG(context); 1547c478bd9Sstevel@tonic-gate ulogentries = log_ctx->ulogentries; 1557c478bd9Sstevel@tonic-gate ulogfd = log_ctx->ulogfd; 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate if (upd == NULL) 1587c478bd9Sstevel@tonic-gate return (KRB5_LOG_ERROR); 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate (void) gettimeofday(×tamp, NULL); 1617c478bd9Sstevel@tonic-gate ktime.seconds = timestamp.tv_sec; 1627c478bd9Sstevel@tonic-gate ktime.useconds = timestamp.tv_usec; 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate upd_size = xdr_sizeof((xdrproc_t)xdr_kdb_incr_update_t, upd); 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate recsize = sizeof (kdb_ent_header_t) + upd_size; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate if (recsize > ulog->kdb_block) { 1697c478bd9Sstevel@tonic-gate if (retval = ulog_resize(ulog, ulogentries, ulogfd, recsize)) { 1707c478bd9Sstevel@tonic-gate /* Resize element array failed */ 1717c478bd9Sstevel@tonic-gate return (retval); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate cur_sno = ulog->kdb_last_sno; 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * We need to overflow our sno, replicas will do full 1797c478bd9Sstevel@tonic-gate * resyncs once they see their sno > than the masters. 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate if (cur_sno == ULONG_MAX) 1827c478bd9Sstevel@tonic-gate cur_sno = 1; 1837c478bd9Sstevel@tonic-gate else 1847c478bd9Sstevel@tonic-gate cur_sno++; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate /* 1877c478bd9Sstevel@tonic-gate * We squirrel this away for finish_update() to index 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate upd->kdb_entry_sno = cur_sno; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate i = (cur_sno - 1) % ulogentries; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate indx_log = (kdb_ent_header_t *)INDEX(ulog, i); 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate (void) memset(indx_log, 0, ulog->kdb_block); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate indx_log->kdb_umagic = KDB_UMAGIC; 1987c478bd9Sstevel@tonic-gate indx_log->kdb_entry_size = upd_size; 1997c478bd9Sstevel@tonic-gate indx_log->kdb_entry_sno = cur_sno; 2007c478bd9Sstevel@tonic-gate indx_log->kdb_time = upd->kdb_time = ktime; 2017c478bd9Sstevel@tonic-gate indx_log->kdb_commit = upd->kdb_commit = FALSE; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_UNSTABLE; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, (char *)indx_log->entry_data, 2067c478bd9Sstevel@tonic-gate indx_log->kdb_entry_size, XDR_ENCODE); 2077c478bd9Sstevel@tonic-gate if (!xdr_kdb_incr_update_t(&xdrs, upd)) 2087c478bd9Sstevel@tonic-gate return (KRB5_LOG_CONV); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate if (retval = ulog_sync_update(ulog, indx_log)) 2117c478bd9Sstevel@tonic-gate return (retval); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate if (ulog->kdb_num < ulogentries) 2147c478bd9Sstevel@tonic-gate ulog->kdb_num++; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate ulog->kdb_last_sno = cur_sno; 2177c478bd9Sstevel@tonic-gate ulog->kdb_last_time = ktime; 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * Since this is a circular array, once we circled, kdb_first_sno is 2217c478bd9Sstevel@tonic-gate * always kdb_entry_sno + 1. 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate if (cur_sno > ulogentries) { 2247c478bd9Sstevel@tonic-gate i = upd->kdb_entry_sno % ulogentries; 2257c478bd9Sstevel@tonic-gate indx_log = (kdb_ent_header_t *)INDEX(ulog, i); 2267c478bd9Sstevel@tonic-gate ulog->kdb_first_sno = indx_log->kdb_entry_sno; 2277c478bd9Sstevel@tonic-gate ulog->kdb_first_time = indx_log->kdb_time; 2287c478bd9Sstevel@tonic-gate } else if (cur_sno == 1) { 2297c478bd9Sstevel@tonic-gate ulog->kdb_first_sno = 1; 2307c478bd9Sstevel@tonic-gate ulog->kdb_first_time = indx_log->kdb_time; 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate ulog_sync_header(ulog); 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate return (0); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Mark the log entry as committed and sync the memory mapped log 2407c478bd9Sstevel@tonic-gate * to file. 2417c478bd9Sstevel@tonic-gate */ 2427c478bd9Sstevel@tonic-gate krb5_error_code 2437c478bd9Sstevel@tonic-gate ulog_finish_update(krb5_context context, kdb_incr_update_t *upd) 2447c478bd9Sstevel@tonic-gate { 2457c478bd9Sstevel@tonic-gate krb5_error_code retval; 2467c478bd9Sstevel@tonic-gate kdb_ent_header_t *indx_log; 2477c478bd9Sstevel@tonic-gate uint_t i; 2487c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 2497c478bd9Sstevel@tonic-gate kdb_hlog_t *ulog = NULL; 2507c478bd9Sstevel@tonic-gate uint32_t ulogentries; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate INIT_ULOG(context); 2537c478bd9Sstevel@tonic-gate ulogentries = log_ctx->ulogentries; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate i = (upd->kdb_entry_sno - 1) % ulogentries; 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate indx_log = (kdb_ent_header_t *)INDEX(ulog, i); 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate indx_log->kdb_commit = TRUE; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_STABLE; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (retval = ulog_sync_update(ulog, indx_log)) 2647c478bd9Sstevel@tonic-gate return (retval); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate ulog_sync_header(ulog); 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate return (0); 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* 2727c478bd9Sstevel@tonic-gate * Set the header log details on the slave and sync it to file. 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate void 2757c478bd9Sstevel@tonic-gate ulog_finish_update_slave(kdb_hlog_t *ulog, kdb_last_t lastentry) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate ulog->kdb_last_sno = lastentry.last_sno; 2797c478bd9Sstevel@tonic-gate ulog->kdb_last_time = lastentry.last_time; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate ulog_sync_header(ulog); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate /* 2857c478bd9Sstevel@tonic-gate * Delete an entry to the update log. 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate krb5_error_code 2887c478bd9Sstevel@tonic-gate ulog_delete_update(krb5_context context, kdb_incr_update_t *upd) 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate upd->kdb_deleted = TRUE; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate return (ulog_add_update(context, upd)); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * Used by the slave or master (during ulog_check) to update it's hash db from 2987c478bd9Sstevel@tonic-gate * the incr update log. 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate krb5_error_code 3017c478bd9Sstevel@tonic-gate ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret) 3027c478bd9Sstevel@tonic-gate { 3037c478bd9Sstevel@tonic-gate krb5_db_entry *entry = NULL; 3047c478bd9Sstevel@tonic-gate kdb_incr_update_t *upd = NULL, *fupd; 3057c478bd9Sstevel@tonic-gate int i, no_of_updates; 3067c478bd9Sstevel@tonic-gate krb5_error_code retval; 3077c478bd9Sstevel@tonic-gate krb5_principal dbprinc = NULL; 3087c478bd9Sstevel@tonic-gate kdb_last_t errlast; 3097c478bd9Sstevel@tonic-gate char *dbprincstr = NULL; 3107c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 3117c478bd9Sstevel@tonic-gate kdb_hlog_t *ulog = NULL; 312*67c90040Ssemery bool_t fini = FALSE; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate INIT_ULOG(context); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate no_of_updates = incr_ret->updates.kdb_ulog_t_len; 3177c478bd9Sstevel@tonic-gate upd = incr_ret->updates.kdb_ulog_t_val; 3187c478bd9Sstevel@tonic-gate fupd = upd; 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 32154925bf6Swillf * We reset last_sno and last_time to 0, if krb5_db_put_principal 32254925bf6Swillf * or krb5_db_delete_principal fail. 3237c478bd9Sstevel@tonic-gate */ 3247c478bd9Sstevel@tonic-gate errlast.last_sno = (unsigned int)0; 3257c478bd9Sstevel@tonic-gate errlast.last_time.seconds = (unsigned int)0; 3267c478bd9Sstevel@tonic-gate errlast.last_time.useconds = (unsigned int)0; 3277c478bd9Sstevel@tonic-gate 328*67c90040Ssemery if (krb5_db_inited(context)) { 329*67c90040Ssemery retval = krb5_db_open(context, NULL, 330*67c90040Ssemery KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN); 331*67c90040Ssemery if (retval != 0) 3327c478bd9Sstevel@tonic-gate goto cleanup; 333*67c90040Ssemery fini = TRUE; 334*67c90040Ssemery } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate for (i = 0; i < no_of_updates; i++) { 3377c478bd9Sstevel@tonic-gate int nentry = 1; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate if (!upd->kdb_commit) 3407c478bd9Sstevel@tonic-gate continue; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate if (upd->kdb_deleted) { 3437c478bd9Sstevel@tonic-gate dbprincstr = malloc((upd->kdb_princ_name.utf8str_t_len 3447c478bd9Sstevel@tonic-gate + 1) * sizeof (char)); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate if (dbprincstr == NULL) { 3477c478bd9Sstevel@tonic-gate retval = ENOMEM; 3487c478bd9Sstevel@tonic-gate goto cleanup; 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate (void) strlcpy(dbprincstr, 3527c478bd9Sstevel@tonic-gate (char *)upd->kdb_princ_name.utf8str_t_val, 3537c478bd9Sstevel@tonic-gate (upd->kdb_princ_name.utf8str_t_len + 1)); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate if (retval = krb5_parse_name(context, dbprincstr, 3567c478bd9Sstevel@tonic-gate &dbprinc)) { 3577c478bd9Sstevel@tonic-gate goto cleanup; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if (dbprincstr) 3617c478bd9Sstevel@tonic-gate free(dbprincstr); 3627c478bd9Sstevel@tonic-gate 36354925bf6Swillf retval = krb5_db_delete_principal(context, 3647c478bd9Sstevel@tonic-gate dbprinc, &nentry); 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if (dbprinc) 3677c478bd9Sstevel@tonic-gate krb5_free_principal(context, dbprinc); 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate if (retval) 3707c478bd9Sstevel@tonic-gate goto cleanup; 3717c478bd9Sstevel@tonic-gate } else { 3727c478bd9Sstevel@tonic-gate entry = (krb5_db_entry *)malloc(sizeof (krb5_db_entry)); 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate if (!entry) { 3757c478bd9Sstevel@tonic-gate retval = errno; 3767c478bd9Sstevel@tonic-gate goto cleanup; 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate (void) memset(entry, 0, sizeof (krb5_db_entry)); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate if (retval = ulog_conv_2dbentry(context, entry, upd, 1)) 3827c478bd9Sstevel@tonic-gate goto cleanup; 3837c478bd9Sstevel@tonic-gate 38454925bf6Swillf retval = krb5_db_put_principal(context, entry, 3857c478bd9Sstevel@tonic-gate &nentry); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate if (entry) { 3887c478bd9Sstevel@tonic-gate krb5_db_free_principal(context, entry, nentry); 3897c478bd9Sstevel@tonic-gate free(entry); 3907c478bd9Sstevel@tonic-gate entry = NULL; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate if (retval) 3937c478bd9Sstevel@tonic-gate goto cleanup; 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate upd++; 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate cleanup: 4007c478bd9Sstevel@tonic-gate if (fupd) 4017c478bd9Sstevel@tonic-gate ulog_free_entries(fupd, no_of_updates); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) { 4047c478bd9Sstevel@tonic-gate if (retval) 4057c478bd9Sstevel@tonic-gate ulog_finish_update_slave(ulog, errlast); 4067c478bd9Sstevel@tonic-gate else 4077c478bd9Sstevel@tonic-gate ulog_finish_update_slave(ulog, incr_ret->lastentry); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 410*67c90040Ssemery if (fini == TRUE) 411*67c90040Ssemery krb5_db_fini(context); 412*67c90040Ssemery 4137c478bd9Sstevel@tonic-gate return (retval); 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* 4177c478bd9Sstevel@tonic-gate * Validate the log file and resync any uncommitted update entries 4187c478bd9Sstevel@tonic-gate * to the principal database. 4197c478bd9Sstevel@tonic-gate */ 4207c478bd9Sstevel@tonic-gate krb5_error_code 4217c478bd9Sstevel@tonic-gate ulog_check(krb5_context context, kdb_hlog_t *ulog) 4227c478bd9Sstevel@tonic-gate { 4237c478bd9Sstevel@tonic-gate XDR xdrs; 4247c478bd9Sstevel@tonic-gate krb5_error_code retval = 0; 4257c478bd9Sstevel@tonic-gate int i; 4267c478bd9Sstevel@tonic-gate kdb_ent_header_t *indx_log; 4277c478bd9Sstevel@tonic-gate kdb_incr_update_t *upd = NULL; 4287c478bd9Sstevel@tonic-gate kdb_incr_result_t *incr_ret = NULL; 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_STABLE; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate for (i = 0; i < ulog->kdb_num; i++) { 4337c478bd9Sstevel@tonic-gate indx_log = (kdb_ent_header_t *)INDEX(ulog, i); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate if (indx_log->kdb_umagic != KDB_UMAGIC) { 4367c478bd9Sstevel@tonic-gate /* 4377c478bd9Sstevel@tonic-gate * Update entry corrupted we should scream and die 4387c478bd9Sstevel@tonic-gate */ 4397c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_CORRUPT; 4407c478bd9Sstevel@tonic-gate retval = KRB5_LOG_CORRUPT; 4417c478bd9Sstevel@tonic-gate break; 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate if (indx_log->kdb_commit == FALSE) { 4457c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_UNSTABLE; 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate incr_ret = (kdb_incr_result_t *) 4487c478bd9Sstevel@tonic-gate malloc(sizeof (kdb_incr_result_t)); 4497c478bd9Sstevel@tonic-gate if (incr_ret == NULL) { 4507c478bd9Sstevel@tonic-gate retval = errno; 4517c478bd9Sstevel@tonic-gate goto error; 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate upd = (kdb_incr_update_t *) 4557c478bd9Sstevel@tonic-gate malloc(sizeof (kdb_incr_update_t)); 4567c478bd9Sstevel@tonic-gate if (upd == NULL) { 4577c478bd9Sstevel@tonic-gate retval = errno; 4587c478bd9Sstevel@tonic-gate goto error; 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate (void) memset(upd, 0, sizeof (kdb_incr_update_t)); 4627c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, (char *)indx_log->entry_data, 4637c478bd9Sstevel@tonic-gate indx_log->kdb_entry_size, XDR_DECODE); 4647c478bd9Sstevel@tonic-gate if (!xdr_kdb_incr_update_t(&xdrs, upd)) { 4657c478bd9Sstevel@tonic-gate retval = KRB5_LOG_CONV; 4667c478bd9Sstevel@tonic-gate goto error; 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate incr_ret->updates.kdb_ulog_t_len = 1; 4707c478bd9Sstevel@tonic-gate incr_ret->updates.kdb_ulog_t_val = upd; 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate upd->kdb_commit = TRUE; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4757c478bd9Sstevel@tonic-gate * We don't want to readd this update and just use the 4767c478bd9Sstevel@tonic-gate * existing update to be propagated later on 4777c478bd9Sstevel@tonic-gate */ 4787c478bd9Sstevel@tonic-gate ulog_set_role(context, IPROP_NULL); 4797c478bd9Sstevel@tonic-gate retval = ulog_replay(context, incr_ret); 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * upd was freed by ulog_replay, we NULL 4837c478bd9Sstevel@tonic-gate * the pointer in case we subsequently break from loop. 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate upd = NULL; 4867c478bd9Sstevel@tonic-gate if (incr_ret) { 4877c478bd9Sstevel@tonic-gate free(incr_ret); 4887c478bd9Sstevel@tonic-gate incr_ret = NULL; 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate ulog_set_role(context, IPROP_MASTER); 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate if (retval) 4937c478bd9Sstevel@tonic-gate goto error; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * We flag this as committed since this was 4977c478bd9Sstevel@tonic-gate * the last entry before kadmind crashed, ergo 4987c478bd9Sstevel@tonic-gate * the slaves have not seen this update before 4997c478bd9Sstevel@tonic-gate */ 5007c478bd9Sstevel@tonic-gate indx_log->kdb_commit = TRUE; 5017c478bd9Sstevel@tonic-gate retval = ulog_sync_update(ulog, indx_log); 5027c478bd9Sstevel@tonic-gate if (retval) 5037c478bd9Sstevel@tonic-gate goto error; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_STABLE; 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate error: 5107c478bd9Sstevel@tonic-gate if (upd) 5117c478bd9Sstevel@tonic-gate ulog_free_entries(upd, 1); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate if (incr_ret) 5147c478bd9Sstevel@tonic-gate free(incr_ret); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate ulog_sync_header(ulog); 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate return (retval); 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate /* 5227c478bd9Sstevel@tonic-gate * Map the log file to memory for performance and simplicity. 5237c478bd9Sstevel@tonic-gate * 5247c478bd9Sstevel@tonic-gate * Called by: if iprop_enabled then ulog_map(); 5257c478bd9Sstevel@tonic-gate * Assumes that the caller will terminate on ulog_map, hence munmap and 5267c478bd9Sstevel@tonic-gate * closing of the fd are implicitly performed by the caller. 5277c478bd9Sstevel@tonic-gate * Returns 0 on success else failure. 5287c478bd9Sstevel@tonic-gate */ 5297c478bd9Sstevel@tonic-gate krb5_error_code 5307c478bd9Sstevel@tonic-gate ulog_map(krb5_context context, kadm5_config_params *params, int caller) 5317c478bd9Sstevel@tonic-gate { 5327c478bd9Sstevel@tonic-gate struct stat st; 5337c478bd9Sstevel@tonic-gate krb5_error_code retval; 5347c478bd9Sstevel@tonic-gate uint32_t ulog_filesize; 5357c478bd9Sstevel@tonic-gate char logname[MAX_FILENAME]; 5367c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 5377c478bd9Sstevel@tonic-gate kdb_hlog_t *ulog = NULL; 5387c478bd9Sstevel@tonic-gate uint32_t ulogentries; 5397c478bd9Sstevel@tonic-gate int ulogfd = -1; 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if ((caller == FKADMIND) || (caller == FKCOMMAND)) 5427c478bd9Sstevel@tonic-gate ulogentries = params->iprop_ulogsize; 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate ulog_filesize = sizeof (kdb_hlog_t); 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate if (strlcpy(logname, params->dbname, MAX_FILENAME) >= MAX_FILENAME) 5477c478bd9Sstevel@tonic-gate return (KRB5_LOG_ERROR); 5487c478bd9Sstevel@tonic-gate if (strlcat(logname, ".ulog", MAX_FILENAME) >= MAX_FILENAME) 5497c478bd9Sstevel@tonic-gate return (KRB5_LOG_ERROR); 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if (stat(logname, &st) == -1) { 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate if (caller == FKPROPLOG) { 5547c478bd9Sstevel@tonic-gate /* 5557c478bd9Sstevel@tonic-gate * File doesn't exist so we exit with kproplog 5567c478bd9Sstevel@tonic-gate */ 5577c478bd9Sstevel@tonic-gate return (errno); 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate if ((ulogfd = open(logname, O_RDWR+O_CREAT, 0600)) == -1) { 5617c478bd9Sstevel@tonic-gate return (errno); 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate if (lseek(ulogfd, 0L, SEEK_CUR) == -1) { 5657c478bd9Sstevel@tonic-gate return (errno); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate if ((caller == FKADMIND) || (caller == FKCOMMAND)) 5697c478bd9Sstevel@tonic-gate ulog_filesize += ulogentries * ULOG_BLOCK; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate if (lseek(ulogfd, ulog_filesize, SEEK_SET) == -1) { 5727c478bd9Sstevel@tonic-gate return (errno); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate if (write(ulogfd, "+", 1) != 1) { 5767c478bd9Sstevel@tonic-gate return (errno); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate } else { 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate if ((ulogfd = open(logname, O_RDWR, 0600)) == -1) { 5827c478bd9Sstevel@tonic-gate /* 5837c478bd9Sstevel@tonic-gate * Can't open existing log file 5847c478bd9Sstevel@tonic-gate */ 5857c478bd9Sstevel@tonic-gate return (errno); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate if (caller == FKPROPLOG) { 5907c478bd9Sstevel@tonic-gate fstat(ulogfd, &st); 5917c478bd9Sstevel@tonic-gate ulog_filesize = st.st_size; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate ulog = (kdb_hlog_t *)mmap(0, ulog_filesize, 5947c478bd9Sstevel@tonic-gate PROT_READ+PROT_WRITE, MAP_PRIVATE, ulogfd, 0); 5957c478bd9Sstevel@tonic-gate } else { 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * else kadmind, kpropd, & kcommands should udpate stores 5987c478bd9Sstevel@tonic-gate */ 5997c478bd9Sstevel@tonic-gate ulog = (kdb_hlog_t *)mmap(0, MAXLOGLEN, 6007c478bd9Sstevel@tonic-gate PROT_READ+PROT_WRITE, MAP_SHARED, ulogfd, 0); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if ((int)(ulog) == -1) { 6047c478bd9Sstevel@tonic-gate /* 6057c478bd9Sstevel@tonic-gate * Can't map update log file to memory 6067c478bd9Sstevel@tonic-gate */ 6077c478bd9Sstevel@tonic-gate return (errno); 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate if (!context->kdblog_context) { 6117c478bd9Sstevel@tonic-gate if (!(log_ctx = malloc(sizeof (kdb_log_context)))) 6127c478bd9Sstevel@tonic-gate return (errno); 6137c478bd9Sstevel@tonic-gate context->kdblog_context = (void *)log_ctx; 6147c478bd9Sstevel@tonic-gate } else 6157c478bd9Sstevel@tonic-gate log_ctx = context->kdblog_context; 6167c478bd9Sstevel@tonic-gate log_ctx->ulog = ulog; 6177c478bd9Sstevel@tonic-gate log_ctx->ulogentries = ulogentries; 6187c478bd9Sstevel@tonic-gate log_ctx->ulogfd = ulogfd; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if (ulog->kdb_hmagic != KDB_HMAGIC) { 6217c478bd9Sstevel@tonic-gate if (ulog->kdb_hmagic == 0) { 6227c478bd9Sstevel@tonic-gate /* 6237c478bd9Sstevel@tonic-gate * New update log 6247c478bd9Sstevel@tonic-gate */ 6257c478bd9Sstevel@tonic-gate (void) memset(ulog, 0, sizeof (kdb_hlog_t)); 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate ulog->kdb_hmagic = KDB_HMAGIC; 6287c478bd9Sstevel@tonic-gate ulog->db_version_num = KDB_VERSION; 6297c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_STABLE; 6307c478bd9Sstevel@tonic-gate ulog->kdb_block = ULOG_BLOCK; 6317c478bd9Sstevel@tonic-gate if (!(caller == FKPROPLOG)) 6327c478bd9Sstevel@tonic-gate ulog_sync_header(ulog); 6337c478bd9Sstevel@tonic-gate } else { 6347c478bd9Sstevel@tonic-gate return (KRB5_LOG_CORRUPT); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate if (caller == FKADMIND) { 6397c478bd9Sstevel@tonic-gate switch (ulog->kdb_state) { 6407c478bd9Sstevel@tonic-gate case KDB_STABLE: 6417c478bd9Sstevel@tonic-gate case KDB_UNSTABLE: 6427c478bd9Sstevel@tonic-gate /* 6437c478bd9Sstevel@tonic-gate * Log is currently un/stable, check anyway 6447c478bd9Sstevel@tonic-gate */ 6457c478bd9Sstevel@tonic-gate retval = ulog_check(context, ulog); 6467c478bd9Sstevel@tonic-gate if (retval == KRB5_LOG_CORRUPT) { 6477c478bd9Sstevel@tonic-gate return (retval); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate break; 6507c478bd9Sstevel@tonic-gate case KDB_CORRUPT: 6517c478bd9Sstevel@tonic-gate return (KRB5_LOG_CORRUPT); 6527c478bd9Sstevel@tonic-gate default: 6537c478bd9Sstevel@tonic-gate /* 6547c478bd9Sstevel@tonic-gate * Invalid db state 6557c478bd9Sstevel@tonic-gate */ 6567c478bd9Sstevel@tonic-gate return (KRB5_LOG_ERROR); 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate } else if ((caller == FKPROPLOG) || (caller == FKPROPD)) { 6597c478bd9Sstevel@tonic-gate /* 6607c478bd9Sstevel@tonic-gate * kproplog and kpropd don't need to do anything else 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate return (0); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* 6667c478bd9Sstevel@tonic-gate * Reinit ulog if the log is being truncated or expanded after 6677c478bd9Sstevel@tonic-gate * we have circled. 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate if (ulog->kdb_num != ulogentries) { 6707c478bd9Sstevel@tonic-gate if ((ulog->kdb_num != 0) && 6717c478bd9Sstevel@tonic-gate ((ulog->kdb_last_sno > ulog->kdb_num) || 6727c478bd9Sstevel@tonic-gate (ulog->kdb_num > ulogentries))) { 6737c478bd9Sstevel@tonic-gate (void) memset(ulog, 0, sizeof (kdb_hlog_t)); 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate ulog->kdb_hmagic = KDB_HMAGIC; 6767c478bd9Sstevel@tonic-gate ulog->db_version_num = KDB_VERSION; 6777c478bd9Sstevel@tonic-gate ulog->kdb_state = KDB_STABLE; 6787c478bd9Sstevel@tonic-gate ulog->kdb_block = ULOG_BLOCK; 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate ulog_sync_header(ulog); 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate /* 6847c478bd9Sstevel@tonic-gate * Expand ulog if we have specified a greater size 6857c478bd9Sstevel@tonic-gate */ 6867c478bd9Sstevel@tonic-gate if (ulog->kdb_num < ulogentries) { 6877c478bd9Sstevel@tonic-gate ulog_filesize += ulogentries * ulog->kdb_block; 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (lseek(ulogfd, ulog_filesize, SEEK_SET) == -1) { 6907c478bd9Sstevel@tonic-gate return (errno); 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate if (write(ulogfd, "+", 1) != 1) { 6947c478bd9Sstevel@tonic-gate return (errno); 6957c478bd9Sstevel@tonic-gate } 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate return (0); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* 7037c478bd9Sstevel@tonic-gate * Get the last set of updates seen, (last+1) to n is returned. 7047c478bd9Sstevel@tonic-gate */ 7057c478bd9Sstevel@tonic-gate krb5_error_code 7067c478bd9Sstevel@tonic-gate ulog_get_entries( 7077c478bd9Sstevel@tonic-gate krb5_context context, /* input - krb5 lib config */ 7087c478bd9Sstevel@tonic-gate kdb_last_t last, /* input - slave's last sno */ 7097c478bd9Sstevel@tonic-gate kdb_incr_result_t *ulog_handle) /* output - incr result for slave */ 7107c478bd9Sstevel@tonic-gate { 7117c478bd9Sstevel@tonic-gate XDR xdrs; 7127c478bd9Sstevel@tonic-gate kdb_ent_header_t *indx_log; 7137c478bd9Sstevel@tonic-gate kdb_incr_update_t *upd; 7147c478bd9Sstevel@tonic-gate uint_t indx, count, tdiff; 7157c478bd9Sstevel@tonic-gate uint32_t sno; 7167c478bd9Sstevel@tonic-gate krb5_error_code retval; 7177c478bd9Sstevel@tonic-gate struct timeval timestamp; 7187c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 7197c478bd9Sstevel@tonic-gate kdb_hlog_t *ulog = NULL; 7207c478bd9Sstevel@tonic-gate uint32_t ulogentries; 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate INIT_ULOG(context); 7237c478bd9Sstevel@tonic-gate ulogentries = log_ctx->ulogentries; 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate /* 7267c478bd9Sstevel@tonic-gate * Check to make sure we don't have a corrupt ulog first. 7277c478bd9Sstevel@tonic-gate */ 7287c478bd9Sstevel@tonic-gate if (ulog->kdb_state == KDB_CORRUPT) { 7297c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_ERROR; 7307c478bd9Sstevel@tonic-gate return (KRB5_LOG_CORRUPT); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate gettimeofday(×tamp, NULL); 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate tdiff = timestamp.tv_sec - ulog->kdb_last_time.seconds; 7367c478bd9Sstevel@tonic-gate if (tdiff <= ULOG_IDLE_TIME) { 7377c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_BUSY; 7387c478bd9Sstevel@tonic-gate return (0); 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate /* 7427c478bd9Sstevel@tonic-gate * We need to lock out other processes here, such as kadmin.local, 7437c478bd9Sstevel@tonic-gate * since we are looking at the last_sno and looking up updates. So 7447c478bd9Sstevel@tonic-gate * we can share with other readers. 7457c478bd9Sstevel@tonic-gate */ 7467c478bd9Sstevel@tonic-gate retval = krb5_db_lock(context, KRB5_LOCKMODE_SHARED); 7477c478bd9Sstevel@tonic-gate if (retval) 7487c478bd9Sstevel@tonic-gate return (retval); 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate /* 7517c478bd9Sstevel@tonic-gate * We may have overflowed the update log or we shrunk the log, or 7527c478bd9Sstevel@tonic-gate * the client's ulog has just been created. 7537c478bd9Sstevel@tonic-gate */ 7547c478bd9Sstevel@tonic-gate if ((last.last_sno > ulog->kdb_last_sno) || 7557c478bd9Sstevel@tonic-gate (last.last_sno < ulog->kdb_first_sno) || 7567c478bd9Sstevel@tonic-gate (last.last_sno == 0)) { 7577c478bd9Sstevel@tonic-gate ulog_handle->lastentry.last_sno = ulog->kdb_last_sno; 7587c478bd9Sstevel@tonic-gate (void) krb5_db_unlock(context); 7597c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_FULL_RESYNC_NEEDED; 7607c478bd9Sstevel@tonic-gate return (0); 7617c478bd9Sstevel@tonic-gate } else if (last.last_sno <= ulog->kdb_last_sno) { 7627c478bd9Sstevel@tonic-gate sno = last.last_sno; 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate indx = (sno - 1) % ulogentries; 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate indx_log = (kdb_ent_header_t *)INDEX(ulog, indx); 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate /* 7697c478bd9Sstevel@tonic-gate * Validate the time stamp just to make sure it was the same sno 7707c478bd9Sstevel@tonic-gate */ 7717c478bd9Sstevel@tonic-gate if ((indx_log->kdb_time.seconds == last.last_time.seconds) && 7727c478bd9Sstevel@tonic-gate (indx_log->kdb_time.useconds == last.last_time.useconds)) { 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate /* 7757c478bd9Sstevel@tonic-gate * If we have the same sno we return success 7767c478bd9Sstevel@tonic-gate */ 7777c478bd9Sstevel@tonic-gate if (last.last_sno == ulog->kdb_last_sno) { 7787c478bd9Sstevel@tonic-gate (void) krb5_db_unlock(context); 7797c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_NIL; 7807c478bd9Sstevel@tonic-gate return (0); 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate count = ulog->kdb_last_sno - sno; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate ulog_handle->updates.kdb_ulog_t_val = 7867c478bd9Sstevel@tonic-gate (kdb_incr_update_t *)malloc( 7877c478bd9Sstevel@tonic-gate sizeof (kdb_incr_update_t) * count); 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate upd = ulog_handle->updates.kdb_ulog_t_val; 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate if (upd == NULL) { 7927c478bd9Sstevel@tonic-gate (void) krb5_db_unlock(context); 7937c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_ERROR; 7947c478bd9Sstevel@tonic-gate return (errno); 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate while (sno < ulog->kdb_last_sno) { 7987c478bd9Sstevel@tonic-gate indx = sno % ulogentries; 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate indx_log = (kdb_ent_header_t *) 8017c478bd9Sstevel@tonic-gate INDEX(ulog, indx); 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate (void) memset(upd, 0, 8047c478bd9Sstevel@tonic-gate sizeof (kdb_incr_update_t)); 8057c478bd9Sstevel@tonic-gate xdrmem_create(&xdrs, 8067c478bd9Sstevel@tonic-gate (char *)indx_log->entry_data, 8077c478bd9Sstevel@tonic-gate indx_log->kdb_entry_size, XDR_DECODE); 8087c478bd9Sstevel@tonic-gate if (!xdr_kdb_incr_update_t(&xdrs, upd)) { 8097c478bd9Sstevel@tonic-gate (void) krb5_db_unlock(context); 8107c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_ERROR; 8117c478bd9Sstevel@tonic-gate return (KRB5_LOG_CONV); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate /* 8147c478bd9Sstevel@tonic-gate * Mark commitment since we didn't 8157c478bd9Sstevel@tonic-gate * want to decode and encode the 8167c478bd9Sstevel@tonic-gate * incr update record the first time. 8177c478bd9Sstevel@tonic-gate */ 8187c478bd9Sstevel@tonic-gate upd->kdb_commit = indx_log->kdb_commit; 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate upd++; 8217c478bd9Sstevel@tonic-gate sno++; 8227c478bd9Sstevel@tonic-gate } /* while */ 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate ulog_handle->updates.kdb_ulog_t_len = count; 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate ulog_handle->lastentry.last_sno = ulog->kdb_last_sno; 8277c478bd9Sstevel@tonic-gate ulog_handle->lastentry.last_time.seconds = 8287c478bd9Sstevel@tonic-gate ulog->kdb_last_time.seconds; 8297c478bd9Sstevel@tonic-gate ulog_handle->lastentry.last_time.useconds = 8307c478bd9Sstevel@tonic-gate ulog->kdb_last_time.useconds; 8317c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_OK; 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate (void) krb5_db_unlock(context); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate return (0); 8367c478bd9Sstevel@tonic-gate } else { 8377c478bd9Sstevel@tonic-gate /* 8387c478bd9Sstevel@tonic-gate * We have time stamp mismatch or we no longer have 8397c478bd9Sstevel@tonic-gate * the slave's last sno, so we brute force it 8407c478bd9Sstevel@tonic-gate */ 8417c478bd9Sstevel@tonic-gate (void) krb5_db_unlock(context); 8427c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_FULL_RESYNC_NEEDED; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate return (0); 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate /* 8497c478bd9Sstevel@tonic-gate * Should never get here, return error 8507c478bd9Sstevel@tonic-gate */ 8517c478bd9Sstevel@tonic-gate ulog_handle->ret = UPDATE_ERROR; 8527c478bd9Sstevel@tonic-gate return (KRB5_LOG_ERROR); 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate krb5_error_code 8567c478bd9Sstevel@tonic-gate ulog_set_role(krb5_context ctx, iprop_role role) 8577c478bd9Sstevel@tonic-gate { 8587c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate if (!ctx->kdblog_context) { 8617c478bd9Sstevel@tonic-gate if (!(log_ctx = malloc(sizeof (kdb_log_context)))) 8627c478bd9Sstevel@tonic-gate return (errno); 8637c478bd9Sstevel@tonic-gate ctx->kdblog_context = (void *)log_ctx; 8647c478bd9Sstevel@tonic-gate } else 8657c478bd9Sstevel@tonic-gate log_ctx = ctx->kdblog_context; 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate log_ctx->iproprole = role; 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate return (0); 8707c478bd9Sstevel@tonic-gate } 871