Home | History | Annotate | Line # | Download | only in kadm5
log.c revision 1.1.1.1.10.1
      1           1.1  elric /*	$NetBSD: log.c,v 1.1.1.1.10.1 2014/08/19 23:45:19 tls 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.1.10.1    tls __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.1.10.1    tls     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.1.10.1    tls     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.1.10.1    tls         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.1.10.1    tls         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.1.10.1    tls         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.1.10.1    tls         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.1.10.1    tls         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.1.10.1    tls         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.1.10.1    tls         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.1.10.1    tls         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.1.10.1    tls 	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.1.10.1    tls     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.1.10.1    tls     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