1/*	$NetBSD: test_ap-req.c,v 1.2 2017/01/28 21:31:49 christos Exp $	*/
2
3/*
4 * Copyright (c) 2006 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 KTH nor the names of its contributors may be
20 *    used to endorse or promote products derived from this software without
21 *    specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
34
35#include <config.h>
36
37#include <sys/types.h>
38#include <stdio.h>
39#include <krb5/krb5.h>
40#include <err.h>
41#include <krb5/getarg.h>
42#include <krb5/roken.h>
43
44static int verify_pac = 0;
45static int server_any = 0;
46static int version_flag = 0;
47static int help_flag	= 0;
48
49static struct getargs args[] = {
50    {"verify-pac",0,	arg_flag,	&verify_pac,
51     "verify the PAC", NULL },
52    {"server-any",0,	arg_flag,	&server_any,
53     "let server pick the principal", NULL },
54    {"version",	0,	arg_flag,	&version_flag,
55     "print version", NULL },
56    {"help",	0,	arg_flag,	&help_flag,
57     NULL, NULL }
58};
59
60static void
61usage (int ret)
62{
63    arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "...");
64    exit (ret);
65}
66
67
68static void
69test_ap(krb5_context context,
70	krb5_principal target,
71	krb5_principal server,
72	krb5_keytab keytab,
73	krb5_ccache ccache,
74	const krb5_flags client_flags)
75{
76    krb5_error_code ret;
77    krb5_auth_context client_ac = NULL, server_ac = NULL;
78    krb5_data data;
79    krb5_flags server_flags;
80    krb5_ticket *ticket = NULL;
81    int32_t server_seq, client_seq;
82
83    ret = krb5_mk_req_exact(context,
84			    &client_ac,
85			    client_flags,
86			    target,
87			    NULL,
88			    ccache,
89			    &data);
90    if (ret)
91	krb5_err(context, 1, ret, "krb5_mk_req_exact");
92
93    ret = krb5_rd_req(context,
94		      &server_ac,
95		      &data,
96		      server,
97		      keytab,
98		      &server_flags,
99		      &ticket);
100    if (ret)
101	krb5_err(context, 1, ret, "krb5_rd_req");
102
103
104    if (server_flags & AP_OPTS_MUTUAL_REQUIRED) {
105	krb5_ap_rep_enc_part *repl;
106
107	krb5_data_free(&data);
108
109	if ((client_flags & AP_OPTS_MUTUAL_REQUIRED) == 0)
110	    krb5_errx(context, 1, "client flag missing mutual req");
111
112	ret = krb5_mk_rep (context, server_ac, &data);
113	if (ret)
114	    krb5_err(context, 1, ret, "krb5_mk_rep");
115
116	ret = krb5_rd_rep (context,
117			   client_ac,
118			   &data,
119			   &repl);
120	if (ret)
121	    krb5_err(context, 1, ret, "krb5_rd_rep");
122
123	krb5_free_ap_rep_enc_part (context, repl);
124    } else {
125	if (client_flags & AP_OPTS_MUTUAL_REQUIRED)
126	    krb5_errx(context, 1, "server flag missing mutual req");
127    }
128
129    krb5_auth_con_getremoteseqnumber(context, server_ac, &server_seq);
130    krb5_auth_con_getremoteseqnumber(context, client_ac, &client_seq);
131    if (server_seq != client_seq)
132	krb5_errx(context, 1, "seq num differ");
133
134    krb5_auth_con_getlocalseqnumber(context, server_ac, &server_seq);
135    krb5_auth_con_getlocalseqnumber(context, client_ac, &client_seq);
136    if (server_seq != client_seq)
137	krb5_errx(context, 1, "seq num differ");
138
139    krb5_data_free(&data);
140    krb5_auth_con_free(context, client_ac);
141    krb5_auth_con_free(context, server_ac);
142
143    if (verify_pac) {
144	krb5_pac pac;
145
146	ret = krb5_ticket_get_authorization_data_type(context,
147						      ticket,
148						      KRB5_AUTHDATA_WIN2K_PAC,
149						      &data);
150	if (ret)
151	    krb5_err(context, 1, ret, "get pac");
152
153	ret = krb5_pac_parse(context, data.data, data.length, &pac);
154	if (ret)
155	    krb5_err(context, 1, ret, "pac parse");
156
157	krb5_pac_free(context, pac);
158    }
159
160    krb5_free_ticket(context, ticket);
161}
162
163
164int
165main(int argc, char **argv)
166{
167    krb5_context context;
168    krb5_error_code ret;
169    int optidx = 0;
170    const char *principal, *keytab, *ccache;
171    krb5_ccache id;
172    krb5_keytab kt;
173    krb5_principal sprincipal, server;
174
175    setprogname(argv[0]);
176
177    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
178	usage(1);
179
180    if (help_flag)
181	usage (0);
182
183    if(version_flag){
184	print_version(NULL);
185	exit(0);
186    }
187
188    argc -= optidx;
189    argv += optidx;
190
191    if (argc < 3)
192	usage(1);
193
194    principal = argv[0];
195    keytab = argv[1];
196    ccache = argv[2];
197
198    ret = krb5_init_context(&context);
199    if (ret)
200	errx (1, "krb5_init_context failed: %d", ret);
201
202    ret = krb5_cc_resolve(context, ccache, &id);
203    if (ret)
204	krb5_err(context, 1, ret, "krb5_cc_resolve");
205
206    ret = krb5_parse_name(context, principal, &sprincipal);
207    if (ret)
208	krb5_err(context, 1, ret, "krb5_parse_name");
209
210    ret = krb5_kt_resolve(context, keytab, &kt);
211    if (ret)
212	krb5_err(context, 1, ret, "krb5_kt_resolve");
213
214    if (server_any)
215	server = NULL;
216    else
217	server = sprincipal;
218
219    test_ap(context, sprincipal, server, kt, id, 0);
220    test_ap(context, sprincipal, server, kt, id, AP_OPTS_MUTUAL_REQUIRED);
221
222    krb5_cc_close(context, id);
223    krb5_kt_close(context, kt);
224    krb5_free_principal(context, sprincipal);
225
226    krb5_free_context(context);
227
228    return ret;
229}
230