1 /*
2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * This module will parse the update logs on the master or slave servers.
8  */
9 
10 #include <stdio.h>
11 #include <libintl.h>
12 #include <sys/types.h>
13 #include <time.h>
14 #include <limits.h>
15 #include <locale.h>
16 #include <syslog.h>
17 #include <kdb/kdb_log.h>
18 #include <kadm5/admin.h>
19 
20 static char	*progname;
21 
22 static void
usage()23 usage()
24 {
25 	(void) fprintf(stderr, gettext("\nUsage: %s [-h] [-v] [-e num]\n\n"),
26 	    progname);
27 	exit(1);
28 }
29 
30 /*
31  * Print the individual types if verbose mode was specified.
32  */
33 static void
print_attr(kdbe_attr_type_t type)34 print_attr(kdbe_attr_type_t type)
35 {
36 	switch (type) {
37 		case AT_ATTRFLAGS:
38 			(void) printf(gettext("\t\tAttribute flags\n"));
39 			break;
40 		case AT_MAX_LIFE:
41 			(void) printf(gettext("\t\tMaximum ticket life\n"));
42 			break;
43 		case AT_MAX_RENEW_LIFE:
44 			(void) printf(gettext("\t\tMaximum renewable life\n"));
45 			break;
46 		case AT_EXP:
47 			(void) printf(gettext("\t\tPrincipal expiration\n"));
48 			break;
49 		case AT_PW_EXP:
50 			(void) printf(gettext("\t\tPassword expiration\n"));
51 			break;
52 		case AT_LAST_SUCCESS:
53 			(void) printf(gettext("\t\tLast successful auth\n"));
54 			break;
55 		case AT_LAST_FAILED:
56 			(void) printf(gettext("\t\tLast failed auth\n"));
57 			break;
58 		case AT_FAIL_AUTH_COUNT:
59 			(void) printf(gettext("\t\tFailed passwd attempt\n"));
60 			break;
61 		case AT_PRINC:
62 			(void) printf(gettext("\t\tPrincipal\n"));
63 			break;
64 		case AT_KEYDATA:
65 			(void) printf(gettext("\t\tKey data\n"));
66 			break;
67 		case AT_TL_DATA:
68 			(void) printf(gettext("\t\tTL data\n"));
69 			break;
70 		case AT_LEN:
71 			(void) printf(gettext("\t\tLength\n"));
72 			break;
73 		case AT_MOD_PRINC:
74 			(void) printf(gettext("\t\tModifying principal\n"));
75 			break;
76 		case AT_MOD_TIME:
77 			(void) printf(gettext("\t\tModification time\n"));
78 			break;
79 		case AT_MOD_WHERE:
80 			(void) printf(gettext("\t\tModified where\n"));
81 			break;
82 		case AT_PW_LAST_CHANGE:
83 			(void) printf(gettext("\t\tPassword last changed\n"));
84 			break;
85 		case AT_PW_POLICY:
86 			(void) printf(gettext("\t\tPassword policy\n"));
87 			break;
88 		case AT_PW_POLICY_SWITCH:
89 			(void) printf(gettext("\t\tPassword policy switch\n"));
90 			break;
91 		case AT_PW_HIST_KVNO:
92 			(void) printf(gettext("\t\tPassword history KVNO\n"));
93 			break;
94 		case AT_PW_HIST:
95 			(void) printf(gettext("\t\tPassword history\n"));
96 			break;
97 	} /* switch */
98 
99 }
100 /*
101  * Print the update entry information
102  */
103 static void
print_update(kdb_hlog_t * ulog,uint32_t entry,bool_t verbose)104 print_update(kdb_hlog_t *ulog, uint32_t entry, bool_t verbose)
105 {
106 	XDR		xdrs;
107 	uint32_t	start_sno, i, j, indx;
108 	char		*dbprinc;
109 	kdb_ent_header_t *indx_log;
110 	kdb_incr_update_t upd;
111 
112 	if (entry && (entry < ulog->kdb_num))
113 		start_sno = ulog->kdb_last_sno - entry;
114 	else
115 		start_sno = ulog->kdb_first_sno - 1;
116 
117 	for (i = start_sno; i < ulog->kdb_last_sno; i++) {
118 		indx = i % ulog->kdb_num;
119 
120 		indx_log = (kdb_ent_header_t *)INDEX(ulog, indx);
121 
122 		/*
123 		 * Check for corrupt update entry
124 		 */
125 		if (indx_log->kdb_umagic != KDB_UMAGIC) {
126 			(void) fprintf(stderr,
127 			    gettext("Corrupt update entry\n\n"));
128 			exit(1);
129 		}
130 
131 		(void) memset((char *)&upd, 0, sizeof (kdb_incr_update_t));
132 		xdrmem_create(&xdrs, (char *)indx_log->entry_data,
133 		    indx_log->kdb_entry_size, XDR_DECODE);
134 		if (!xdr_kdb_incr_update_t(&xdrs, &upd)) {
135 			(void) printf(gettext("Entry data decode failure\n\n"));
136 			exit(1);
137 		}
138 
139 		(void) printf("---\n");
140 		(void) printf(gettext("Update Entry\n"));
141 
142 		(void) printf(gettext("\tUpdate serial # : %u\n"),
143 		    indx_log->kdb_entry_sno);
144 
145 		(void) printf(gettext("\tUpdate operation : "));
146 		if (upd.kdb_deleted)
147 			(void) printf(gettext("Delete\n"));
148 		else
149 			(void) printf(gettext("Add\n"));
150 
151 		dbprinc = malloc(upd.kdb_princ_name.utf8str_t_len + 1);
152 		if (dbprinc == NULL) {
153 			(void) printf(gettext("Could not allocate "
154 			    "principal name\n\n"));
155 			exit(1);
156 		}
157 		(void) strlcpy(dbprinc, upd.kdb_princ_name.utf8str_t_val,
158 		    (upd.kdb_princ_name.utf8str_t_len + 1));
159 		(void) printf(gettext("\tUpdate principal : %s\n"), dbprinc);
160 
161 		(void) printf(gettext("\tUpdate size : %u\n"),
162 		    indx_log->kdb_entry_size);
163 
164 		(void) printf(gettext("\tUpdate committed : %s\n"),
165 		    indx_log->kdb_commit ? "True" : "False");
166 
167 		if (indx_log->kdb_time.seconds == 0L)
168 			(void) printf(gettext("\tUpdate time stamp : None\n"));
169 		else
170 			(void) printf(gettext("\tUpdate time stamp : %s"),
171 			    ctime((time_t *)&(indx_log->kdb_time.seconds)));
172 
173 		(void) printf(gettext("\tAttributes changed : %d\n"),
174 		    upd.kdb_update.kdbe_t_len);
175 
176 		if (verbose)
177 			for (j = 0; j < upd.kdb_update.kdbe_t_len; j++)
178 				print_attr(
179 				    upd.kdb_update.kdbe_t_val[j].av_type);
180 
181 		xdr_free(xdr_kdb_incr_update_t, (char *)&upd);
182 		if (dbprinc)
183 			free(dbprinc);
184 	} /* for */
185 }
186 
187 int
main(int argc,char ** argv)188 main(int argc, char **argv)
189 {
190 	int			c;
191 	bool_t			verbose = FALSE;
192 	bool_t			headeronly = FALSE;
193 	uint32_t		entry = 0;
194 	krb5_context		context;
195 	kadm5_config_params	params;
196 	kdb_log_context		*log_ctx;
197 	kdb_hlog_t		*ulog = NULL;
198 
199 	(void) setlocale(LC_ALL, "");
200 
201 #if !defined(TEXT_DOMAIN)
202 #define	TEXT_DOMAIN "SYS_TEST"
203 #endif /* TEXT_DOMAIN */
204 
205 	(void) textdomain(TEXT_DOMAIN);
206 
207 	if (geteuid() != (uid_t)0) {
208 		(void) fprintf(stderr,
209 		    gettext("kproplog must be run as root\n\n"));
210 		exit(1);
211 	}
212 
213 	progname = argv[0];
214 
215 	while ((c = getopt(argc, argv, "vhe:")) != -1) {
216 		switch (c) {
217 			case 'h':
218 				headeronly = TRUE;
219 				break;
220 			case 'e':
221 				entry = atoi(optarg);
222 				break;
223 			case 'v':
224 				verbose = TRUE;
225 				break;
226 			default:
227 				usage();
228 		}
229 	}
230 
231 	if (krb5_init_context(&context)) {
232 		(void) fprintf(stderr,
233 		    gettext("Unable to initialize Kerberos\n\n"));
234 		exit(1);
235 	}
236 
237 	(void) memset((char *)&params, 0, sizeof (params));
238 
239 	if (kadm5_get_config_params(context, NULL, NULL, &params, &params)) {
240 		(void) fprintf(stderr,
241 		    gettext("Couldn't read database_name\n\n"));
242 		exit(1);
243 	}
244 
245 	(void) printf(gettext("\nKerberos update log (%s.ulog)\n"),
246 	    params.dbname);
247 
248 	if (ulog_map(context, &params, FKPROPLOG)) {
249 		(void) fprintf(stderr, gettext("Unable to map log file "
250 		    "%s.ulog\n\n"), params.dbname);
251 		exit(1);
252 	}
253 
254 	log_ctx = context->kdblog_context;
255 	if (log_ctx)
256 		ulog = log_ctx->ulog;
257 	else {
258 		(void) fprintf(stderr, gettext("Unable to map log file "
259 		    "%s.ulog\n\n"), params.dbname);
260 		exit(1);
261 	}
262 
263 	if (ulog->kdb_hmagic != KDB_HMAGIC) {
264 		(void) fprintf(stderr,
265 		    gettext("Corrupt header log, exiting\n\n"));
266 		exit(1);
267 	}
268 
269 	(void) printf(gettext("Update log dump :\n"));
270 	(void) printf(gettext("\tLog version # : %u\n"), ulog->db_version_num);
271 	(void) printf(gettext("\tLog state : "));
272 	switch (ulog->kdb_state) {
273 		case KDB_STABLE:
274 			(void) printf(gettext("Stable\n"));
275 			break;
276 		case KDB_UNSTABLE:
277 			(void) printf(gettext("Unstable\n"));
278 			break;
279 		case KDB_CORRUPT:
280 			(void) printf(gettext("Corrupt\n"));
281 			break;
282 		default:
283 			(void) printf(gettext("Unknown state: %d\n"),
284 			    ulog->kdb_state);
285 			break;
286 	}
287 	(void) printf(gettext("\tEntry block size : %u\n"), ulog->kdb_block);
288 	(void) printf(gettext("\tNumber of entries : %u\n"), ulog->kdb_num);
289 
290 	if (ulog->kdb_last_sno == 0)
291 		(void) printf(gettext("\tLast serial # : None\n"));
292 	else {
293 		if (ulog->kdb_first_sno == 0)
294 			(void) printf(gettext("\tFirst serial # : None\n"));
295 		else {
296 			(void) printf(gettext("\tFirst serial # : "));
297 			(void) printf("%u\n", ulog->kdb_first_sno);
298 		}
299 
300 		(void) printf(gettext("\tLast serial # : "));
301 		(void) printf("%u\n", ulog->kdb_last_sno);
302 	}
303 
304 	if (ulog->kdb_last_time.seconds == 0L) {
305 		(void) printf(gettext("\tLast time stamp : None\n"));
306 	} else {
307 		if (ulog->kdb_first_time.seconds == 0L)
308 			(void) printf(gettext("\tFirst time stamp : None\n"));
309 		else {
310 			(void) printf(gettext("\tFirst time stamp : %s"),
311 			    ctime((time_t *)
312 			    &(ulog->kdb_first_time.seconds)));
313 		}
314 
315 		(void) printf(gettext("\tLast time stamp : %s\n"),
316 		    ctime((time_t *)&(ulog->kdb_last_time.seconds)));
317 	}
318 
319 	if ((!headeronly) && ulog->kdb_num) {
320 		print_update(ulog, entry, verbose);
321 	}
322 
323 	(void) printf("\n");
324 
325 	return (0);
326 }
327