xref: /netbsd-src/crypto/external/bsd/heimdal/dist/kdc/kdc-replay.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1 /*	$NetBSD: kdc-replay.c,v 1.3 2023/06/19 21:41:41 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2007 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include "kdc_locl.h"
37 
38 static int version_flag;
39 static int help_flag;
40 
41 struct getargs args[] = {
42     { "version",   0,	arg_flag, &version_flag, NULL, NULL },
43     { "help",     'h',	arg_flag, &help_flag,    NULL, NULL }
44 };
45 
46 static const int num_args = sizeof(args) / sizeof(args[0]);
47 
48 static void
usage(int ret)49 usage(int ret)
50 {
51     arg_printusage (args, num_args, NULL, "kdc-request-log-file");
52     exit (ret);
53 }
54 
55 int
main(int argc,char ** argv)56 main(int argc, char **argv)
57 {
58     krb5_error_code ret;
59     krb5_context context;
60     krb5_kdc_configuration *config;
61     krb5_storage *sp;
62     int fd, optidx = 0;
63 
64     setprogname(argv[0]);
65 
66     if(getarg(args, num_args, argc, argv, &optidx))
67 	usage(1);
68 
69     if(help_flag)
70 	usage(0);
71 
72     if(version_flag){
73 	print_version(NULL);
74 	exit(0);
75     }
76 
77     ret = krb5_init_context(&context);
78     if (ret)
79 	errx (1, "krb5_init_context failed to parse configuration file");
80 
81     ret = krb5_kdc_get_config(context, &config);
82     if (ret)
83 	krb5_err(context, 1, ret, "krb5_kdc_default_config");
84 
85     kdc_openlog(context, "kdc-replay", config);
86 
87     ret = krb5_kdc_set_dbinfo(context, config);
88     if (ret)
89 	krb5_err(context, 1, ret, "krb5_kdc_set_dbinfo");
90 
91 #ifdef PKINIT
92     if (config->enable_pkinit) {
93 	if (config->pkinit_kdc_identity == NULL)
94 	    krb5_errx(context, 1, "pkinit enabled but no identity");
95 
96 	if (config->pkinit_kdc_anchors == NULL)
97 	    krb5_errx(context, 1, "pkinit enabled but no X509 anchors");
98 
99 	krb5_kdc_pk_initialize(context, config,
100 			       config->pkinit_kdc_identity,
101 			       config->pkinit_kdc_anchors,
102 			       config->pkinit_kdc_cert_pool,
103 			       config->pkinit_kdc_revoke);
104 
105     }
106 #endif /* PKINIT */
107 
108     if (argc != 2)
109 	errx(1, "argc != 2");
110 
111     printf("kdc replay\n");
112 
113     fd = open(argv[1], O_RDONLY);
114     if (fd < 0)
115 	err(1, "open: %s", argv[1]);
116 
117     sp = krb5_storage_from_fd(fd);
118     if (sp == NULL)
119 	krb5_errx(context, 1, "krb5_storage_from_fd");
120 
121     while(1) {
122 	struct sockaddr_storage sa;
123 	krb5_socklen_t salen = sizeof(sa);
124 	struct timeval tv;
125 	krb5_address a;
126 	krb5_data d, r;
127 	uint32_t t, clty, tag;
128 	char astr[80];
129 
130 	ret = krb5_ret_uint32(sp, &t);
131 	if (ret == HEIM_ERR_EOF)
132 	    break;
133 	else if (ret)
134 	    krb5_errx(context, 1, "krb5_ret_uint32(version)");
135 	if (t != 1)
136 	    krb5_errx(context, 1, "version not 1");
137 	ret = krb5_ret_uint32(sp, &t);
138 	if (ret)
139 	    krb5_errx(context, 1, "krb5_ret_uint32(time)");
140 	ret = krb5_ret_address(sp, &a);
141 	if (ret)
142 	    krb5_errx(context, 1, "krb5_ret_address");
143 	ret = krb5_ret_data(sp, &d);
144 	if (ret)
145 	    krb5_errx(context, 1, "krb5_ret_data");
146 	ret = krb5_ret_uint32(sp, &clty);
147 	if (ret)
148 	    krb5_errx(context, 1, "krb5_ret_uint32(class|type)");
149 	ret = krb5_ret_uint32(sp, &tag);
150 	if (ret)
151 	    krb5_errx(context, 1, "krb5_ret_uint32(tag)");
152 
153 
154 	ret = krb5_addr2sockaddr (context, &a, (struct sockaddr *)&sa,
155 				  &salen, 88);
156 	if (ret == KRB5_PROG_ATYPE_NOSUPP)
157 	    goto out;
158 	else if (ret)
159 	    krb5_err(context, 1, ret, "krb5_addr2sockaddr");
160 
161 	ret = krb5_print_address(&a, astr, sizeof(astr), NULL);
162 	if (ret)
163 	    krb5_err(context, 1, ret, "krb5_print_address");
164 
165 	printf("processing request from %s, %lu bytes\n",
166 	       astr, (unsigned long)d.length);
167 
168 	r.length = 0;
169 	r.data = NULL;
170 
171 	tv.tv_sec = t;
172 	tv.tv_usec = 0;
173 
174 	krb5_kdc_update_time(&tv);
175 	krb5_set_real_time(context, tv.tv_sec, 0);
176 
177 	ret = krb5_kdc_process_request(context, config, d.data, d.length,
178 				       &r, NULL, astr,
179 				       (struct sockaddr *)&sa, 0);
180 	if (ret)
181 	    krb5_err(context, 1, ret, "krb5_kdc_process_request");
182 
183 	if (r.length) {
184 	    Der_class cl;
185 	    Der_type ty;
186 	    unsigned int tag2;
187 	    ret = der_get_tag (r.data, r.length,
188 			       &cl, &ty, &tag2, NULL);
189             if (ret)
190                 krb5_err(context, 1, ret, "Could not decode replay data");
191 	    if (MAKE_TAG(cl, ty, 0) != clty)
192 		krb5_errx(context, 1, "class|type mismatch: %d != %d",
193 			  (int)MAKE_TAG(cl, ty, 0), (int)clty);
194 	    if (tag != tag2)
195 		krb5_errx(context, 1, "tag mismatch");
196 
197 	    krb5_data_free(&r);
198 	} else {
199 	    if (clty != 0xffffffff)
200 		krb5_errx(context, 1, "clty not invalid");
201 	    if (tag != 0xffffffff)
202 		krb5_errx(context, 1, "tag not invalid");
203 	}
204 
205     out:
206 	krb5_data_free(&d);
207 	krb5_free_address(context, &a);
208     }
209 
210     krb5_storage_free(sp);
211     krb5_free_context(context);
212 
213     printf("done\n");
214 
215     return 0;
216 }
217