#
# This patch is to provide internal log rotation functionality for both
# kadmind & krb5kdc daemons. The functionality is defined in krb5.conf
# man page via 'admin_server_rotate' & 'kdc_rotate' parameters.
#
# Following two relations can be specified:
#
# period = delta_time
# versions = number
#
# NOTE:
#
# MIT Kerberos Consortium did not accept new features for MIT kerberos 1.13
# release. For that matter, we would like to try to push this log rotation
# functionality in later MIT kerberos release, 1.14 or later.
# Patch source: in-house
#
--- a/src/lib/kadm5/logger.c
+++ b/src/lib/kadm5/logger.c
@@ -115,6 +115,13 @@ struct log_entry {
struct log_file {
FILE *lf_filep;
char *lf_fname;
+ /* Solaris Kerberos */
+ char *lf_fopen_mode; /* "a+" or "w" */
+#define K_LOG_DEF_FILE_ROTATE_PERIOD -1 /* never */
+#define K_LOG_DEF_FILE_ROTATE_VERSIONS 0 /* no versions */
+ time_t lf_rotate_period;
+ time_t lf_last_rotated;
+ int lf_rotate_versions;
} log_file;
struct log_syslog {
int ls_facility;
@@ -128,6 +135,11 @@ struct log_entry {
};
#define lfu_filep log_union.log_file.lf_filep
#define lfu_fname log_union.log_file.lf_fname
+/* Solaris Kerberos */
+#define lfu_fopen_mode log_union.log_file.lf_fopen_mode
+#define lfu_rotate_period log_union.log_file.lf_rotate_period
+#define lfu_last_rotated log_union.log_file.lf_last_rotated
+#define lfu_rotate_versions log_union.log_file.lf_rotate_versions
#define lsu_facility log_union.log_syslog.ls_facility
#define lsu_severity log_union.log_syslog.ls_severity
#define ldu_filep log_union.log_device.ld_filep
@@ -161,6 +173,132 @@ static struct log_entry def_log_entry;
-1)
#define DEVICE_CLOSE(d) fclose(d)
+/*
+ * Solaris Kerberos
+ * klog_rotate() - roate a log file if we have specified rotation
+ * parameters in krb5.conf.
+ */
+static void
+klog_rotate(struct log_entry *le)
+{
+ time_t t;
+ int i;
+ char *name_buf1;
+ char *name_buf2;
+ char *old_name;
+ char *new_name;
+ char *tmp;
+ FILE *fp;
+ int num_vers;
+ mode_t old_umask;
+
+ /*
+ * By default we don't rotate.
+ */
+ if (le->lfu_rotate_period == K_LOG_DEF_FILE_ROTATE_PERIOD)
+ return;
+
+ t = time(0);
+
+ if (t >= le->lfu_last_rotated + le->lfu_rotate_period) {
+ /*
+ * The N log file versions will be renamed X.N-1 X.N-2, ... X.0.
+ * So the allocate file name buffers that can the version
+ * number extensions.
+ * 32 extra bytes is plenty.
+ */
+ name_buf1 = malloc(strlen(le->lfu_fname) + 32);
+
+ if (name_buf1 == NULL)
+ return;
+
+ name_buf2 = malloc(strlen(le->lfu_fname) + 32);
+
+ if (name_buf2 == NULL) {
+ free(name_buf1);
+ return;
+ }
+
+ old_name = name_buf1;
+ new_name = name_buf2;
+
+ /*
+ * If there N versions, then the first one has file extension
+ * of N-1.
+ */
+ (void) sprintf(new_name, "%s.%d", le->lfu_fname,
+ le->lfu_rotate_versions - 1);
+
+ /*
+ * Rename file.N-2 to file.N-1, file.N-3 to file.N-2, ...
+ * file.0 to file.1
+ */
+ for (i = le->lfu_rotate_versions - 1; i > 0; i--) {
+ (void) sprintf(old_name, "%s.%d", le->lfu_fname, i - 1);
+ (void) rename(old_name, new_name);
+
+ /*
+ * swap old name and new name. This way,
+ * on the next iteration, new_name.X
+ * becomes new_name.X-1.
+ */
+ tmp = old_name;
+ old_name = new_name;
+ new_name = tmp;
+ }
+ old_name = le->lfu_fname;
+
+ (void) rename(old_name, new_name);
+
+ /*
+ * Even though we don't know yet if the fopen()
+ * of the log file will succeed, we mark the log
+ * as rotated. This is so we don't repeatably
+ * rotate file.N-2 to file.N-1 ... etc without
+ * waiting for the rotate period to elapse.
+ */
+ le->lfu_last_rotated = t;
+
+ /*
+ * Default log file creation mode should be read-only
+ * by owner(root), but the admin can override with
+ * chmod(1) if desired.
+ */
+
+ old_umask = umask(077);
+ fp = fopen(old_name, le->lfu_fopen_mode);
+
+ umask(old_umask);
+
+ if (fp != NULL) {
+
+ (void) fclose(le->lfu_filep);
+ le->lfu_filep = fp;
+
+ /*
+ * If the version parameter in krb5.conf was
+ * 0, then we take this to mean that rotating the
+ * log file will cause us to dispose of the
+ * old one, and created a new one. We have just
+ * renamed the old one to file.-1, so remove it.
+ */
+ if (le->lfu_rotate_versions <= 0)
+ (void) unlink(new_name);
+
+ } else {
+ fprintf(stderr,
+ _("During rotate, couldn't open log file %s: %s\n"),
+ old_name, error_message(errno));
+ /*
+ * Put it back.
+ */
+ (void) rename(new_name, old_name);
+ }
+ free(name_buf1);
+ free(name_buf2);
+ }
+}
+
/*
* klog_com_err_proc() - Handle com_err(3) messages as specified by the
@@ -276,6 +414,8 @@ klog_com_err_proc(const char *whoami, long int code, const char *format, va_list
for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
switch (log_control.log_entries[lindex].log_type) {
case K_LOG_FILE:
+ /* Solaris Kerberos */
+ klog_rotate(&log_control.log_entries[lindex]);
case K_LOG_STDERR:
/*
* Files/standard error.
@@ -360,6 +500,7 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
int error;
int do_openlog, log_facility;
FILE *f;
+ mode_t old_umask;
/* Initialize */
do_openlog = 0;
@@ -423,12 +564,66 @@ krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do
* Check for append/overwrite, then open the file.
*/
if (cp[4] == ':' || cp[4] == '=') {
- f = fopen(&cp[5], (cp[4] == ':') ? "a" : "w");
+ /* Solaris Kerberos */
+ log_control.log_entries[i].lfu_fopen_mode =
+ (cp[4] == ':') ? "a" : "w";
+ old_umask = umask(077);
+ f = fopen(&cp[5],
+ log_control.log_entries[i].lfu_fopen_mode);
+ umask(old_umask);
if (f) {
- set_cloexec_file(f);
+ char rotate_kw[128];
log_control.log_entries[i].lfu_filep = f;
log_control.log_entries[i].log_type = K_LOG_FILE;
log_control.log_entries[i].lfu_fname = &cp[5];
+ log_control.log_entries[i].lfu_rotate_period =
+ K_LOG_DEF_FILE_ROTATE_PERIOD;
+ log_control.log_entries[i].lfu_rotate_versions =
+ K_LOG_DEF_FILE_ROTATE_VERSIONS;
+ log_control.log_entries[i].lfu_last_rotated =
+ time(0);
+
+ /*
+ * Now parse for ename_"rotate" = {
+ * period = XXX
+ * versions = 10
+ * }
+ */
+ if (strlen(ename) + strlen("_rotate") <
+ sizeof (rotate_kw)) {
+
+ char *time;
+ krb5_deltat dt;
+ int vers;
+
+ strcpy(rotate_kw, ename);
+ strcat(rotate_kw, "_rotate");
+
+ if (!profile_get_string(kcontext->profile,
+ "logging", rotate_kw,
+ "period", NULL,
+ &time)) {
+
+ if (time != NULL) {
+ if (!krb5_string_to_deltat(time,
+ &dt)) {
+ log_control.log_entries[i].lfu_rotate_period =
+ (time_t) dt;
+ }
+ free(time);
+ }
+ }
+
+ if (!profile_get_integer(
+ kcontext->profile,
+ "logging", rotate_kw,
+ "versions",
+ K_LOG_DEF_FILE_ROTATE_VERSIONS,
+ &vers)) {
+ log_control.log_entries[i].lfu_rotate_versions = vers;
+ }
+
+ }
} else {
fprintf(stderr,"Couldn't open log file %s: %s\n",
&cp[5], error_message(errno));
@@ -880,6 +1075,8 @@ klog_vsyslog(int priority, const char *format, va_list arglist)
for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
switch (log_control.log_entries[lindex].log_type) {
case K_LOG_FILE:
+ /* Solaris Kerberos */
+ klog_rotate(&log_control.log_entries[lindex]);
case K_LOG_STDERR:
/*
* Files/standard error.