Home | History | Annotate | Line # | Download | only in kadm5
log.c revision 1.1.1.2
      1      1.1   elric /*	$NetBSD: log.c,v 1.1.1.2 2014/04/24 12:45:49 pettai Exp $	*/
      2      1.1   elric 
      3      1.1   elric /*
      4      1.1   elric  * Copyright (c) 1997 - 2007 Kungliga Tekniska Hgskolan
      5      1.1   elric  * (Royal Institute of Technology, Stockholm, Sweden).
      6      1.1   elric  * All rights reserved.
      7      1.1   elric  *
      8      1.1   elric  * Redistribution and use in source and binary forms, with or without
      9      1.1   elric  * modification, are permitted provided that the following conditions
     10      1.1   elric  * are met:
     11      1.1   elric  *
     12      1.1   elric  * 1. Redistributions of source code must retain the above copyright
     13      1.1   elric  *    notice, this list of conditions and the following disclaimer.
     14      1.1   elric  *
     15      1.1   elric  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1   elric  *    notice, this list of conditions and the following disclaimer in the
     17      1.1   elric  *    documentation and/or other materials provided with the distribution.
     18      1.1   elric  *
     19      1.1   elric  * 3. Neither the name of the Institute nor the names of its contributors
     20      1.1   elric  *    may be used to endorse or promote products derived from this software
     21      1.1   elric  *    without specific prior written permission.
     22      1.1   elric  *
     23      1.1   elric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     24      1.1   elric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25      1.1   elric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26      1.1   elric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     27      1.1   elric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28      1.1   elric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29      1.1   elric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30      1.1   elric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31      1.1   elric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32      1.1   elric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33      1.1   elric  * SUCH DAMAGE.
     34      1.1   elric  */
     35      1.1   elric 
     36      1.1   elric #include "kadm5_locl.h"
     37      1.1   elric #include "heim_threads.h"
     38      1.1   elric 
     39  1.1.1.2  pettai __RCSID("NetBSD");
     40      1.1   elric 
     41      1.1   elric /*
     42      1.1   elric  * A log record consists of:
     43      1.1   elric  *
     44      1.1   elric  * version number		4 bytes
     45      1.1   elric  * time in seconds		4 bytes
     46      1.1   elric  * operation (enum kadm_ops)	4 bytes
     47      1.1   elric  * length of record		4 bytes
     48      1.1   elric  * data...			n bytes
     49      1.1   elric  * length of record		4 bytes
     50      1.1   elric  * version number		4 bytes
     51      1.1   elric  *
     52      1.1   elric  */
     53      1.1   elric 
     54      1.1   elric kadm5_ret_t
     55      1.1   elric kadm5_log_get_version_fd (int fd,
     56      1.1   elric 			  uint32_t *ver)
     57      1.1   elric {
     58      1.1   elric     int ret;
     59      1.1   elric     krb5_storage *sp;
     60      1.1   elric     int32_t old_version;
     61      1.1   elric 
     62      1.1   elric     ret = lseek (fd, 0, SEEK_END);
     63      1.1   elric     if(ret < 0)
     64      1.1   elric 	return errno;
     65      1.1   elric     if(ret == 0) {
     66      1.1   elric 	*ver = 0;
     67      1.1   elric 	return 0;
     68      1.1   elric     }
     69      1.1   elric     sp = krb5_storage_from_fd (fd);
     70      1.1   elric     krb5_storage_seek(sp, -4, SEEK_CUR);
     71      1.1   elric     krb5_ret_int32 (sp, &old_version);
     72      1.1   elric     *ver = old_version;
     73      1.1   elric     krb5_storage_free(sp);
     74      1.1   elric     lseek (fd, 0, SEEK_END);
     75      1.1   elric     return 0;
     76      1.1   elric }
     77      1.1   elric 
     78      1.1   elric kadm5_ret_t
     79      1.1   elric kadm5_log_get_version (kadm5_server_context *context, uint32_t *ver)
     80      1.1   elric {
     81      1.1   elric     return kadm5_log_get_version_fd (context->log_context.log_fd, ver);
     82      1.1   elric }
     83      1.1   elric 
     84      1.1   elric kadm5_ret_t
     85      1.1   elric kadm5_log_set_version (kadm5_server_context *context, uint32_t vno)
     86      1.1   elric {
     87      1.1   elric     kadm5_log_context *log_context = &context->log_context;
     88      1.1   elric 
     89      1.1   elric     log_context->version = vno;
     90      1.1   elric     return 0;
     91      1.1   elric }
     92      1.1   elric 
     93      1.1   elric kadm5_ret_t
     94      1.1   elric kadm5_log_init (kadm5_server_context *context)
     95      1.1   elric {
     96      1.1   elric     int fd;
     97      1.1   elric     kadm5_ret_t ret;
     98      1.1   elric     kadm5_log_context *log_context = &context->log_context;
     99      1.1   elric 
    100      1.1   elric     if (log_context->log_fd != -1)
    101      1.1   elric 	return 0;
    102      1.1   elric     fd = open (log_context->log_file, O_RDWR | O_CREAT, 0600);
    103      1.1   elric     if (fd < 0) {
    104      1.1   elric 	ret = errno;
    105      1.1   elric 	krb5_set_error_message(context->context, ret, "kadm5_log_init: open %s",
    106      1.1   elric 			      log_context->log_file);
    107      1.1   elric 	return ret;
    108      1.1   elric     }
    109      1.1   elric     if (flock (fd, LOCK_EX) < 0) {
    110      1.1   elric 	ret = errno;
    111      1.1   elric 	krb5_set_error_message(context->context, ret, "kadm5_log_init: flock %s",
    112      1.1   elric 			       log_context->log_file);
    113      1.1   elric 	close (fd);
    114      1.1   elric 	return errno;
    115      1.1   elric     }
    116      1.1   elric 
    117      1.1   elric     ret = kadm5_log_get_version_fd (fd, &log_context->version);
    118      1.1   elric     if (ret)
    119      1.1   elric 	return ret;
    120      1.1   elric 
    121      1.1   elric     log_context->log_fd  = fd;
    122      1.1   elric     return 0;
    123      1.1   elric }
    124      1.1   elric 
    125      1.1   elric kadm5_ret_t
    126      1.1   elric kadm5_log_reinit (kadm5_server_context *context)
    127      1.1   elric {
    128      1.1   elric     int fd;
    129      1.1   elric     kadm5_log_context *log_context = &context->log_context;
    130      1.1   elric 
    131      1.1   elric     if (log_context->log_fd != -1) {
    132      1.1   elric 	flock (log_context->log_fd, LOCK_UN);
    133      1.1   elric 	close (log_context->log_fd);
    134      1.1   elric 	log_context->log_fd = -1;
    135      1.1   elric     }
    136      1.1   elric     fd = open (log_context->log_file, O_RDWR | O_CREAT | O_TRUNC, 0600);
    137      1.1   elric     if (fd < 0)
    138      1.1   elric 	return errno;
    139      1.1   elric     if (flock (fd, LOCK_EX) < 0) {
    140      1.1   elric 	close (fd);
    141      1.1   elric 	return errno;
    142      1.1   elric     }
    143      1.1   elric 
    144      1.1   elric     log_context->version = 0;
    145      1.1   elric     log_context->log_fd  = fd;
    146      1.1   elric     return 0;
    147      1.1   elric }
    148      1.1   elric 
    149      1.1   elric 
    150      1.1   elric kadm5_ret_t
    151      1.1   elric kadm5_log_end (kadm5_server_context *context)
    152      1.1   elric {
    153      1.1   elric     kadm5_log_context *log_context = &context->log_context;
    154      1.1   elric     int fd = log_context->log_fd;
    155      1.1   elric 
    156      1.1   elric     flock (fd, LOCK_UN);
    157      1.1   elric     close(fd);
    158      1.1   elric     log_context->log_fd = -1;
    159      1.1   elric     return 0;
    160      1.1   elric }
    161      1.1   elric 
    162      1.1   elric static kadm5_ret_t
    163      1.1   elric kadm5_log_preamble (kadm5_server_context *context,
    164      1.1   elric 		    krb5_storage *sp,
    165      1.1   elric 		    enum kadm_ops op)
    166      1.1   elric {
    167      1.1   elric     kadm5_log_context *log_context = &context->log_context;
    168      1.1   elric     kadm5_ret_t kadm_ret;
    169      1.1   elric 
    170      1.1   elric     kadm_ret = kadm5_log_init (context);
    171      1.1   elric     if (kadm_ret)
    172      1.1   elric 	return kadm_ret;
    173      1.1   elric 
    174      1.1   elric     krb5_store_int32 (sp, ++log_context->version);
    175      1.1   elric     krb5_store_int32 (sp, time(NULL));
    176      1.1   elric     krb5_store_int32 (sp, op);
    177      1.1   elric     return 0;
    178      1.1   elric }
    179      1.1   elric 
    180      1.1   elric static kadm5_ret_t
    181      1.1   elric kadm5_log_postamble (kadm5_log_context *context,
    182      1.1   elric 		     krb5_storage *sp)
    183      1.1   elric {
    184      1.1   elric     krb5_store_int32 (sp, context->version);
    185      1.1   elric     return 0;
    186      1.1   elric }
    187      1.1   elric 
    188      1.1   elric /*
    189      1.1   elric  * flush the log record in `sp'.
    190      1.1   elric  */
    191      1.1   elric 
    192      1.1   elric static kadm5_ret_t
    193      1.1   elric kadm5_log_flush (kadm5_log_context *log_context,
    194      1.1   elric 		 krb5_storage *sp)
    195      1.1   elric {
    196      1.1   elric     krb5_data data;
    197      1.1   elric     size_t len;
    198  1.1.1.2  pettai     ssize_t ret;
    199      1.1   elric 
    200      1.1   elric     krb5_storage_to_data(sp, &data);
    201      1.1   elric     len = data.length;
    202      1.1   elric     ret = write (log_context->log_fd, data.data, len);
    203  1.1.1.2  pettai     if (ret < 0 || (size_t)ret != len) {
    204      1.1   elric 	krb5_data_free(&data);
    205      1.1   elric 	return errno;
    206      1.1   elric     }
    207      1.1   elric     if (fsync (log_context->log_fd) < 0) {
    208      1.1   elric 	krb5_data_free(&data);
    209      1.1   elric 	return errno;
    210      1.1   elric     }
    211      1.1   elric 
    212      1.1   elric     /*
    213      1.1   elric      * Try to send a signal to any running `ipropd-master'
    214      1.1   elric      */
    215      1.1   elric #ifndef NO_UNIX_SOCKETS
    216      1.1   elric     sendto (log_context->socket_fd,
    217      1.1   elric 	    (void *)&log_context->version,
    218      1.1   elric 	    sizeof(log_context->version),
    219      1.1   elric 	    0,
    220      1.1   elric 	    (struct sockaddr *)&log_context->socket_name,
    221      1.1   elric 	    sizeof(log_context->socket_name));
    222      1.1   elric #else
    223      1.1   elric     sendto (log_context->socket_fd,
    224      1.1   elric 	    (void *)&log_context->version,
    225      1.1   elric 	    sizeof(log_context->version),
    226      1.1   elric 	    0,
    227      1.1   elric 	    log_context->socket_info->ai_addr,
    228      1.1   elric 	    log_context->socket_info->ai_addrlen);
    229      1.1   elric #endif
    230      1.1   elric 
    231      1.1   elric     krb5_data_free(&data);
    232      1.1   elric     return 0;
    233      1.1   elric }
    234      1.1   elric 
    235      1.1   elric /*
    236      1.1   elric  * Add a `create' operation to the log.
    237      1.1   elric  */
    238      1.1   elric 
    239      1.1   elric kadm5_ret_t
    240      1.1   elric kadm5_log_create (kadm5_server_context *context,
    241      1.1   elric 		  hdb_entry *ent)
    242      1.1   elric {
    243      1.1   elric     krb5_storage *sp;
    244      1.1   elric     kadm5_ret_t ret;
    245      1.1   elric     krb5_data value;
    246      1.1   elric     kadm5_log_context *log_context = &context->log_context;
    247      1.1   elric 
    248      1.1   elric     sp = krb5_storage_emem();
    249      1.1   elric     ret = hdb_entry2value (context->context, ent, &value);
    250      1.1   elric     if (ret) {
    251      1.1   elric 	krb5_storage_free(sp);
    252      1.1   elric 	return ret;
    253      1.1   elric     }
    254      1.1   elric     ret = kadm5_log_preamble (context, sp, kadm_create);
    255      1.1   elric     if (ret) {
    256      1.1   elric 	krb5_data_free (&value);
    257      1.1   elric 	krb5_storage_free(sp);
    258      1.1   elric 	return ret;
    259      1.1   elric     }
    260      1.1   elric     krb5_store_int32 (sp, value.length);
    261      1.1   elric     krb5_storage_write(sp, value.data, value.length);
    262      1.1   elric     krb5_store_int32 (sp, value.length);
    263      1.1   elric     krb5_data_free (&value);
    264      1.1   elric     ret = kadm5_log_postamble (log_context, sp);
    265      1.1   elric     if (ret) {
    266      1.1   elric 	krb5_storage_free (sp);
    267      1.1   elric 	return ret;
    268      1.1   elric     }
    269      1.1   elric     ret = kadm5_log_flush (log_context, sp);
    270      1.1   elric     krb5_storage_free (sp);
    271      1.1   elric     if (ret)
    272      1.1   elric 	return ret;
    273      1.1   elric     ret = kadm5_log_end (context);
    274      1.1   elric     return ret;
    275      1.1   elric }
    276      1.1   elric 
    277      1.1   elric /*
    278      1.1   elric  * Read the data of a create log record from `sp' and change the
    279      1.1   elric  * database.
    280      1.1   elric  */
    281      1.1   elric 
    282      1.1   elric static kadm5_ret_t
    283      1.1   elric kadm5_log_replay_create (kadm5_server_context *context,
    284      1.1   elric 			 uint32_t ver,
    285      1.1   elric 			 uint32_t len,
    286      1.1   elric 			 krb5_storage *sp)
    287      1.1   elric {
    288      1.1   elric     krb5_error_code ret;
    289      1.1   elric     krb5_data data;
    290      1.1   elric     hdb_entry_ex ent;
    291      1.1   elric 
    292      1.1   elric     memset(&ent, 0, sizeof(ent));
    293      1.1   elric 
    294      1.1   elric     ret = krb5_data_alloc (&data, len);
    295      1.1   elric     if (ret) {
    296      1.1   elric 	krb5_set_error_message(context->context, ret, "out of memory");
    297      1.1   elric 	return ret;
    298      1.1   elric     }
    299      1.1   elric     krb5_storage_read (sp, data.data, len);
    300      1.1   elric     ret = hdb_value2entry (context->context, &data, &ent.entry);
    301      1.1   elric     krb5_data_free(&data);
    302      1.1   elric     if (ret) {
    303      1.1   elric 	krb5_set_error_message(context->context, ret,
    304      1.1   elric 			       "Unmarshaling hdb entry failed");
    305      1.1   elric 	return ret;
    306      1.1   elric     }
    307      1.1   elric     ret = context->db->hdb_store(context->context, context->db, 0, &ent);
    308      1.1   elric     hdb_free_entry (context->context, &ent);
    309      1.1   elric     return ret;
    310      1.1   elric }
    311      1.1   elric 
    312      1.1   elric /*
    313      1.1   elric  * Add a `delete' operation to the log.
    314      1.1   elric  */
    315      1.1   elric 
    316      1.1   elric kadm5_ret_t
    317      1.1   elric kadm5_log_delete (kadm5_server_context *context,
    318      1.1   elric 		  krb5_principal princ)
    319      1.1   elric {
    320      1.1   elric     krb5_storage *sp;
    321      1.1   elric     kadm5_ret_t ret;
    322      1.1   elric     off_t off;
    323      1.1   elric     off_t len;
    324      1.1   elric     kadm5_log_context *log_context = &context->log_context;
    325      1.1   elric 
    326      1.1   elric     sp = krb5_storage_emem();
    327      1.1   elric     if (sp == NULL)
    328      1.1   elric 	return ENOMEM;
    329      1.1   elric     ret = kadm5_log_preamble (context, sp, kadm_delete);
    330      1.1   elric     if (ret)
    331      1.1   elric 	goto out;
    332      1.1   elric     ret = krb5_store_int32 (sp, 0);
    333      1.1   elric     if (ret)
    334      1.1   elric 	goto out;
    335      1.1   elric     off = krb5_storage_seek (sp, 0, SEEK_CUR);
    336      1.1   elric     ret = krb5_store_principal (sp, princ);
    337      1.1   elric     if (ret)
    338      1.1   elric 	goto out;
    339      1.1   elric     len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
    340      1.1   elric     krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
    341      1.1   elric     ret = krb5_store_int32 (sp, len);
    342      1.1   elric     if (ret)
    343      1.1   elric 	goto out;
    344      1.1   elric     krb5_storage_seek(sp, len, SEEK_CUR);
    345      1.1   elric     ret = krb5_store_int32 (sp, len);
    346      1.1   elric     if (ret)
    347      1.1   elric 	goto out;
    348      1.1   elric     ret = kadm5_log_postamble (log_context, sp);
    349      1.1   elric     if (ret)
    350      1.1   elric 	goto out;
    351      1.1   elric     ret = kadm5_log_flush (log_context, sp);
    352      1.1   elric     if (ret)
    353      1.1   elric 	goto out;
    354      1.1   elric     ret = kadm5_log_end (context);
    355      1.1   elric out:
    356      1.1   elric     krb5_storage_free (sp);
    357      1.1   elric     return ret;
    358      1.1   elric }
    359      1.1   elric 
    360      1.1   elric /*
    361      1.1   elric  * Read a `delete' log operation from `sp' and apply it.
    362      1.1   elric  */
    363      1.1   elric 
    364      1.1   elric static kadm5_ret_t
    365      1.1   elric kadm5_log_replay_delete (kadm5_server_context *context,
    366      1.1   elric 			 uint32_t ver,
    367      1.1   elric 			 uint32_t len,
    368      1.1   elric 			 krb5_storage *sp)
    369      1.1   elric {
    370      1.1   elric     krb5_error_code ret;
    371      1.1   elric     krb5_principal principal;
    372      1.1   elric 
    373      1.1   elric     ret = krb5_ret_principal (sp, &principal);
    374      1.1   elric     if (ret) {
    375      1.1   elric 	krb5_set_error_message(context->context,  ret, "Failed to read deleted "
    376      1.1   elric 			       "principal from log version: %ld",  (long)ver);
    377      1.1   elric 	return ret;
    378      1.1   elric     }
    379      1.1   elric 
    380      1.1   elric     ret = context->db->hdb_remove(context->context, context->db, principal);
    381      1.1   elric     krb5_free_principal (context->context, principal);
    382      1.1   elric     return ret;
    383      1.1   elric }
    384      1.1   elric 
    385      1.1   elric /*
    386      1.1   elric  * Add a `rename' operation to the log.
    387      1.1   elric  */
    388      1.1   elric 
    389      1.1   elric kadm5_ret_t
    390      1.1   elric kadm5_log_rename (kadm5_server_context *context,
    391      1.1   elric 		  krb5_principal source,
    392      1.1   elric 		  hdb_entry *ent)
    393      1.1   elric {
    394      1.1   elric     krb5_storage *sp;
    395      1.1   elric     kadm5_ret_t ret;
    396      1.1   elric     off_t off;
    397      1.1   elric     off_t len;
    398      1.1   elric     krb5_data value;
    399      1.1   elric     kadm5_log_context *log_context = &context->log_context;
    400      1.1   elric 
    401      1.1   elric     krb5_data_zero(&value);
    402      1.1   elric 
    403      1.1   elric     sp = krb5_storage_emem();
    404      1.1   elric     ret = hdb_entry2value (context->context, ent, &value);
    405      1.1   elric     if (ret)
    406      1.1   elric 	goto failed;
    407      1.1   elric 
    408      1.1   elric     ret = kadm5_log_preamble (context, sp, kadm_rename);
    409      1.1   elric     if (ret)
    410      1.1   elric 	goto failed;
    411      1.1   elric 
    412      1.1   elric     ret = krb5_store_int32 (sp, 0);
    413      1.1   elric     if (ret)
    414      1.1   elric 	goto failed;
    415      1.1   elric     off = krb5_storage_seek (sp, 0, SEEK_CUR);
    416      1.1   elric     ret = krb5_store_principal (sp, source);
    417      1.1   elric     if (ret)
    418      1.1   elric 	goto failed;
    419      1.1   elric 
    420      1.1   elric     krb5_storage_write(sp, value.data, value.length);
    421      1.1   elric     len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
    422      1.1   elric 
    423      1.1   elric     krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
    424      1.1   elric     ret = krb5_store_int32 (sp, len);
    425      1.1   elric     if (ret)
    426      1.1   elric 	goto failed;
    427      1.1   elric 
    428      1.1   elric     krb5_storage_seek(sp, len, SEEK_CUR);
    429      1.1   elric     ret = krb5_store_int32 (sp, len);
    430      1.1   elric     if (ret)
    431      1.1   elric 	goto failed;
    432      1.1   elric 
    433      1.1   elric     ret = kadm5_log_postamble (log_context, sp);
    434      1.1   elric     if (ret)
    435      1.1   elric 	goto failed;
    436      1.1   elric 
    437      1.1   elric     ret = kadm5_log_flush (log_context, sp);
    438      1.1   elric     if (ret)
    439      1.1   elric 	goto failed;
    440      1.1   elric     krb5_storage_free (sp);
    441      1.1   elric     krb5_data_free (&value);
    442      1.1   elric 
    443      1.1   elric     return kadm5_log_end (context);
    444      1.1   elric 
    445      1.1   elric failed:
    446      1.1   elric     krb5_data_free(&value);
    447      1.1   elric     krb5_storage_free(sp);
    448      1.1   elric     return ret;
    449      1.1   elric }
    450      1.1   elric 
    451      1.1   elric /*
    452      1.1   elric  * Read a `rename' log operation from `sp' and apply it.
    453      1.1   elric  */
    454      1.1   elric 
    455      1.1   elric static kadm5_ret_t
    456      1.1   elric kadm5_log_replay_rename (kadm5_server_context *context,
    457      1.1   elric 			 uint32_t ver,
    458      1.1   elric 			 uint32_t len,
    459      1.1   elric 			 krb5_storage *sp)
    460      1.1   elric {
    461      1.1   elric     krb5_error_code ret;
    462      1.1   elric     krb5_principal source;
    463      1.1   elric     hdb_entry_ex target_ent;
    464      1.1   elric     krb5_data value;
    465      1.1   elric     off_t off;
    466      1.1   elric     size_t princ_len, data_len;
    467      1.1   elric 
    468      1.1   elric     memset(&target_ent, 0, sizeof(target_ent));
    469      1.1   elric 
    470      1.1   elric     off = krb5_storage_seek(sp, 0, SEEK_CUR);
    471      1.1   elric     ret = krb5_ret_principal (sp, &source);
    472      1.1   elric     if (ret) {
    473      1.1   elric 	krb5_set_error_message(context->context, ret, "Failed to read renamed "
    474      1.1   elric 			       "principal in log, version: %ld", (long)ver);
    475      1.1   elric 	return ret;
    476      1.1   elric     }
    477      1.1   elric     princ_len = krb5_storage_seek(sp, 0, SEEK_CUR) - off;
    478      1.1   elric     data_len = len - princ_len;
    479      1.1   elric     ret = krb5_data_alloc (&value, data_len);
    480      1.1   elric     if (ret) {
    481      1.1   elric 	krb5_free_principal (context->context, source);
    482      1.1   elric 	return ret;
    483      1.1   elric     }
    484      1.1   elric     krb5_storage_read (sp, value.data, data_len);
    485      1.1   elric     ret = hdb_value2entry (context->context, &value, &target_ent.entry);
    486      1.1   elric     krb5_data_free(&value);
    487      1.1   elric     if (ret) {
    488      1.1   elric 	krb5_free_principal (context->context, source);
    489      1.1   elric 	return ret;
    490      1.1   elric     }
    491      1.1   elric     ret = context->db->hdb_store (context->context, context->db,
    492      1.1   elric 				  0, &target_ent);
    493      1.1   elric     hdb_free_entry (context->context, &target_ent);
    494      1.1   elric     if (ret) {
    495      1.1   elric 	krb5_free_principal (context->context, source);
    496      1.1   elric 	return ret;
    497      1.1   elric     }
    498      1.1   elric     ret = context->db->hdb_remove (context->context, context->db, source);
    499      1.1   elric     krb5_free_principal (context->context, source);
    500      1.1   elric     return ret;
    501      1.1   elric }
    502      1.1   elric 
    503      1.1   elric 
    504      1.1   elric /*
    505      1.1   elric  * Add a `modify' operation to the log.
    506      1.1   elric  */
    507      1.1   elric 
    508      1.1   elric kadm5_ret_t
    509      1.1   elric kadm5_log_modify (kadm5_server_context *context,
    510      1.1   elric 		  hdb_entry *ent,
    511      1.1   elric 		  uint32_t mask)
    512      1.1   elric {
    513      1.1   elric     krb5_storage *sp;
    514      1.1   elric     kadm5_ret_t ret;
    515      1.1   elric     krb5_data value;
    516      1.1   elric     uint32_t len;
    517      1.1   elric     kadm5_log_context *log_context = &context->log_context;
    518      1.1   elric 
    519      1.1   elric     krb5_data_zero(&value);
    520      1.1   elric 
    521      1.1   elric     sp = krb5_storage_emem();
    522      1.1   elric     ret = hdb_entry2value (context->context, ent, &value);
    523      1.1   elric     if (ret)
    524      1.1   elric 	goto failed;
    525      1.1   elric 
    526      1.1   elric     ret = kadm5_log_preamble (context, sp, kadm_modify);
    527      1.1   elric     if (ret)
    528      1.1   elric 	goto failed;
    529      1.1   elric 
    530      1.1   elric     len = value.length + 4;
    531      1.1   elric     ret = krb5_store_int32 (sp, len);
    532      1.1   elric     if (ret)
    533      1.1   elric 	goto failed;
    534      1.1   elric     ret = krb5_store_int32 (sp, mask);
    535      1.1   elric     if (ret)
    536      1.1   elric 	goto failed;
    537      1.1   elric     krb5_storage_write (sp, value.data, value.length);
    538      1.1   elric 
    539      1.1   elric     ret = krb5_store_int32 (sp, len);
    540      1.1   elric     if (ret)
    541      1.1   elric 	goto failed;
    542      1.1   elric     ret = kadm5_log_postamble (log_context, sp);
    543      1.1   elric     if (ret)
    544      1.1   elric 	goto failed;
    545      1.1   elric     ret = kadm5_log_flush (log_context, sp);
    546      1.1   elric     if (ret)
    547      1.1   elric 	goto failed;
    548      1.1   elric     krb5_data_free(&value);
    549      1.1   elric     krb5_storage_free (sp);
    550      1.1   elric     return kadm5_log_end (context);
    551      1.1   elric failed:
    552      1.1   elric     krb5_data_free(&value);
    553      1.1   elric     krb5_storage_free(sp);
    554      1.1   elric     return ret;
    555      1.1   elric }
    556      1.1   elric 
    557      1.1   elric /*
    558      1.1   elric  * Read a `modify' log operation from `sp' and apply it.
    559      1.1   elric  */
    560      1.1   elric 
    561      1.1   elric static kadm5_ret_t
    562      1.1   elric kadm5_log_replay_modify (kadm5_server_context *context,
    563      1.1   elric 			 uint32_t ver,
    564      1.1   elric 			 uint32_t len,
    565      1.1   elric 			 krb5_storage *sp)
    566      1.1   elric {
    567      1.1   elric     krb5_error_code ret;
    568      1.1   elric     int32_t mask;
    569      1.1   elric     krb5_data value;
    570      1.1   elric     hdb_entry_ex ent, log_ent;
    571      1.1   elric 
    572      1.1   elric     memset(&log_ent, 0, sizeof(log_ent));
    573      1.1   elric 
    574      1.1   elric     krb5_ret_int32 (sp, &mask);
    575      1.1   elric     len -= 4;
    576      1.1   elric     ret = krb5_data_alloc (&value, len);
    577      1.1   elric     if (ret) {
    578      1.1   elric 	krb5_set_error_message(context->context, ret, "out of memory");
    579      1.1   elric 	return ret;
    580      1.1   elric     }
    581      1.1   elric     krb5_storage_read (sp, value.data, len);
    582      1.1   elric     ret = hdb_value2entry (context->context, &value, &log_ent.entry);
    583      1.1   elric     krb5_data_free(&value);
    584      1.1   elric     if (ret)
    585      1.1   elric 	return ret;
    586      1.1   elric 
    587      1.1   elric     memset(&ent, 0, sizeof(ent));
    588      1.1   elric     ret = context->db->hdb_fetch_kvno(context->context, context->db,
    589      1.1   elric 				      log_ent.entry.principal,
    590      1.1   elric 				      HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent);
    591      1.1   elric     if (ret)
    592      1.1   elric 	goto out;
    593      1.1   elric     if (mask & KADM5_PRINC_EXPIRE_TIME) {
    594      1.1   elric 	if (log_ent.entry.valid_end == NULL) {
    595      1.1   elric 	    ent.entry.valid_end = NULL;
    596      1.1   elric 	} else {
    597      1.1   elric 	    if (ent.entry.valid_end == NULL) {
    598      1.1   elric 		ent.entry.valid_end = malloc(sizeof(*ent.entry.valid_end));
    599      1.1   elric 		if (ent.entry.valid_end == NULL) {
    600      1.1   elric 		    ret = ENOMEM;
    601      1.1   elric 		    krb5_set_error_message(context->context, ret, "out of memory");
    602      1.1   elric 		    goto out;
    603      1.1   elric 		}
    604      1.1   elric 	    }
    605      1.1   elric 	    *ent.entry.valid_end = *log_ent.entry.valid_end;
    606      1.1   elric 	}
    607      1.1   elric     }
    608      1.1   elric     if (mask & KADM5_PW_EXPIRATION) {
    609      1.1   elric 	if (log_ent.entry.pw_end == NULL) {
    610      1.1   elric 	    ent.entry.pw_end = NULL;
    611      1.1   elric 	} else {
    612      1.1   elric 	    if (ent.entry.pw_end == NULL) {
    613      1.1   elric 		ent.entry.pw_end = malloc(sizeof(*ent.entry.pw_end));
    614      1.1   elric 		if (ent.entry.pw_end == NULL) {
    615      1.1   elric 		    ret = ENOMEM;
    616      1.1   elric 		    krb5_set_error_message(context->context, ret, "out of memory");
    617      1.1   elric 		    goto out;
    618      1.1   elric 		}
    619      1.1   elric 	    }
    620      1.1   elric 	    *ent.entry.pw_end = *log_ent.entry.pw_end;
    621      1.1   elric 	}
    622      1.1   elric     }
    623      1.1   elric     if (mask & KADM5_LAST_PWD_CHANGE) {
    624  1.1.1.2  pettai         krb5_warnx (context->context, "Unimplemented mask KADM5_LAST_PWD_CHANGE");
    625      1.1   elric     }
    626      1.1   elric     if (mask & KADM5_ATTRIBUTES) {
    627      1.1   elric 	ent.entry.flags = log_ent.entry.flags;
    628      1.1   elric     }
    629      1.1   elric     if (mask & KADM5_MAX_LIFE) {
    630      1.1   elric 	if (log_ent.entry.max_life == NULL) {
    631      1.1   elric 	    ent.entry.max_life = NULL;
    632      1.1   elric 	} else {
    633      1.1   elric 	    if (ent.entry.max_life == NULL) {
    634      1.1   elric 		ent.entry.max_life = malloc (sizeof(*ent.entry.max_life));
    635      1.1   elric 		if (ent.entry.max_life == NULL) {
    636      1.1   elric 		    ret = ENOMEM;
    637      1.1   elric 		    krb5_set_error_message(context->context, ret, "out of memory");
    638      1.1   elric 		    goto out;
    639      1.1   elric 		}
    640      1.1   elric 	    }
    641      1.1   elric 	    *ent.entry.max_life = *log_ent.entry.max_life;
    642      1.1   elric 	}
    643      1.1   elric     }
    644      1.1   elric     if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) {
    645      1.1   elric 	if (ent.entry.modified_by == NULL) {
    646      1.1   elric 	    ent.entry.modified_by = malloc(sizeof(*ent.entry.modified_by));
    647      1.1   elric 	    if (ent.entry.modified_by == NULL) {
    648      1.1   elric 		ret = ENOMEM;
    649      1.1   elric 		krb5_set_error_message(context->context, ret, "out of memory");
    650      1.1   elric 		goto out;
    651      1.1   elric 	    }
    652      1.1   elric 	} else
    653      1.1   elric 	    free_Event(ent.entry.modified_by);
    654      1.1   elric 	ret = copy_Event(log_ent.entry.modified_by, ent.entry.modified_by);
    655      1.1   elric 	if (ret) {
    656      1.1   elric 	    krb5_set_error_message(context->context, ret, "out of memory");
    657      1.1   elric 	    goto out;
    658      1.1   elric 	}
    659      1.1   elric     }
    660      1.1   elric     if (mask & KADM5_KVNO) {
    661      1.1   elric 	ent.entry.kvno = log_ent.entry.kvno;
    662      1.1   elric     }
    663      1.1   elric     if (mask & KADM5_MKVNO) {
    664  1.1.1.2  pettai         krb5_warnx (context->context, "Unimplemented mask KADM5_KVNO");
    665      1.1   elric     }
    666      1.1   elric     if (mask & KADM5_AUX_ATTRIBUTES) {
    667  1.1.1.2  pettai         krb5_warnx (context->context, "Unimplemented mask KADM5_AUX_ATTRIBUTES");
    668      1.1   elric     }
    669      1.1   elric     if (mask & KADM5_POLICY) {
    670  1.1.1.2  pettai         krb5_warnx (context->context, "Unimplemented mask KADM5_POLICY");
    671      1.1   elric     }
    672      1.1   elric     if (mask & KADM5_POLICY_CLR) {
    673  1.1.1.2  pettai         krb5_warnx (context->context, "Unimplemented mask KADM5_POLICY_CLR");
    674      1.1   elric     }
    675      1.1   elric     if (mask & KADM5_MAX_RLIFE) {
    676      1.1   elric 	if (log_ent.entry.max_renew == NULL) {
    677      1.1   elric 	    ent.entry.max_renew = NULL;
    678      1.1   elric 	} else {
    679      1.1   elric 	    if (ent.entry.max_renew == NULL) {
    680      1.1   elric 		ent.entry.max_renew = malloc (sizeof(*ent.entry.max_renew));
    681      1.1   elric 		if (ent.entry.max_renew == NULL) {
    682      1.1   elric 		    ret = ENOMEM;
    683      1.1   elric 		    krb5_set_error_message(context->context, ret, "out of memory");
    684      1.1   elric 		    goto out;
    685      1.1   elric 		}
    686      1.1   elric 	    }
    687      1.1   elric 	    *ent.entry.max_renew = *log_ent.entry.max_renew;
    688      1.1   elric 	}
    689      1.1   elric     }
    690      1.1   elric     if (mask & KADM5_LAST_SUCCESS) {
    691  1.1.1.2  pettai         krb5_warnx (context->context, "Unimplemented mask KADM5_LAST_SUCCESS");
    692      1.1   elric     }
    693      1.1   elric     if (mask & KADM5_LAST_FAILED) {
    694  1.1.1.2  pettai         krb5_warnx (context->context, "Unimplemented mask KADM5_LAST_FAILED");
    695      1.1   elric     }
    696      1.1   elric     if (mask & KADM5_FAIL_AUTH_COUNT) {
    697  1.1.1.2  pettai         krb5_warnx (context->context, "Unimplemented mask KADM5_FAIL_AUTH_COUNT");
    698      1.1   elric     }
    699      1.1   elric     if (mask & KADM5_KEY_DATA) {
    700      1.1   elric 	size_t num;
    701  1.1.1.2  pettai 	size_t i;
    702      1.1   elric 
    703      1.1   elric 	for (i = 0; i < ent.entry.keys.len; ++i)
    704      1.1   elric 	    free_Key(&ent.entry.keys.val[i]);
    705      1.1   elric 	free (ent.entry.keys.val);
    706      1.1   elric 
    707      1.1   elric 	num = log_ent.entry.keys.len;
    708      1.1   elric 
    709      1.1   elric 	ent.entry.keys.len = num;
    710      1.1   elric 	ent.entry.keys.val = malloc(len * sizeof(*ent.entry.keys.val));
    711      1.1   elric 	if (ent.entry.keys.val == NULL) {
    712      1.1   elric 	    krb5_set_error_message(context->context, ENOMEM, "out of memory");
    713      1.1   elric 	    return ENOMEM;
    714      1.1   elric 	}
    715      1.1   elric 	for (i = 0; i < ent.entry.keys.len; ++i) {
    716      1.1   elric 	    ret = copy_Key(&log_ent.entry.keys.val[i],
    717      1.1   elric 			   &ent.entry.keys.val[i]);
    718      1.1   elric 	    if (ret) {
    719      1.1   elric 		krb5_set_error_message(context->context, ret, "out of memory");
    720      1.1   elric 		goto out;
    721      1.1   elric 	    }
    722      1.1   elric 	}
    723      1.1   elric     }
    724      1.1   elric     if ((mask & KADM5_TL_DATA) && log_ent.entry.extensions) {
    725      1.1   elric 	HDB_extensions *es = ent.entry.extensions;
    726      1.1   elric 
    727      1.1   elric 	ent.entry.extensions = calloc(1, sizeof(*ent.entry.extensions));
    728      1.1   elric 	if (ent.entry.extensions == NULL)
    729      1.1   elric 	    goto out;
    730      1.1   elric 
    731      1.1   elric 	ret = copy_HDB_extensions(log_ent.entry.extensions,
    732      1.1   elric 				  ent.entry.extensions);
    733      1.1   elric 	if (ret) {
    734      1.1   elric 	    krb5_set_error_message(context->context, ret, "out of memory");
    735      1.1   elric 	    free(ent.entry.extensions);
    736      1.1   elric 	    ent.entry.extensions = es;
    737      1.1   elric 	    goto out;
    738      1.1   elric 	}
    739      1.1   elric 	if (es) {
    740      1.1   elric 	    free_HDB_extensions(es);
    741      1.1   elric 	    free(es);
    742      1.1   elric 	}
    743      1.1   elric     }
    744      1.1   elric     ret = context->db->hdb_store(context->context, context->db,
    745      1.1   elric 				 HDB_F_REPLACE, &ent);
    746      1.1   elric  out:
    747      1.1   elric     hdb_free_entry (context->context, &ent);
    748      1.1   elric     hdb_free_entry (context->context, &log_ent);
    749      1.1   elric     return ret;
    750      1.1   elric }
    751      1.1   elric 
    752      1.1   elric /*
    753      1.1   elric  * Add a `nop' operation to the log. Does not close the log.
    754      1.1   elric  */
    755      1.1   elric 
    756      1.1   elric kadm5_ret_t
    757      1.1   elric kadm5_log_nop (kadm5_server_context *context)
    758      1.1   elric {
    759      1.1   elric     krb5_storage *sp;
    760      1.1   elric     kadm5_ret_t ret;
    761      1.1   elric     kadm5_log_context *log_context = &context->log_context;
    762      1.1   elric 
    763      1.1   elric     sp = krb5_storage_emem();
    764      1.1   elric     ret = kadm5_log_preamble (context, sp, kadm_nop);
    765      1.1   elric     if (ret) {
    766      1.1   elric 	krb5_storage_free (sp);
    767      1.1   elric 	return ret;
    768      1.1   elric     }
    769      1.1   elric     krb5_store_int32 (sp, 0);
    770      1.1   elric     krb5_store_int32 (sp, 0);
    771      1.1   elric     ret = kadm5_log_postamble (log_context, sp);
    772      1.1   elric     if (ret) {
    773      1.1   elric 	krb5_storage_free (sp);
    774      1.1   elric 	return ret;
    775      1.1   elric     }
    776      1.1   elric     ret = kadm5_log_flush (log_context, sp);
    777      1.1   elric     krb5_storage_free (sp);
    778      1.1   elric 
    779      1.1   elric     return ret;
    780      1.1   elric }
    781      1.1   elric 
    782      1.1   elric /*
    783      1.1   elric  * Read a `nop' log operation from `sp' and apply it.
    784      1.1   elric  */
    785      1.1   elric 
    786      1.1   elric static kadm5_ret_t
    787      1.1   elric kadm5_log_replay_nop (kadm5_server_context *context,
    788      1.1   elric 		      uint32_t ver,
    789      1.1   elric 		      uint32_t len,
    790      1.1   elric 		      krb5_storage *sp)
    791      1.1   elric {
    792      1.1   elric     return 0;
    793      1.1   elric }
    794      1.1   elric 
    795      1.1   elric /*
    796      1.1   elric  * Call `func' for each log record in the log in `context'
    797      1.1   elric  */
    798      1.1   elric 
    799      1.1   elric kadm5_ret_t
    800      1.1   elric kadm5_log_foreach (kadm5_server_context *context,
    801      1.1   elric 		   void (*func)(kadm5_server_context *server_context,
    802      1.1   elric 				uint32_t ver,
    803      1.1   elric 				time_t timestamp,
    804      1.1   elric 				enum kadm_ops op,
    805      1.1   elric 				uint32_t len,
    806      1.1   elric 				krb5_storage *,
    807      1.1   elric 				void *),
    808      1.1   elric 		   void *ctx)
    809      1.1   elric {
    810      1.1   elric     int fd = context->log_context.log_fd;
    811      1.1   elric     krb5_storage *sp;
    812      1.1   elric 
    813      1.1   elric     lseek (fd, 0, SEEK_SET);
    814      1.1   elric     sp = krb5_storage_from_fd (fd);
    815      1.1   elric     for (;;) {
    816      1.1   elric 	int32_t ver, timestamp, op, len, len2, ver2;
    817      1.1   elric 
    818      1.1   elric 	if(krb5_ret_int32 (sp, &ver) != 0)
    819      1.1   elric 	    break;
    820      1.1   elric 	krb5_ret_int32 (sp, &timestamp);
    821      1.1   elric 	krb5_ret_int32 (sp, &op);
    822      1.1   elric 	krb5_ret_int32 (sp, &len);
    823      1.1   elric 	(*func)(context, ver, timestamp, op, len, sp, ctx);
    824      1.1   elric 	krb5_ret_int32 (sp, &len2);
    825      1.1   elric 	krb5_ret_int32 (sp, &ver2);
    826      1.1   elric 	if (len != len2)
    827      1.1   elric 	    abort();
    828      1.1   elric 	if (ver != ver2)
    829      1.1   elric 	    abort();
    830      1.1   elric     }
    831      1.1   elric     krb5_storage_free(sp);
    832      1.1   elric     return 0;
    833      1.1   elric }
    834      1.1   elric 
    835      1.1   elric /*
    836      1.1   elric  * Go to end of log.
    837      1.1   elric  */
    838      1.1   elric 
    839      1.1   elric krb5_storage *
    840      1.1   elric kadm5_log_goto_end (int fd)
    841      1.1   elric {
    842      1.1   elric     krb5_storage *sp;
    843      1.1   elric 
    844      1.1   elric     sp = krb5_storage_from_fd (fd);
    845      1.1   elric     krb5_storage_seek(sp, 0, SEEK_END);
    846      1.1   elric     return sp;
    847      1.1   elric }
    848      1.1   elric 
    849      1.1   elric /*
    850      1.1   elric  * Return previous log entry.
    851      1.1   elric  *
    852      1.1   elric  * The pointer in `sp is assumed to be at the top of the entry before
    853      1.1   elric  * previous entry. On success, the `sp pointer is set to data portion
    854      1.1   elric  * of previous entry. In case of error, it's not changed at all.
    855      1.1   elric  */
    856      1.1   elric 
    857      1.1   elric kadm5_ret_t
    858      1.1   elric kadm5_log_previous (krb5_context context,
    859      1.1   elric 		    krb5_storage *sp,
    860      1.1   elric 		    uint32_t *ver,
    861      1.1   elric 		    time_t *timestamp,
    862      1.1   elric 		    enum kadm_ops *op,
    863      1.1   elric 		    uint32_t *len)
    864      1.1   elric {
    865      1.1   elric     krb5_error_code ret;
    866      1.1   elric     off_t off, oldoff;
    867      1.1   elric     int32_t tmp;
    868      1.1   elric 
    869      1.1   elric     oldoff = krb5_storage_seek(sp, 0, SEEK_CUR);
    870      1.1   elric 
    871      1.1   elric     krb5_storage_seek(sp, -8, SEEK_CUR);
    872      1.1   elric     ret = krb5_ret_int32 (sp, &tmp);
    873      1.1   elric     if (ret)
    874      1.1   elric 	goto end_of_storage;
    875      1.1   elric     *len = tmp;
    876      1.1   elric     ret = krb5_ret_int32 (sp, &tmp);
    877      1.1   elric     if (ret)
    878      1.1   elric 	goto end_of_storage;
    879      1.1   elric     *ver = tmp;
    880      1.1   elric     off = 24 + *len;
    881      1.1   elric     krb5_storage_seek(sp, -off, SEEK_CUR);
    882      1.1   elric     ret = krb5_ret_int32 (sp, &tmp);
    883      1.1   elric     if (ret)
    884      1.1   elric 	goto end_of_storage;
    885  1.1.1.2  pettai     if ((uint32_t)tmp != *ver) {
    886      1.1   elric 	krb5_storage_seek(sp, oldoff, SEEK_SET);
    887      1.1   elric 	krb5_set_error_message(context, KADM5_BAD_DB,
    888      1.1   elric 			       "kadm5_log_previous: log entry "
    889      1.1   elric 			       "have consistency failure, version number wrong "
    890      1.1   elric 			       "(tmp %lu ver %lu)",
    891      1.1   elric 			       (unsigned long)tmp,
    892      1.1   elric 			       (unsigned long)*ver);
    893      1.1   elric 	return KADM5_BAD_DB;
    894      1.1   elric     }
    895      1.1   elric     ret = krb5_ret_int32 (sp, &tmp);
    896      1.1   elric     if (ret)
    897      1.1   elric 	goto end_of_storage;
    898      1.1   elric     *timestamp = tmp;
    899      1.1   elric     ret = krb5_ret_int32 (sp, &tmp);
    900      1.1   elric     if (ret)
    901      1.1   elric 	goto end_of_storage;
    902      1.1   elric     *op = tmp;
    903      1.1   elric     ret = krb5_ret_int32 (sp, &tmp);
    904      1.1   elric     if (ret)
    905      1.1   elric 	goto end_of_storage;
    906  1.1.1.2  pettai     if ((uint32_t)tmp != *len) {
    907      1.1   elric 	krb5_storage_seek(sp, oldoff, SEEK_SET);
    908      1.1   elric 	krb5_set_error_message(context, KADM5_BAD_DB,
    909      1.1   elric 			       "kadm5_log_previous: log entry "
    910      1.1   elric 			       "have consistency failure, length wrong");
    911      1.1   elric 	return KADM5_BAD_DB;
    912      1.1   elric     }
    913      1.1   elric     return 0;
    914      1.1   elric 
    915      1.1   elric  end_of_storage:
    916      1.1   elric     krb5_storage_seek(sp, oldoff, SEEK_SET);
    917      1.1   elric     krb5_set_error_message(context, ret, "kadm5_log_previous: end of storage "
    918      1.1   elric 			   "reached before end");
    919      1.1   elric     return ret;
    920      1.1   elric }
    921      1.1   elric 
    922      1.1   elric /*
    923      1.1   elric  * Replay a record from the log
    924      1.1   elric  */
    925      1.1   elric 
    926      1.1   elric kadm5_ret_t
    927      1.1   elric kadm5_log_replay (kadm5_server_context *context,
    928      1.1   elric 		  enum kadm_ops op,
    929      1.1   elric 		  uint32_t ver,
    930      1.1   elric 		  uint32_t len,
    931      1.1   elric 		  krb5_storage *sp)
    932      1.1   elric {
    933      1.1   elric     switch (op) {
    934      1.1   elric     case kadm_create :
    935      1.1   elric 	return kadm5_log_replay_create (context, ver, len, sp);
    936      1.1   elric     case kadm_delete :
    937      1.1   elric 	return kadm5_log_replay_delete (context, ver, len, sp);
    938      1.1   elric     case kadm_rename :
    939      1.1   elric 	return kadm5_log_replay_rename (context, ver, len, sp);
    940      1.1   elric     case kadm_modify :
    941      1.1   elric 	return kadm5_log_replay_modify (context, ver, len, sp);
    942      1.1   elric     case kadm_nop :
    943      1.1   elric 	return kadm5_log_replay_nop (context, ver, len, sp);
    944      1.1   elric     default :
    945      1.1   elric 	krb5_set_error_message(context->context, KADM5_FAILURE,
    946      1.1   elric 			       "Unsupported replay op %d", (int)op);
    947      1.1   elric 	return KADM5_FAILURE;
    948      1.1   elric     }
    949      1.1   elric }
    950      1.1   elric 
    951      1.1   elric /*
    952      1.1   elric  * truncate the log - i.e. create an empty file with just (nop vno + 2)
    953      1.1   elric  */
    954      1.1   elric 
    955      1.1   elric kadm5_ret_t
    956      1.1   elric kadm5_log_truncate (kadm5_server_context *server_context)
    957      1.1   elric {
    958      1.1   elric     kadm5_ret_t ret;
    959      1.1   elric     uint32_t vno;
    960      1.1   elric 
    961      1.1   elric     ret = kadm5_log_init (server_context);
    962      1.1   elric     if (ret)
    963      1.1   elric 	return ret;
    964      1.1   elric 
    965      1.1   elric     ret = kadm5_log_get_version (server_context, &vno);
    966      1.1   elric     if (ret)
    967      1.1   elric 	return ret;
    968      1.1   elric 
    969      1.1   elric     ret = kadm5_log_reinit (server_context);
    970      1.1   elric     if (ret)
    971      1.1   elric 	return ret;
    972      1.1   elric 
    973      1.1   elric     ret = kadm5_log_set_version (server_context, vno);
    974      1.1   elric     if (ret)
    975      1.1   elric 	return ret;
    976      1.1   elric 
    977      1.1   elric     ret = kadm5_log_nop (server_context);
    978      1.1   elric     if (ret)
    979      1.1   elric 	return ret;
    980      1.1   elric 
    981      1.1   elric     ret = kadm5_log_end (server_context);
    982      1.1   elric     if (ret)
    983      1.1   elric 	return ret;
    984      1.1   elric     return 0;
    985      1.1   elric 
    986      1.1   elric }
    987      1.1   elric 
    988      1.1   elric #ifndef NO_UNIX_SOCKETS
    989      1.1   elric 
    990      1.1   elric static char *default_signal = NULL;
    991      1.1   elric static HEIMDAL_MUTEX signal_mutex = HEIMDAL_MUTEX_INITIALIZER;
    992      1.1   elric 
    993      1.1   elric const char *
    994      1.1   elric kadm5_log_signal_socket(krb5_context context)
    995      1.1   elric {
    996      1.1   elric     HEIMDAL_MUTEX_lock(&signal_mutex);
    997      1.1   elric     if (!default_signal)
    998      1.1   elric 	asprintf(&default_signal, "%s/signal", hdb_db_dir(context));
    999      1.1   elric     HEIMDAL_MUTEX_unlock(&signal_mutex);
   1000      1.1   elric 
   1001      1.1   elric     return krb5_config_get_string_default(context,
   1002      1.1   elric 					  NULL,
   1003      1.1   elric 					  default_signal,
   1004      1.1   elric 					  "kdc",
   1005      1.1   elric 					  "signal_socket",
   1006      1.1   elric 					  NULL);
   1007      1.1   elric }
   1008      1.1   elric 
   1009      1.1   elric #else  /* NO_UNIX_SOCKETS */
   1010      1.1   elric 
   1011      1.1   elric #define SIGNAL_SOCKET_HOST "127.0.0.1"
   1012      1.1   elric #define SIGNAL_SOCKET_PORT "12701"
   1013      1.1   elric 
   1014      1.1   elric kadm5_ret_t
   1015      1.1   elric kadm5_log_signal_socket_info(krb5_context context,
   1016      1.1   elric 			     int server_end,
   1017      1.1   elric 			     struct addrinfo **ret_addrs)
   1018      1.1   elric {
   1019      1.1   elric     struct addrinfo hints;
   1020      1.1   elric     struct addrinfo *addrs = NULL;
   1021      1.1   elric     kadm5_ret_t ret = KADM5_FAILURE;
   1022      1.1   elric     int wsret;
   1023      1.1   elric 
   1024      1.1   elric     memset(&hints, 0, sizeof(hints));
   1025      1.1   elric 
   1026      1.1   elric     hints.ai_flags = AI_NUMERICHOST;
   1027      1.1   elric     if (server_end)
   1028      1.1   elric 	hints.ai_flags |= AI_PASSIVE;
   1029      1.1   elric     hints.ai_family = AF_INET;
   1030      1.1   elric     hints.ai_socktype = SOCK_STREAM;
   1031      1.1   elric     hints.ai_protocol = IPPROTO_TCP;
   1032      1.1   elric 
   1033      1.1   elric     wsret = getaddrinfo(SIGNAL_SOCKET_HOST,
   1034      1.1   elric 			SIGNAL_SOCKET_PORT,
   1035      1.1   elric 			&hints, &addrs);
   1036      1.1   elric 
   1037      1.1   elric     if (wsret != 0) {
   1038      1.1   elric 	krb5_set_error_message(context, KADM5_FAILURE,
   1039      1.1   elric 			       "%s", gai_strerror(wsret));
   1040      1.1   elric 	goto done;
   1041      1.1   elric     }
   1042      1.1   elric 
   1043      1.1   elric     if (addrs == NULL) {
   1044      1.1   elric 	krb5_set_error_message(context, KADM5_FAILURE,
   1045      1.1   elric 			       "getaddrinfo() failed to return address list");
   1046      1.1   elric 	goto done;
   1047      1.1   elric     }
   1048      1.1   elric 
   1049      1.1   elric     *ret_addrs = addrs;
   1050      1.1   elric     addrs = NULL;
   1051      1.1   elric     ret = 0;
   1052      1.1   elric 
   1053      1.1   elric  done:
   1054      1.1   elric     if (addrs)
   1055      1.1   elric 	freeaddrinfo(addrs);
   1056      1.1   elric     return ret;
   1057      1.1   elric }
   1058      1.1   elric 
   1059      1.1   elric #endif
   1060