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