1b528cefcSMark Murray /* 2*8373020dSJacques Vidrine * Copyright (c) 1997 - 2002 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 "kadm5_locl.h" 35b528cefcSMark Murray 36*8373020dSJacques Vidrine RCSID("$Id: log.c,v 1.19 2002/05/24 15:19:21 joda Exp $"); 37b528cefcSMark Murray 38b528cefcSMark Murray /* 39b528cefcSMark Murray * A log record consists of: 40b528cefcSMark Murray * 41b528cefcSMark Murray * version number 4 bytes 42b528cefcSMark Murray * time in seconds 4 bytes 43b528cefcSMark Murray * operation (enum kadm_ops) 4 bytes 44b528cefcSMark Murray * length of record 4 bytes 45b528cefcSMark Murray * data... n bytes 46b528cefcSMark Murray * length of record 4 bytes 47b528cefcSMark Murray * version number 4 bytes 48b528cefcSMark Murray * 49b528cefcSMark Murray */ 50b528cefcSMark Murray 51b528cefcSMark Murray kadm5_ret_t 525e9cd1aeSAssar Westerlund kadm5_log_get_version_fd (int fd, 53b528cefcSMark Murray u_int32_t *ver) 54b528cefcSMark Murray { 55b528cefcSMark Murray int ret; 56b528cefcSMark Murray krb5_storage *sp; 57b528cefcSMark Murray int32_t old_version; 58b528cefcSMark Murray 59b528cefcSMark Murray ret = lseek (fd, 0, SEEK_END); 60b528cefcSMark Murray if(ret < 0) 61b528cefcSMark Murray return errno; 62b528cefcSMark Murray if(ret == 0) { 63b528cefcSMark Murray *ver = 0; 64b528cefcSMark Murray return 0; 65b528cefcSMark Murray } 66b528cefcSMark Murray sp = krb5_storage_from_fd (fd); 67*8373020dSJacques Vidrine krb5_storage_seek(sp, -4, SEEK_CUR); 68b528cefcSMark Murray krb5_ret_int32 (sp, &old_version); 69b528cefcSMark Murray *ver = old_version; 70b528cefcSMark Murray krb5_storage_free(sp); 71b528cefcSMark Murray lseek (fd, 0, SEEK_END); 72b528cefcSMark Murray return 0; 73b528cefcSMark Murray } 74b528cefcSMark Murray 75b528cefcSMark Murray kadm5_ret_t 765e9cd1aeSAssar Westerlund kadm5_log_get_version (kadm5_server_context *context, u_int32_t *ver) 775e9cd1aeSAssar Westerlund { 785e9cd1aeSAssar Westerlund return kadm5_log_get_version_fd (context->log_context.log_fd, ver); 795e9cd1aeSAssar Westerlund } 805e9cd1aeSAssar Westerlund 815e9cd1aeSAssar Westerlund kadm5_ret_t 825e9cd1aeSAssar Westerlund kadm5_log_set_version (kadm5_server_context *context, u_int32_t vno) 835e9cd1aeSAssar Westerlund { 845e9cd1aeSAssar Westerlund kadm5_log_context *log_context = &context->log_context; 855e9cd1aeSAssar Westerlund 865e9cd1aeSAssar Westerlund log_context->version = vno; 875e9cd1aeSAssar Westerlund return 0; 885e9cd1aeSAssar Westerlund } 895e9cd1aeSAssar Westerlund 905e9cd1aeSAssar Westerlund kadm5_ret_t 91b528cefcSMark Murray kadm5_log_init (kadm5_server_context *context) 92b528cefcSMark Murray { 93b528cefcSMark Murray int fd; 94b528cefcSMark Murray kadm5_ret_t ret; 95b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context; 96b528cefcSMark Murray 97b528cefcSMark Murray if (log_context->log_fd != -1) 98b528cefcSMark Murray return 0; 99b528cefcSMark Murray fd = open (log_context->log_file, O_RDWR | O_CREAT, 0600); 100b528cefcSMark Murray if (fd < 0) 101b528cefcSMark Murray return errno; 102b528cefcSMark Murray if (flock (fd, LOCK_EX) < 0) { 103b528cefcSMark Murray close (fd); 104b528cefcSMark Murray return errno; 105b528cefcSMark Murray } 106b528cefcSMark Murray 1075e9cd1aeSAssar Westerlund ret = kadm5_log_get_version_fd (fd, &log_context->version); 108b528cefcSMark Murray if (ret) 109b528cefcSMark Murray return ret; 110b528cefcSMark Murray 111b528cefcSMark Murray log_context->log_fd = fd; 112b528cefcSMark Murray return 0; 113b528cefcSMark Murray } 114b528cefcSMark Murray 115b528cefcSMark Murray kadm5_ret_t 1165e9cd1aeSAssar Westerlund kadm5_log_reinit (kadm5_server_context *context) 1175e9cd1aeSAssar Westerlund { 1185e9cd1aeSAssar Westerlund int fd; 1195e9cd1aeSAssar Westerlund kadm5_log_context *log_context = &context->log_context; 1205e9cd1aeSAssar Westerlund 1215e9cd1aeSAssar Westerlund if (log_context->log_fd != -1) { 1225e9cd1aeSAssar Westerlund close (log_context->log_fd); 1235e9cd1aeSAssar Westerlund log_context->log_fd = -1; 1245e9cd1aeSAssar Westerlund } 1255e9cd1aeSAssar Westerlund fd = open (log_context->log_file, O_RDWR | O_CREAT | O_TRUNC, 0600); 1265e9cd1aeSAssar Westerlund if (fd < 0) 1275e9cd1aeSAssar Westerlund return errno; 1285e9cd1aeSAssar Westerlund if (flock (fd, LOCK_EX) < 0) { 1295e9cd1aeSAssar Westerlund close (fd); 1305e9cd1aeSAssar Westerlund return errno; 1315e9cd1aeSAssar Westerlund } 1325e9cd1aeSAssar Westerlund 1335e9cd1aeSAssar Westerlund log_context->version = 0; 1345e9cd1aeSAssar Westerlund log_context->log_fd = fd; 1355e9cd1aeSAssar Westerlund return 0; 1365e9cd1aeSAssar Westerlund } 1375e9cd1aeSAssar Westerlund 1385e9cd1aeSAssar Westerlund 1395e9cd1aeSAssar Westerlund kadm5_ret_t 140b528cefcSMark Murray kadm5_log_end (kadm5_server_context *context) 141b528cefcSMark Murray { 142b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context; 143b528cefcSMark Murray int fd = log_context->log_fd; 144b528cefcSMark Murray 145b528cefcSMark Murray flock (fd, LOCK_UN); 146b528cefcSMark Murray close(fd); 147b528cefcSMark Murray log_context->log_fd = -1; 148b528cefcSMark Murray return 0; 149b528cefcSMark Murray } 150b528cefcSMark Murray 151b528cefcSMark Murray static kadm5_ret_t 152b528cefcSMark Murray kadm5_log_preamble (kadm5_server_context *context, 153b528cefcSMark Murray krb5_storage *sp, 154b528cefcSMark Murray enum kadm_ops op) 155b528cefcSMark Murray { 156b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context; 157b528cefcSMark Murray kadm5_ret_t kadm_ret; 158b528cefcSMark Murray 159b528cefcSMark Murray kadm_ret = kadm5_log_init (context); 160b528cefcSMark Murray if (kadm_ret) 161b528cefcSMark Murray return kadm_ret; 162b528cefcSMark Murray 163b528cefcSMark Murray krb5_store_int32 (sp, ++log_context->version); 164b528cefcSMark Murray krb5_store_int32 (sp, time(NULL)); 165b528cefcSMark Murray krb5_store_int32 (sp, op); 166b528cefcSMark Murray return 0; 167b528cefcSMark Murray } 168b528cefcSMark Murray 169b528cefcSMark Murray static kadm5_ret_t 170b528cefcSMark Murray kadm5_log_postamble (kadm5_log_context *context, 171b528cefcSMark Murray krb5_storage *sp) 172b528cefcSMark Murray { 173b528cefcSMark Murray krb5_store_int32 (sp, context->version); 174b528cefcSMark Murray return 0; 175b528cefcSMark Murray } 176b528cefcSMark Murray 177b528cefcSMark Murray /* 178b528cefcSMark Murray * flush the log record in `sp'. 179b528cefcSMark Murray */ 180b528cefcSMark Murray 181b528cefcSMark Murray static kadm5_ret_t 182b528cefcSMark Murray kadm5_log_flush (kadm5_log_context *log_context, 183b528cefcSMark Murray krb5_storage *sp) 184b528cefcSMark Murray { 185b528cefcSMark Murray krb5_data data; 186b528cefcSMark Murray size_t len; 187b528cefcSMark Murray int ret; 188b528cefcSMark Murray 189b528cefcSMark Murray krb5_storage_to_data(sp, &data); 190b528cefcSMark Murray len = data.length; 191b528cefcSMark Murray ret = write (log_context->log_fd, data.data, len); 192b528cefcSMark Murray if (ret != len) { 193b528cefcSMark Murray krb5_data_free(&data); 194b528cefcSMark Murray return errno; 195b528cefcSMark Murray } 196b528cefcSMark Murray if (fsync (log_context->log_fd) < 0) { 197b528cefcSMark Murray krb5_data_free(&data); 198b528cefcSMark Murray return errno; 199b528cefcSMark Murray } 200b528cefcSMark Murray /* 201b528cefcSMark Murray * Try to send a signal to any running `ipropd-master' 202b528cefcSMark Murray */ 203b528cefcSMark Murray sendto (log_context->socket_fd, 204b528cefcSMark Murray (void *)&log_context->version, 205b528cefcSMark Murray sizeof(log_context->version), 206b528cefcSMark Murray 0, 207b528cefcSMark Murray (struct sockaddr *)&log_context->socket_name, 208b528cefcSMark Murray sizeof(log_context->socket_name)); 209b528cefcSMark Murray 210b528cefcSMark Murray krb5_data_free(&data); 211b528cefcSMark Murray return 0; 212b528cefcSMark Murray } 213b528cefcSMark Murray 214b528cefcSMark Murray /* 215b528cefcSMark Murray * Add a `create' operation to the log. 216b528cefcSMark Murray */ 217b528cefcSMark Murray 218b528cefcSMark Murray kadm5_ret_t 219b528cefcSMark Murray kadm5_log_create (kadm5_server_context *context, 220b528cefcSMark Murray hdb_entry *ent) 221b528cefcSMark Murray { 222b528cefcSMark Murray krb5_storage *sp; 223b528cefcSMark Murray kadm5_ret_t ret; 224b528cefcSMark Murray krb5_data value; 225b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context; 226b528cefcSMark Murray 227b528cefcSMark Murray sp = krb5_storage_emem(); 228b528cefcSMark Murray ret = hdb_entry2value (context->context, ent, &value); 229b528cefcSMark Murray if (ret) { 230b528cefcSMark Murray krb5_storage_free(sp); 231b528cefcSMark Murray return ret; 232b528cefcSMark Murray } 233b528cefcSMark Murray ret = kadm5_log_preamble (context, sp, kadm_create); 234b528cefcSMark Murray if (ret) { 235b528cefcSMark Murray krb5_data_free (&value); 236b528cefcSMark Murray krb5_storage_free(sp); 237b528cefcSMark Murray return ret; 238b528cefcSMark Murray } 239b528cefcSMark Murray krb5_store_int32 (sp, value.length); 240*8373020dSJacques Vidrine krb5_storage_write(sp, value.data, value.length); 241b528cefcSMark Murray krb5_store_int32 (sp, value.length); 242b528cefcSMark Murray krb5_data_free (&value); 243b528cefcSMark Murray ret = kadm5_log_postamble (log_context, sp); 244b528cefcSMark Murray if (ret) { 245b528cefcSMark Murray krb5_storage_free (sp); 246b528cefcSMark Murray return ret; 247b528cefcSMark Murray } 248b528cefcSMark Murray ret = kadm5_log_flush (log_context, sp); 249b528cefcSMark Murray krb5_storage_free (sp); 250b528cefcSMark Murray if (ret) 251b528cefcSMark Murray return ret; 252b528cefcSMark Murray ret = kadm5_log_end (context); 253b528cefcSMark Murray return ret; 254b528cefcSMark Murray } 255b528cefcSMark Murray 256b528cefcSMark Murray /* 257b528cefcSMark Murray * Read the data of a create log record from `sp' and change the 258b528cefcSMark Murray * database. 259b528cefcSMark Murray */ 260b528cefcSMark Murray 261b528cefcSMark Murray kadm5_ret_t 262b528cefcSMark Murray kadm5_log_replay_create (kadm5_server_context *context, 263b528cefcSMark Murray u_int32_t ver, 264b528cefcSMark Murray u_int32_t len, 265b528cefcSMark Murray krb5_storage *sp) 266b528cefcSMark Murray { 267b528cefcSMark Murray krb5_error_code ret; 268b528cefcSMark Murray krb5_data data; 269b528cefcSMark Murray hdb_entry ent; 270b528cefcSMark Murray 271b528cefcSMark Murray krb5_data_alloc (&data, len); 272*8373020dSJacques Vidrine krb5_storage_read (sp, data.data, len); 273b528cefcSMark Murray ret = hdb_value2entry (context->context, &data, &ent); 274b528cefcSMark Murray krb5_data_free(&data); 275b528cefcSMark Murray if (ret) 276b528cefcSMark Murray return ret; 277b528cefcSMark Murray ret = context->db->store(context->context, context->db, 0, &ent); 278b528cefcSMark Murray hdb_free_entry (context->context, &ent); 279b528cefcSMark Murray return ret; 280b528cefcSMark Murray } 281b528cefcSMark Murray 282b528cefcSMark Murray /* 283b528cefcSMark Murray * Add a `delete' operation to the log. 284b528cefcSMark Murray */ 285b528cefcSMark Murray 286b528cefcSMark Murray kadm5_ret_t 287b528cefcSMark Murray kadm5_log_delete (kadm5_server_context *context, 288b528cefcSMark Murray krb5_principal princ) 289b528cefcSMark Murray { 290b528cefcSMark Murray krb5_storage *sp; 291b528cefcSMark Murray kadm5_ret_t ret; 292b528cefcSMark Murray off_t off; 293b528cefcSMark Murray off_t len; 294b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context; 295b528cefcSMark Murray 296b528cefcSMark Murray sp = krb5_storage_emem(); 297b528cefcSMark Murray ret = kadm5_log_preamble (context, sp, kadm_delete); 298b528cefcSMark Murray if (ret) { 299b528cefcSMark Murray krb5_storage_free(sp); 300b528cefcSMark Murray return ret; 301b528cefcSMark Murray } 302b528cefcSMark Murray krb5_store_int32 (sp, 0); 303*8373020dSJacques Vidrine off = krb5_storage_seek (sp, 0, SEEK_CUR); 304b528cefcSMark Murray krb5_store_principal (sp, princ); 305*8373020dSJacques Vidrine len = krb5_storage_seek (sp, 0, SEEK_CUR) - off; 306*8373020dSJacques Vidrine krb5_storage_seek(sp, -(len + 4), SEEK_CUR); 307b528cefcSMark Murray krb5_store_int32 (sp, len); 308*8373020dSJacques Vidrine krb5_storage_seek(sp, len, SEEK_CUR); 309b528cefcSMark Murray krb5_store_int32 (sp, len); 310b528cefcSMark Murray if (ret) { 311b528cefcSMark Murray krb5_storage_free (sp); 312b528cefcSMark Murray return ret; 313b528cefcSMark Murray } 314b528cefcSMark Murray ret = kadm5_log_postamble (log_context, sp); 315b528cefcSMark Murray if (ret) { 316b528cefcSMark Murray krb5_storage_free (sp); 317b528cefcSMark Murray return ret; 318b528cefcSMark Murray } 319b528cefcSMark Murray ret = kadm5_log_flush (log_context, sp); 320b528cefcSMark Murray krb5_storage_free (sp); 321b528cefcSMark Murray if (ret) 322b528cefcSMark Murray return ret; 323b528cefcSMark Murray ret = kadm5_log_end (context); 324b528cefcSMark Murray return ret; 325b528cefcSMark Murray } 326b528cefcSMark Murray 327b528cefcSMark Murray /* 328b528cefcSMark Murray * Read a `delete' log operation from `sp' and apply it. 329b528cefcSMark Murray */ 330b528cefcSMark Murray 331b528cefcSMark Murray kadm5_ret_t 332b528cefcSMark Murray kadm5_log_replay_delete (kadm5_server_context *context, 333b528cefcSMark Murray u_int32_t ver, 334b528cefcSMark Murray u_int32_t len, 335b528cefcSMark Murray krb5_storage *sp) 336b528cefcSMark Murray { 337b528cefcSMark Murray krb5_error_code ret; 338b528cefcSMark Murray hdb_entry ent; 339b528cefcSMark Murray 340b528cefcSMark Murray krb5_ret_principal (sp, &ent.principal); 341b528cefcSMark Murray 342b528cefcSMark Murray ret = context->db->remove(context->context, context->db, &ent); 343b528cefcSMark Murray krb5_free_principal (context->context, ent.principal); 344b528cefcSMark Murray return ret; 345b528cefcSMark Murray } 346b528cefcSMark Murray 347b528cefcSMark Murray /* 348b528cefcSMark Murray * Add a `rename' operation to the log. 349b528cefcSMark Murray */ 350b528cefcSMark Murray 351b528cefcSMark Murray kadm5_ret_t 352b528cefcSMark Murray kadm5_log_rename (kadm5_server_context *context, 353b528cefcSMark Murray krb5_principal source, 354b528cefcSMark Murray hdb_entry *ent) 355b528cefcSMark Murray { 356b528cefcSMark Murray krb5_storage *sp; 357b528cefcSMark Murray kadm5_ret_t ret; 358b528cefcSMark Murray off_t off; 359b528cefcSMark Murray off_t len; 360b528cefcSMark Murray krb5_data value; 361b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context; 362b528cefcSMark Murray 363b528cefcSMark Murray sp = krb5_storage_emem(); 364b528cefcSMark Murray ret = hdb_entry2value (context->context, ent, &value); 365b528cefcSMark Murray if (ret) { 366b528cefcSMark Murray krb5_storage_free(sp); 367b528cefcSMark Murray return ret; 368b528cefcSMark Murray } 369b528cefcSMark Murray ret = kadm5_log_preamble (context, sp, kadm_rename); 370b528cefcSMark Murray if (ret) { 371b528cefcSMark Murray krb5_storage_free(sp); 372b528cefcSMark Murray krb5_data_free (&value); 373b528cefcSMark Murray return ret; 374b528cefcSMark Murray } 375b528cefcSMark Murray krb5_store_int32 (sp, 0); 376*8373020dSJacques Vidrine off = krb5_storage_seek (sp, 0, SEEK_CUR); 377b528cefcSMark Murray krb5_store_principal (sp, source); 378*8373020dSJacques Vidrine krb5_storage_write(sp, value.data, value.length); 379b528cefcSMark Murray krb5_data_free (&value); 380*8373020dSJacques Vidrine len = krb5_storage_seek (sp, 0, SEEK_CUR) - off; 381b528cefcSMark Murray 382*8373020dSJacques Vidrine krb5_storage_seek(sp, -(len + 4), SEEK_CUR); 383b528cefcSMark Murray krb5_store_int32 (sp, len); 384*8373020dSJacques Vidrine krb5_storage_seek(sp, len, SEEK_CUR); 385b528cefcSMark Murray krb5_store_int32 (sp, len); 386b528cefcSMark Murray if (ret) { 387b528cefcSMark Murray krb5_storage_free (sp); 388b528cefcSMark Murray return ret; 389b528cefcSMark Murray } 390b528cefcSMark Murray ret = kadm5_log_postamble (log_context, sp); 391b528cefcSMark Murray if (ret) { 392b528cefcSMark Murray krb5_storage_free (sp); 393b528cefcSMark Murray return ret; 394b528cefcSMark Murray } 395b528cefcSMark Murray ret = kadm5_log_flush (log_context, sp); 396b528cefcSMark Murray krb5_storage_free (sp); 397b528cefcSMark Murray if (ret) 398b528cefcSMark Murray return ret; 399b528cefcSMark Murray ret = kadm5_log_end (context); 400b528cefcSMark Murray return ret; 401b528cefcSMark Murray } 402b528cefcSMark Murray 403b528cefcSMark Murray /* 404b528cefcSMark Murray * Read a `rename' log operation from `sp' and apply it. 405b528cefcSMark Murray */ 406b528cefcSMark Murray 407b528cefcSMark Murray kadm5_ret_t 408b528cefcSMark Murray kadm5_log_replay_rename (kadm5_server_context *context, 409b528cefcSMark Murray u_int32_t ver, 410b528cefcSMark Murray u_int32_t len, 411b528cefcSMark Murray krb5_storage *sp) 412b528cefcSMark Murray { 413b528cefcSMark Murray krb5_error_code ret; 414b528cefcSMark Murray krb5_principal source; 415b528cefcSMark Murray hdb_entry source_ent, target_ent; 416b528cefcSMark Murray krb5_data value; 417b528cefcSMark Murray off_t off; 418b528cefcSMark Murray size_t princ_len, data_len; 419b528cefcSMark Murray 420*8373020dSJacques Vidrine off = krb5_storage_seek(sp, 0, SEEK_CUR); 421b528cefcSMark Murray krb5_ret_principal (sp, &source); 422*8373020dSJacques Vidrine princ_len = krb5_storage_seek(sp, 0, SEEK_CUR) - off; 423b528cefcSMark Murray data_len = len - princ_len; 424b528cefcSMark Murray krb5_data_alloc (&value, data_len); 425*8373020dSJacques Vidrine krb5_storage_read (sp, value.data, data_len); 426b528cefcSMark Murray ret = hdb_value2entry (context->context, &value, &target_ent); 427b528cefcSMark Murray krb5_data_free(&value); 428b528cefcSMark Murray if (ret) { 429b528cefcSMark Murray krb5_free_principal (context->context, source); 430b528cefcSMark Murray return ret; 431b528cefcSMark Murray } 432b528cefcSMark Murray ret = context->db->store (context->context, context->db, 0, &target_ent); 433b528cefcSMark Murray hdb_free_entry (context->context, &target_ent); 434b528cefcSMark Murray if (ret) { 435b528cefcSMark Murray krb5_free_principal (context->context, source); 436b528cefcSMark Murray return ret; 437b528cefcSMark Murray } 438b528cefcSMark Murray source_ent.principal = source; 439b528cefcSMark Murray ret = context->db->remove (context->context, context->db, &source_ent); 440b528cefcSMark Murray krb5_free_principal (context->context, source); 441b528cefcSMark Murray return ret; 442b528cefcSMark Murray } 443b528cefcSMark Murray 444b528cefcSMark Murray 445b528cefcSMark Murray /* 446b528cefcSMark Murray * Add a `modify' operation to the log. 447b528cefcSMark Murray */ 448b528cefcSMark Murray 449b528cefcSMark Murray kadm5_ret_t 450b528cefcSMark Murray kadm5_log_modify (kadm5_server_context *context, 451b528cefcSMark Murray hdb_entry *ent, 452b528cefcSMark Murray u_int32_t mask) 453b528cefcSMark Murray { 454b528cefcSMark Murray krb5_storage *sp; 455b528cefcSMark Murray kadm5_ret_t ret; 456b528cefcSMark Murray krb5_data value; 457b528cefcSMark Murray u_int32_t len; 458b528cefcSMark Murray kadm5_log_context *log_context = &context->log_context; 459b528cefcSMark Murray 460b528cefcSMark Murray sp = krb5_storage_emem(); 461b528cefcSMark Murray ret = hdb_entry2value (context->context, ent, &value); 462b528cefcSMark Murray if (ret) { 463b528cefcSMark Murray krb5_storage_free(sp); 464b528cefcSMark Murray return ret; 465b528cefcSMark Murray } 466b528cefcSMark Murray ret = kadm5_log_preamble (context, sp, kadm_modify); 467b528cefcSMark Murray if (ret) { 468b528cefcSMark Murray krb5_data_free (&value); 469b528cefcSMark Murray krb5_storage_free(sp); 470b528cefcSMark Murray return ret; 471b528cefcSMark Murray } 472b528cefcSMark Murray len = value.length + 4; 473b528cefcSMark Murray krb5_store_int32 (sp, len); 474b528cefcSMark Murray krb5_store_int32 (sp, mask); 475*8373020dSJacques Vidrine krb5_storage_write (sp, value.data, value.length); 476b528cefcSMark Murray krb5_data_free (&value); 477b528cefcSMark Murray krb5_store_int32 (sp, len); 478b528cefcSMark Murray if (ret) { 479b528cefcSMark Murray krb5_storage_free (sp); 480b528cefcSMark Murray return ret; 481b528cefcSMark Murray } 482b528cefcSMark Murray ret = kadm5_log_postamble (log_context, sp); 483b528cefcSMark Murray if (ret) { 484b528cefcSMark Murray krb5_storage_free (sp); 485b528cefcSMark Murray return ret; 486b528cefcSMark Murray } 487b528cefcSMark Murray ret = kadm5_log_flush (log_context, sp); 488b528cefcSMark Murray krb5_storage_free (sp); 489b528cefcSMark Murray if (ret) 490b528cefcSMark Murray return ret; 491b528cefcSMark Murray ret = kadm5_log_end (context); 492b528cefcSMark Murray return ret; 493b528cefcSMark Murray } 494b528cefcSMark Murray 495b528cefcSMark Murray /* 496b528cefcSMark Murray * Read a `modify' log operation from `sp' and apply it. 497b528cefcSMark Murray */ 498b528cefcSMark Murray 499b528cefcSMark Murray kadm5_ret_t 500b528cefcSMark Murray kadm5_log_replay_modify (kadm5_server_context *context, 501b528cefcSMark Murray u_int32_t ver, 502b528cefcSMark Murray u_int32_t len, 503b528cefcSMark Murray krb5_storage *sp) 504b528cefcSMark Murray { 505b528cefcSMark Murray krb5_error_code ret; 506b528cefcSMark Murray int32_t mask; 507b528cefcSMark Murray krb5_data value; 508b528cefcSMark Murray hdb_entry ent, log_ent; 509b528cefcSMark Murray 510b528cefcSMark Murray krb5_ret_int32 (sp, &mask); 511b528cefcSMark Murray len -= 4; 512b528cefcSMark Murray krb5_data_alloc (&value, len); 513*8373020dSJacques Vidrine krb5_storage_read (sp, value.data, len); 514b528cefcSMark Murray ret = hdb_value2entry (context->context, &value, &log_ent); 515b528cefcSMark Murray krb5_data_free(&value); 516b528cefcSMark Murray if (ret) 517b528cefcSMark Murray return ret; 518b528cefcSMark Murray ent.principal = log_ent.principal; 519b528cefcSMark Murray log_ent.principal = NULL; 520b528cefcSMark Murray ret = context->db->fetch(context->context, context->db, 521b528cefcSMark Murray HDB_F_DECRYPT, &ent); 522b528cefcSMark Murray if (ret) 523b528cefcSMark Murray return ret; 524b528cefcSMark Murray if (mask & KADM5_PRINC_EXPIRE_TIME) { 5255e9cd1aeSAssar Westerlund if (log_ent.valid_end == NULL) { 5265e9cd1aeSAssar Westerlund ent.valid_end = NULL; 5275e9cd1aeSAssar Westerlund } else { 528b528cefcSMark Murray if (ent.valid_end == NULL) 529b528cefcSMark Murray ent.valid_end = malloc(sizeof(*ent.valid_end)); 530b528cefcSMark Murray *ent.valid_end = *log_ent.valid_end; 531b528cefcSMark Murray } 5325e9cd1aeSAssar Westerlund } 533b528cefcSMark Murray if (mask & KADM5_PW_EXPIRATION) { 5345e9cd1aeSAssar Westerlund if (log_ent.pw_end == NULL) { 5355e9cd1aeSAssar Westerlund ent.pw_end = NULL; 5365e9cd1aeSAssar Westerlund } else { 537b528cefcSMark Murray if (ent.pw_end == NULL) 538b528cefcSMark Murray ent.pw_end = malloc(sizeof(*ent.pw_end)); 539b528cefcSMark Murray *ent.pw_end = *log_ent.pw_end; 540b528cefcSMark Murray } 5415e9cd1aeSAssar Westerlund } 542b528cefcSMark Murray if (mask & KADM5_LAST_PWD_CHANGE) { 543b528cefcSMark Murray abort (); /* XXX */ 544b528cefcSMark Murray } 545b528cefcSMark Murray if (mask & KADM5_ATTRIBUTES) { 546b528cefcSMark Murray ent.flags = log_ent.flags; 547b528cefcSMark Murray } 548b528cefcSMark Murray if (mask & KADM5_MAX_LIFE) { 5495e9cd1aeSAssar Westerlund if (log_ent.max_life == NULL) { 5505e9cd1aeSAssar Westerlund ent.max_life = NULL; 5515e9cd1aeSAssar Westerlund } else { 552b528cefcSMark Murray if (ent.max_life == NULL) 553b528cefcSMark Murray ent.max_life = malloc (sizeof(*ent.max_life)); 554b528cefcSMark Murray *ent.max_life = *log_ent.max_life; 555b528cefcSMark Murray } 5565e9cd1aeSAssar Westerlund } 557b528cefcSMark Murray if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) { 558b528cefcSMark Murray if (ent.modified_by == NULL) { 559b528cefcSMark Murray ent.modified_by = malloc(sizeof(*ent.modified_by)); 560b528cefcSMark Murray } else 561b528cefcSMark Murray free_Event(ent.modified_by); 562b528cefcSMark Murray copy_Event(log_ent.modified_by, ent.modified_by); 563b528cefcSMark Murray } 564b528cefcSMark Murray if (mask & KADM5_KVNO) { 565b528cefcSMark Murray ent.kvno = log_ent.kvno; 566b528cefcSMark Murray } 567b528cefcSMark Murray if (mask & KADM5_MKVNO) { 568b528cefcSMark Murray abort (); /* XXX */ 569b528cefcSMark Murray } 570b528cefcSMark Murray if (mask & KADM5_AUX_ATTRIBUTES) { 571b528cefcSMark Murray abort (); /* XXX */ 572b528cefcSMark Murray } 573b528cefcSMark Murray if (mask & KADM5_POLICY) { 574b528cefcSMark Murray abort (); /* XXX */ 575b528cefcSMark Murray } 576b528cefcSMark Murray if (mask & KADM5_POLICY_CLR) { 577b528cefcSMark Murray abort (); /* XXX */ 578b528cefcSMark Murray } 579b528cefcSMark Murray if (mask & KADM5_MAX_RLIFE) { 5805e9cd1aeSAssar Westerlund if (log_ent.max_renew == NULL) { 5815e9cd1aeSAssar Westerlund ent.max_renew = NULL; 5825e9cd1aeSAssar Westerlund } else { 583b528cefcSMark Murray if (ent.max_renew == NULL) 584b528cefcSMark Murray ent.max_renew = malloc (sizeof(*ent.max_renew)); 585b528cefcSMark Murray *ent.max_renew = *log_ent.max_renew; 586b528cefcSMark Murray } 5875e9cd1aeSAssar Westerlund } 588b528cefcSMark Murray if (mask & KADM5_LAST_SUCCESS) { 589b528cefcSMark Murray abort (); /* XXX */ 590b528cefcSMark Murray } 591b528cefcSMark Murray if (mask & KADM5_LAST_FAILED) { 592b528cefcSMark Murray abort (); /* XXX */ 593b528cefcSMark Murray } 594b528cefcSMark Murray if (mask & KADM5_FAIL_AUTH_COUNT) { 595b528cefcSMark Murray abort (); /* XXX */ 596b528cefcSMark Murray } 597b528cefcSMark Murray if (mask & KADM5_KEY_DATA) { 598b528cefcSMark Murray size_t len; 599b528cefcSMark Murray int i; 600b528cefcSMark Murray 601b528cefcSMark Murray for (i = 0; i < ent.keys.len; ++i) 602b528cefcSMark Murray free_Key(&ent.keys.val[i]); 603b528cefcSMark Murray free (ent.keys.val); 604b528cefcSMark Murray 605b528cefcSMark Murray len = log_ent.keys.len; 606b528cefcSMark Murray 607b528cefcSMark Murray ent.keys.len = len; 608b528cefcSMark Murray ent.keys.val = malloc(len * sizeof(*ent.keys.val)); 609b528cefcSMark Murray for (i = 0; i < ent.keys.len; ++i) 610b528cefcSMark Murray copy_Key(&log_ent.keys.val[i], 611b528cefcSMark Murray &ent.keys.val[i]); 612b528cefcSMark Murray } 613b528cefcSMark Murray ret = context->db->store(context->context, context->db, 614b528cefcSMark Murray HDB_F_REPLACE, &ent); 615b528cefcSMark Murray hdb_free_entry (context->context, &ent); 616b528cefcSMark Murray hdb_free_entry (context->context, &log_ent); 617b528cefcSMark Murray return ret; 618b528cefcSMark Murray } 619b528cefcSMark Murray 620b528cefcSMark Murray /* 6215e9cd1aeSAssar Westerlund * Add a `nop' operation to the log. 6225e9cd1aeSAssar Westerlund */ 6235e9cd1aeSAssar Westerlund 6245e9cd1aeSAssar Westerlund kadm5_ret_t 6255e9cd1aeSAssar Westerlund kadm5_log_nop (kadm5_server_context *context) 6265e9cd1aeSAssar Westerlund { 6275e9cd1aeSAssar Westerlund krb5_storage *sp; 6285e9cd1aeSAssar Westerlund kadm5_ret_t ret; 6295e9cd1aeSAssar Westerlund kadm5_log_context *log_context = &context->log_context; 6305e9cd1aeSAssar Westerlund 6315e9cd1aeSAssar Westerlund sp = krb5_storage_emem(); 6325e9cd1aeSAssar Westerlund ret = kadm5_log_preamble (context, sp, kadm_nop); 6335e9cd1aeSAssar Westerlund if (ret) { 6345e9cd1aeSAssar Westerlund krb5_storage_free (sp); 6355e9cd1aeSAssar Westerlund return ret; 6365e9cd1aeSAssar Westerlund } 6375e9cd1aeSAssar Westerlund krb5_store_int32 (sp, 0); 6385e9cd1aeSAssar Westerlund krb5_store_int32 (sp, 0); 6395e9cd1aeSAssar Westerlund ret = kadm5_log_postamble (log_context, sp); 6405e9cd1aeSAssar Westerlund if (ret) { 6415e9cd1aeSAssar Westerlund krb5_storage_free (sp); 6425e9cd1aeSAssar Westerlund return ret; 6435e9cd1aeSAssar Westerlund } 6445e9cd1aeSAssar Westerlund ret = kadm5_log_flush (log_context, sp); 6455e9cd1aeSAssar Westerlund krb5_storage_free (sp); 6465e9cd1aeSAssar Westerlund if (ret) 6475e9cd1aeSAssar Westerlund return ret; 6485e9cd1aeSAssar Westerlund ret = kadm5_log_end (context); 6495e9cd1aeSAssar Westerlund return ret; 6505e9cd1aeSAssar Westerlund } 6515e9cd1aeSAssar Westerlund 6525e9cd1aeSAssar Westerlund /* 6535e9cd1aeSAssar Westerlund * Read a `nop' log operation from `sp' and apply it. 6545e9cd1aeSAssar Westerlund */ 6555e9cd1aeSAssar Westerlund 6565e9cd1aeSAssar Westerlund kadm5_ret_t 6575e9cd1aeSAssar Westerlund kadm5_log_replay_nop (kadm5_server_context *context, 6585e9cd1aeSAssar Westerlund u_int32_t ver, 6595e9cd1aeSAssar Westerlund u_int32_t len, 6605e9cd1aeSAssar Westerlund krb5_storage *sp) 6615e9cd1aeSAssar Westerlund { 6625e9cd1aeSAssar Westerlund return 0; 6635e9cd1aeSAssar Westerlund } 6645e9cd1aeSAssar Westerlund 6655e9cd1aeSAssar Westerlund /* 666b528cefcSMark Murray * Call `func' for each log record in the log in `context' 667b528cefcSMark Murray */ 668b528cefcSMark Murray 669b528cefcSMark Murray kadm5_ret_t 670b528cefcSMark Murray kadm5_log_foreach (kadm5_server_context *context, 671b528cefcSMark Murray void (*func)(kadm5_server_context *server_context, 672b528cefcSMark Murray u_int32_t ver, 673b528cefcSMark Murray time_t timestamp, 674b528cefcSMark Murray enum kadm_ops op, 675b528cefcSMark Murray u_int32_t len, 676b528cefcSMark Murray krb5_storage *sp)) 677b528cefcSMark Murray { 678b528cefcSMark Murray int fd = context->log_context.log_fd; 679b528cefcSMark Murray krb5_storage *sp; 680b528cefcSMark Murray 681b528cefcSMark Murray lseek (fd, 0, SEEK_SET); 682b528cefcSMark Murray sp = krb5_storage_from_fd (fd); 683b528cefcSMark Murray for (;;) { 684b528cefcSMark Murray int32_t ver, timestamp, op, len; 685b528cefcSMark Murray 686b528cefcSMark Murray if(krb5_ret_int32 (sp, &ver) != 0) 687b528cefcSMark Murray break; 688b528cefcSMark Murray krb5_ret_int32 (sp, ×tamp); 689b528cefcSMark Murray krb5_ret_int32 (sp, &op); 690b528cefcSMark Murray krb5_ret_int32 (sp, &len); 691b528cefcSMark Murray (*func)(context, ver, timestamp, op, len, sp); 692*8373020dSJacques Vidrine krb5_storage_seek(sp, 8, SEEK_CUR); 693b528cefcSMark Murray } 694b528cefcSMark Murray return 0; 695b528cefcSMark Murray } 696b528cefcSMark Murray 697b528cefcSMark Murray /* 698b528cefcSMark Murray * Go to end of log. 699b528cefcSMark Murray */ 700b528cefcSMark Murray 701b528cefcSMark Murray krb5_storage * 702b528cefcSMark Murray kadm5_log_goto_end (int fd) 703b528cefcSMark Murray { 704b528cefcSMark Murray krb5_storage *sp; 705b528cefcSMark Murray 706b528cefcSMark Murray sp = krb5_storage_from_fd (fd); 707*8373020dSJacques Vidrine krb5_storage_seek(sp, 0, SEEK_END); 708b528cefcSMark Murray return sp; 709b528cefcSMark Murray } 710b528cefcSMark Murray 711b528cefcSMark Murray /* 712b528cefcSMark Murray * Return previous log entry. 713b528cefcSMark Murray */ 714b528cefcSMark Murray 715b528cefcSMark Murray kadm5_ret_t 716b528cefcSMark Murray kadm5_log_previous (krb5_storage *sp, 717b528cefcSMark Murray u_int32_t *ver, 718b528cefcSMark Murray time_t *timestamp, 719b528cefcSMark Murray enum kadm_ops *op, 720b528cefcSMark Murray u_int32_t *len) 721b528cefcSMark Murray { 722b528cefcSMark Murray off_t off; 723b528cefcSMark Murray int32_t tmp; 724b528cefcSMark Murray 725*8373020dSJacques Vidrine krb5_storage_seek(sp, -8, SEEK_CUR); 726b528cefcSMark Murray krb5_ret_int32 (sp, &tmp); 727b528cefcSMark Murray *len = tmp; 728b528cefcSMark Murray krb5_ret_int32 (sp, &tmp); 729b528cefcSMark Murray *ver = tmp; 730b528cefcSMark Murray off = 24 + *len; 731*8373020dSJacques Vidrine krb5_storage_seek(sp, -off, SEEK_CUR); 732b528cefcSMark Murray krb5_ret_int32 (sp, &tmp); 733b528cefcSMark Murray assert(tmp == *ver); 734b528cefcSMark Murray krb5_ret_int32 (sp, &tmp); 735b528cefcSMark Murray *timestamp = tmp; 736b528cefcSMark Murray krb5_ret_int32 (sp, &tmp); 737b528cefcSMark Murray *op = tmp; 738b528cefcSMark Murray krb5_ret_int32 (sp, &tmp); 739b528cefcSMark Murray assert(tmp == *len); 740b528cefcSMark Murray return 0; 741b528cefcSMark Murray } 742b528cefcSMark Murray 743b528cefcSMark Murray /* 744b528cefcSMark Murray * Replay a record from the log 745b528cefcSMark Murray */ 746b528cefcSMark Murray 747b528cefcSMark Murray kadm5_ret_t 748b528cefcSMark Murray kadm5_log_replay (kadm5_server_context *context, 749b528cefcSMark Murray enum kadm_ops op, 750b528cefcSMark Murray u_int32_t ver, 751b528cefcSMark Murray u_int32_t len, 752b528cefcSMark Murray krb5_storage *sp) 753b528cefcSMark Murray { 754b528cefcSMark Murray switch (op) { 755b528cefcSMark Murray case kadm_create : 756b528cefcSMark Murray return kadm5_log_replay_create (context, ver, len, sp); 757b528cefcSMark Murray case kadm_delete : 758b528cefcSMark Murray return kadm5_log_replay_delete (context, ver, len, sp); 759b528cefcSMark Murray case kadm_rename : 760b528cefcSMark Murray return kadm5_log_replay_rename (context, ver, len, sp); 761b528cefcSMark Murray case kadm_modify : 762b528cefcSMark Murray return kadm5_log_replay_modify (context, ver, len, sp); 7635e9cd1aeSAssar Westerlund case kadm_nop : 7645e9cd1aeSAssar Westerlund return kadm5_log_replay_nop (context, ver, len, sp); 765b528cefcSMark Murray default : 766b528cefcSMark Murray return KADM5_FAILURE; 767b528cefcSMark Murray } 768b528cefcSMark Murray } 7695e9cd1aeSAssar Westerlund 7705e9cd1aeSAssar Westerlund /* 7715e9cd1aeSAssar Westerlund * truncate the log - i.e. create an empty file with just (nop vno + 2) 7725e9cd1aeSAssar Westerlund */ 7735e9cd1aeSAssar Westerlund 7745e9cd1aeSAssar Westerlund kadm5_ret_t 7755e9cd1aeSAssar Westerlund kadm5_log_truncate (kadm5_server_context *server_context) 7765e9cd1aeSAssar Westerlund { 7775e9cd1aeSAssar Westerlund kadm5_ret_t ret; 7785e9cd1aeSAssar Westerlund u_int32_t vno; 7795e9cd1aeSAssar Westerlund 7805e9cd1aeSAssar Westerlund ret = kadm5_log_init (server_context); 7815e9cd1aeSAssar Westerlund if (ret) 7825e9cd1aeSAssar Westerlund return ret; 7835e9cd1aeSAssar Westerlund 7845e9cd1aeSAssar Westerlund ret = kadm5_log_get_version (server_context, &vno); 7855e9cd1aeSAssar Westerlund if (ret) 7865e9cd1aeSAssar Westerlund return ret; 7875e9cd1aeSAssar Westerlund 7885e9cd1aeSAssar Westerlund ret = kadm5_log_reinit (server_context); 7895e9cd1aeSAssar Westerlund if (ret) 7905e9cd1aeSAssar Westerlund return ret; 7915e9cd1aeSAssar Westerlund 7925e9cd1aeSAssar Westerlund ret = kadm5_log_set_version (server_context, vno + 1); 7935e9cd1aeSAssar Westerlund if (ret) 7945e9cd1aeSAssar Westerlund return ret; 7955e9cd1aeSAssar Westerlund 7965e9cd1aeSAssar Westerlund ret = kadm5_log_nop (server_context); 7975e9cd1aeSAssar Westerlund if (ret) 7985e9cd1aeSAssar Westerlund return ret; 7995e9cd1aeSAssar Westerlund 8005e9cd1aeSAssar Westerlund ret = kadm5_log_end (server_context); 8015e9cd1aeSAssar Westerlund if (ret) 8025e9cd1aeSAssar Westerlund return ret; 8035e9cd1aeSAssar Westerlund return 0; 8045e9cd1aeSAssar Westerlund 8055e9cd1aeSAssar Westerlund } 806