1bbd80c28SJacques Vidrine /*
2*ae771770SStanislav Sedov * Copyright (c) 2003-2007 Kungliga Tekniska Högskolan
3bbd80c28SJacques Vidrine * (Royal Institute of Technology, Stockholm, Sweden).
4bbd80c28SJacques Vidrine * All rights reserved.
5bbd80c28SJacques Vidrine *
6bbd80c28SJacques Vidrine * Redistribution and use in source and binary forms, with or without
7bbd80c28SJacques Vidrine * modification, are permitted provided that the following conditions
8bbd80c28SJacques Vidrine * are met:
9bbd80c28SJacques Vidrine *
10bbd80c28SJacques Vidrine * 1. Redistributions of source code must retain the above copyright
11bbd80c28SJacques Vidrine * notice, this list of conditions and the following disclaimer.
12bbd80c28SJacques Vidrine *
13bbd80c28SJacques Vidrine * 2. Redistributions in binary form must reproduce the above copyright
14bbd80c28SJacques Vidrine * notice, this list of conditions and the following disclaimer in the
15bbd80c28SJacques Vidrine * documentation and/or other materials provided with the distribution.
16bbd80c28SJacques Vidrine *
17bbd80c28SJacques Vidrine * 3. Neither the name of KTH nor the names of its contributors may be
18bbd80c28SJacques Vidrine * used to endorse or promote products derived from this software without
19bbd80c28SJacques Vidrine * specific prior written permission.
20bbd80c28SJacques Vidrine *
21bbd80c28SJacques Vidrine * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22bbd80c28SJacques Vidrine * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23bbd80c28SJacques Vidrine * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24bbd80c28SJacques Vidrine * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25bbd80c28SJacques Vidrine * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26bbd80c28SJacques Vidrine * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27bbd80c28SJacques Vidrine * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28bbd80c28SJacques Vidrine * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29bbd80c28SJacques Vidrine * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30bbd80c28SJacques Vidrine * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31c19800e8SDoug Rabson * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32c19800e8SDoug Rabson */
33bbd80c28SJacques Vidrine
34c19800e8SDoug Rabson #ifdef HAVE_CONFIG_H
35c19800e8SDoug Rabson #include <config.h>
36c19800e8SDoug Rabson #endif
37c19800e8SDoug Rabson
38*ae771770SStanislav Sedov #include <roken.h>
39c19800e8SDoug Rabson #include <stdio.h>
40c19800e8SDoug Rabson #include <stdlib.h>
41c19800e8SDoug Rabson #include <string.h>
42c19800e8SDoug Rabson #include <stdarg.h>
43c19800e8SDoug Rabson #include <gssapi.h>
44*ae771770SStanislav Sedov #include <gssapi_krb5.h>
45*ae771770SStanislav Sedov #include <gssapi_spnego.h>
46bbd80c28SJacques Vidrine #include <err.h>
47c19800e8SDoug Rabson #include <getarg.h>
48bbd80c28SJacques Vidrine
49c19800e8SDoug Rabson #include "test_common.h"
50c19800e8SDoug Rabson
51bbd80c28SJacques Vidrine static void
print_time(OM_uint32 time_rec)52bbd80c28SJacques Vidrine print_time(OM_uint32 time_rec)
53bbd80c28SJacques Vidrine {
54bbd80c28SJacques Vidrine if (time_rec == GSS_C_INDEFINITE) {
55bbd80c28SJacques Vidrine printf("cred never expire\n");
56bbd80c28SJacques Vidrine } else {
57c19800e8SDoug Rabson time_t t = time_rec + time(NULL);
58bbd80c28SJacques Vidrine printf("expiration time: %s", ctime(&t));
59bbd80c28SJacques Vidrine }
60bbd80c28SJacques Vidrine }
61bbd80c28SJacques Vidrine
62c19800e8SDoug Rabson #if 0
63c19800e8SDoug Rabson
64c19800e8SDoug Rabson static void
65c19800e8SDoug Rabson test_add(gss_cred_id_t cred_handle)
66bbd80c28SJacques Vidrine {
67bbd80c28SJacques Vidrine OM_uint32 major_status, minor_status;
68c19800e8SDoug Rabson gss_cred_id_t copy_cred;
69bbd80c28SJacques Vidrine OM_uint32 time_rec;
70bbd80c28SJacques Vidrine
71bbd80c28SJacques Vidrine major_status = gss_add_cred (&minor_status,
72bbd80c28SJacques Vidrine cred_handle,
73bbd80c28SJacques Vidrine GSS_C_NO_NAME,
74bbd80c28SJacques Vidrine GSS_KRB5_MECHANISM,
75bbd80c28SJacques Vidrine GSS_C_INITIATE,
76bbd80c28SJacques Vidrine 0,
77bbd80c28SJacques Vidrine 0,
78bbd80c28SJacques Vidrine ©_cred,
79bbd80c28SJacques Vidrine NULL,
80bbd80c28SJacques Vidrine &time_rec,
81bbd80c28SJacques Vidrine NULL);
82bbd80c28SJacques Vidrine
83bbd80c28SJacques Vidrine if (GSS_ERROR(major_status))
84bbd80c28SJacques Vidrine errx(1, "add_cred failed");
85bbd80c28SJacques Vidrine
86bbd80c28SJacques Vidrine print_time(time_rec);
87bbd80c28SJacques Vidrine
88bbd80c28SJacques Vidrine major_status = gss_release_cred(&minor_status,
89bbd80c28SJacques Vidrine ©_cred);
90bbd80c28SJacques Vidrine if (GSS_ERROR(major_status))
91bbd80c28SJacques Vidrine errx(1, "release_cred failed");
92c19800e8SDoug Rabson }
93c19800e8SDoug Rabson
94c19800e8SDoug Rabson static void
95c19800e8SDoug Rabson copy_cred(void)
96c19800e8SDoug Rabson {
97c19800e8SDoug Rabson OM_uint32 major_status, minor_status;
98c19800e8SDoug Rabson gss_cred_id_t cred_handle;
99c19800e8SDoug Rabson OM_uint32 time_rec;
100c19800e8SDoug Rabson
101c19800e8SDoug Rabson major_status = gss_acquire_cred(&minor_status,
102c19800e8SDoug Rabson GSS_C_NO_NAME,
103c19800e8SDoug Rabson 0,
104c19800e8SDoug Rabson NULL,
105c19800e8SDoug Rabson GSS_C_INITIATE,
106c19800e8SDoug Rabson &cred_handle,
107c19800e8SDoug Rabson NULL,
108c19800e8SDoug Rabson &time_rec);
109c19800e8SDoug Rabson if (GSS_ERROR(major_status))
110c19800e8SDoug Rabson errx(1, "acquire_cred failed");
111c19800e8SDoug Rabson
112c19800e8SDoug Rabson print_time(time_rec);
113c19800e8SDoug Rabson
114c19800e8SDoug Rabson test_add(cred_handle);
115c19800e8SDoug Rabson test_add(cred_handle);
116c19800e8SDoug Rabson test_add(cred_handle);
117c19800e8SDoug Rabson
118c19800e8SDoug Rabson major_status = gss_release_cred(&minor_status,
119c19800e8SDoug Rabson &cred_handle);
120c19800e8SDoug Rabson if (GSS_ERROR(major_status))
121c19800e8SDoug Rabson errx(1, "release_cred failed");
122c19800e8SDoug Rabson }
123c19800e8SDoug Rabson #endif
124c19800e8SDoug Rabson
125*ae771770SStanislav Sedov static gss_cred_id_t
acquire_cred_service(const char * service,gss_OID nametype,gss_OID_set oidset,int flags)126c19800e8SDoug Rabson acquire_cred_service(const char *service,
127c19800e8SDoug Rabson gss_OID nametype,
128*ae771770SStanislav Sedov gss_OID_set oidset,
129c19800e8SDoug Rabson int flags)
130c19800e8SDoug Rabson {
131c19800e8SDoug Rabson OM_uint32 major_status, minor_status;
132c19800e8SDoug Rabson gss_cred_id_t cred_handle;
133c19800e8SDoug Rabson OM_uint32 time_rec;
134c19800e8SDoug Rabson gss_buffer_desc name_buffer;
135c19800e8SDoug Rabson gss_name_t name = GSS_C_NO_NAME;
136c19800e8SDoug Rabson
137c19800e8SDoug Rabson if (service) {
138c19800e8SDoug Rabson name_buffer.value = rk_UNCONST(service);
139c19800e8SDoug Rabson name_buffer.length = strlen(service);
140c19800e8SDoug Rabson
141c19800e8SDoug Rabson major_status = gss_import_name(&minor_status,
142c19800e8SDoug Rabson &name_buffer,
143c19800e8SDoug Rabson nametype,
144c19800e8SDoug Rabson &name);
145c19800e8SDoug Rabson if (GSS_ERROR(major_status))
146c19800e8SDoug Rabson errx(1, "import_name failed");
147c19800e8SDoug Rabson }
148c19800e8SDoug Rabson
149c19800e8SDoug Rabson major_status = gss_acquire_cred(&minor_status,
150c19800e8SDoug Rabson name,
151c19800e8SDoug Rabson 0,
152*ae771770SStanislav Sedov oidset,
153c19800e8SDoug Rabson flags,
154c19800e8SDoug Rabson &cred_handle,
155c19800e8SDoug Rabson NULL,
156c19800e8SDoug Rabson &time_rec);
157c19800e8SDoug Rabson if (GSS_ERROR(major_status)) {
158c19800e8SDoug Rabson warnx("acquire_cred failed: %s",
159c19800e8SDoug Rabson gssapi_err(major_status, minor_status, GSS_C_NO_OID));
160c19800e8SDoug Rabson } else {
161c19800e8SDoug Rabson print_time(time_rec);
162c19800e8SDoug Rabson gss_release_cred(&minor_status, &cred_handle);
163c19800e8SDoug Rabson }
164c19800e8SDoug Rabson
165c19800e8SDoug Rabson if (name != GSS_C_NO_NAME)
166c19800e8SDoug Rabson gss_release_name(&minor_status, &name);
167c19800e8SDoug Rabson
168c19800e8SDoug Rabson if (GSS_ERROR(major_status))
169c19800e8SDoug Rabson exit(1);
170*ae771770SStanislav Sedov
171*ae771770SStanislav Sedov return cred_handle;
172c19800e8SDoug Rabson }
173c19800e8SDoug Rabson
174c19800e8SDoug Rabson static int version_flag = 0;
175c19800e8SDoug Rabson static int help_flag = 0;
176*ae771770SStanislav Sedov static int kerberos_flag = 0;
177*ae771770SStanislav Sedov static int enctype = 0;
178c19800e8SDoug Rabson static char *acquire_name;
179c19800e8SDoug Rabson static char *acquire_type;
180*ae771770SStanislav Sedov static char *target_name;
181c19800e8SDoug Rabson static char *name_type;
182c19800e8SDoug Rabson static char *ccache;
183*ae771770SStanislav Sedov static int num_loops = 1;
184c19800e8SDoug Rabson
185c19800e8SDoug Rabson static struct getargs args[] = {
186c19800e8SDoug Rabson {"acquire-name", 0, arg_string, &acquire_name, "name", NULL },
187c19800e8SDoug Rabson {"acquire-type", 0, arg_string, &acquire_type, "type", NULL },
188*ae771770SStanislav Sedov {"enctype", 0, arg_integer, &enctype, "enctype-num", NULL },
189*ae771770SStanislav Sedov {"loops", 0, arg_integer, &num_loops, "enctype-num", NULL },
190*ae771770SStanislav Sedov {"kerberos", 0, arg_flag, &kerberos_flag, "enctype-num", NULL },
191*ae771770SStanislav Sedov {"target-name", 0, arg_string, &target_name, "name", NULL },
192c19800e8SDoug Rabson {"ccache", 0, arg_string, &ccache, "name", NULL },
193c19800e8SDoug Rabson {"name-type", 0, arg_string, &name_type, "type", NULL },
194c19800e8SDoug Rabson {"version", 0, arg_flag, &version_flag, "print version", NULL },
195c19800e8SDoug Rabson {"help", 0, arg_flag, &help_flag, NULL, NULL }
196c19800e8SDoug Rabson };
197c19800e8SDoug Rabson
198c19800e8SDoug Rabson static void
usage(int ret)199c19800e8SDoug Rabson usage (int ret)
200c19800e8SDoug Rabson {
201c19800e8SDoug Rabson arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "");
202c19800e8SDoug Rabson exit (ret);
203c19800e8SDoug Rabson }
204c19800e8SDoug Rabson
205c19800e8SDoug Rabson int
main(int argc,char ** argv)206c19800e8SDoug Rabson main(int argc, char **argv)
207c19800e8SDoug Rabson {
208*ae771770SStanislav Sedov gss_OID_set oidset = GSS_C_NULL_OID_SET;
209*ae771770SStanislav Sedov gss_OID mechoid = GSS_C_NO_OID;
210*ae771770SStanislav Sedov OM_uint32 maj_stat, min_stat;
211*ae771770SStanislav Sedov gss_cred_id_t cred;
212*ae771770SStanislav Sedov gss_name_t target = GSS_C_NO_NAME;
213*ae771770SStanislav Sedov int i, optidx = 0;
214c19800e8SDoug Rabson OM_uint32 flag;
215c19800e8SDoug Rabson gss_OID type;
216c19800e8SDoug Rabson
217c19800e8SDoug Rabson setprogname(argv[0]);
218c19800e8SDoug Rabson if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
219c19800e8SDoug Rabson usage(1);
220c19800e8SDoug Rabson
221c19800e8SDoug Rabson if (help_flag)
222c19800e8SDoug Rabson usage (0);
223c19800e8SDoug Rabson
224c19800e8SDoug Rabson if(version_flag){
225c19800e8SDoug Rabson print_version(NULL);
226c19800e8SDoug Rabson exit(0);
227c19800e8SDoug Rabson }
228c19800e8SDoug Rabson
229c19800e8SDoug Rabson argc -= optidx;
230c19800e8SDoug Rabson argv += optidx;
231c19800e8SDoug Rabson
232c19800e8SDoug Rabson if (argc != 0)
233c19800e8SDoug Rabson usage(1);
234c19800e8SDoug Rabson
235c19800e8SDoug Rabson if (acquire_type) {
236c19800e8SDoug Rabson if (strcasecmp(acquire_type, "both") == 0)
237c19800e8SDoug Rabson flag = GSS_C_BOTH;
238c19800e8SDoug Rabson else if (strcasecmp(acquire_type, "accept") == 0)
239c19800e8SDoug Rabson flag = GSS_C_ACCEPT;
240c19800e8SDoug Rabson else if (strcasecmp(acquire_type, "initiate") == 0)
241c19800e8SDoug Rabson flag = GSS_C_INITIATE;
242c19800e8SDoug Rabson else
243c19800e8SDoug Rabson errx(1, "unknown type %s", acquire_type);
244c19800e8SDoug Rabson } else
245c19800e8SDoug Rabson flag = GSS_C_ACCEPT;
246c19800e8SDoug Rabson
247c19800e8SDoug Rabson if (name_type) {
248c19800e8SDoug Rabson if (strcasecmp("hostbased-service", name_type) == 0)
249c19800e8SDoug Rabson type = GSS_C_NT_HOSTBASED_SERVICE;
250c19800e8SDoug Rabson else if (strcasecmp("user-name", name_type) == 0)
251c19800e8SDoug Rabson type = GSS_C_NT_USER_NAME;
252c19800e8SDoug Rabson else
253c19800e8SDoug Rabson errx(1, "unknown name type %s", name_type);
254c19800e8SDoug Rabson } else
255c19800e8SDoug Rabson type = GSS_C_NT_HOSTBASED_SERVICE;
256c19800e8SDoug Rabson
257c19800e8SDoug Rabson if (ccache) {
258*ae771770SStanislav Sedov maj_stat = gss_krb5_ccache_name(&min_stat, ccache, NULL);
259*ae771770SStanislav Sedov if (GSS_ERROR(maj_stat))
260c19800e8SDoug Rabson errx(1, "gss_krb5_ccache_name %s",
261*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
262c19800e8SDoug Rabson }
263c19800e8SDoug Rabson
264*ae771770SStanislav Sedov if (kerberos_flag) {
265*ae771770SStanislav Sedov mechoid = GSS_KRB5_MECHANISM;
266*ae771770SStanislav Sedov
267*ae771770SStanislav Sedov maj_stat = gss_create_empty_oid_set(&min_stat, &oidset);
268*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE)
269*ae771770SStanislav Sedov errx(1, "gss_create_empty_oid_set: %s",
270*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
271*ae771770SStanislav Sedov
272*ae771770SStanislav Sedov maj_stat = gss_add_oid_set_member(&min_stat, GSS_KRB5_MECHANISM, &oidset);
273*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE)
274*ae771770SStanislav Sedov errx(1, "gss_add_oid_set_member: %s",
275*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
276*ae771770SStanislav Sedov }
277*ae771770SStanislav Sedov
278*ae771770SStanislav Sedov if (target_name) {
279*ae771770SStanislav Sedov gss_buffer_desc name;
280*ae771770SStanislav Sedov
281*ae771770SStanislav Sedov name.value = target_name;
282*ae771770SStanislav Sedov name.length = strlen(target_name);
283*ae771770SStanislav Sedov maj_stat = gss_import_name(&min_stat, &name,
284*ae771770SStanislav Sedov GSS_C_NT_HOSTBASED_SERVICE, &target);
285*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE)
286*ae771770SStanislav Sedov errx(1, "gss_import_name: %s",
287*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
288*ae771770SStanislav Sedov }
289*ae771770SStanislav Sedov
290*ae771770SStanislav Sedov for (i = 0; i < num_loops; i++) {
291*ae771770SStanislav Sedov
292*ae771770SStanislav Sedov cred = acquire_cred_service(acquire_name, type, oidset, flag);
293*ae771770SStanislav Sedov
294*ae771770SStanislav Sedov if (enctype) {
295*ae771770SStanislav Sedov int32_t enctypelist = enctype;
296*ae771770SStanislav Sedov
297*ae771770SStanislav Sedov maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, cred,
298*ae771770SStanislav Sedov 1, &enctypelist);
299*ae771770SStanislav Sedov if (maj_stat)
300*ae771770SStanislav Sedov errx(1, "gss_krb5_set_allowable_enctypes: %s",
301*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
302*ae771770SStanislav Sedov }
303*ae771770SStanislav Sedov
304*ae771770SStanislav Sedov if (target) {
305*ae771770SStanislav Sedov gss_ctx_id_t context = GSS_C_NO_CONTEXT;
306*ae771770SStanislav Sedov gss_buffer_desc out;
307*ae771770SStanislav Sedov
308*ae771770SStanislav Sedov out.length = 0;
309*ae771770SStanislav Sedov out.value = NULL;
310*ae771770SStanislav Sedov
311*ae771770SStanislav Sedov maj_stat = gss_init_sec_context(&min_stat,
312*ae771770SStanislav Sedov cred, &context,
313*ae771770SStanislav Sedov target, mechoid,
314*ae771770SStanislav Sedov GSS_C_MUTUAL_FLAG, 0, NULL,
315*ae771770SStanislav Sedov GSS_C_NO_BUFFER, NULL,
316*ae771770SStanislav Sedov &out, NULL, NULL);
317*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
318*ae771770SStanislav Sedov errx(1, "init_sec_context failed: %s",
319*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
320*ae771770SStanislav Sedov
321*ae771770SStanislav Sedov gss_release_buffer(&min_stat, &out);
322*ae771770SStanislav Sedov gss_delete_sec_context(&min_stat, &context, NULL);
323*ae771770SStanislav Sedov }
324*ae771770SStanislav Sedov gss_release_cred(&min_stat, &cred);
325*ae771770SStanislav Sedov }
326*ae771770SStanislav Sedov
327bbd80c28SJacques Vidrine
328bbd80c28SJacques Vidrine return 0;
329bbd80c28SJacques Vidrine }
330