1 /*	$NetBSD: test_acquire_cred.c,v 1.1.1.2 2014/04/24 12:45:29 pettai Exp $	*/
2 
3 /*
4  * Copyright (c) 2003-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 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 
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39 
40 #include <krb5/roken.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <stdarg.h>
45 #include <gssapi/gssapi.h>
46 #include <gssapi/gssapi_krb5.h>
47 #include <gssapi/gssapi_spnego.h>
48 #include <err.h>
49 #include <krb5/getarg.h>
50 
51 #include "test_common.h"
52 
53 static void
print_time(OM_uint32 time_rec)54 print_time(OM_uint32 time_rec)
55 {
56     if (time_rec == GSS_C_INDEFINITE) {
57 	printf("cred never expire\n");
58     } else {
59 	time_t t = time_rec + time(NULL);
60 	printf("expiration time: %s", ctime(&t));
61     }
62 }
63 
64 #if 0
65 
66 static void
67 test_add(gss_cred_id_t cred_handle)
68 {
69     OM_uint32 major_status, minor_status;
70     gss_cred_id_t copy_cred;
71     OM_uint32 time_rec;
72 
73     major_status = gss_add_cred (&minor_status,
74 				 cred_handle,
75 				 GSS_C_NO_NAME,
76 				 GSS_KRB5_MECHANISM,
77 				 GSS_C_INITIATE,
78 				 0,
79 				 0,
80 				 &copy_cred,
81 				 NULL,
82 				 &time_rec,
83 				 NULL);
84 
85     if (GSS_ERROR(major_status))
86 	errx(1, "add_cred failed");
87 
88     print_time(time_rec);
89 
90     major_status = gss_release_cred(&minor_status,
91 				    &copy_cred);
92     if (GSS_ERROR(major_status))
93 	errx(1, "release_cred failed");
94 }
95 
96 static void
97 copy_cred(void)
98 {
99     OM_uint32 major_status, minor_status;
100     gss_cred_id_t cred_handle;
101     OM_uint32 time_rec;
102 
103     major_status = gss_acquire_cred(&minor_status,
104 				    GSS_C_NO_NAME,
105 				    0,
106 				    NULL,
107 				    GSS_C_INITIATE,
108 				    &cred_handle,
109 				    NULL,
110 				    &time_rec);
111     if (GSS_ERROR(major_status))
112 	errx(1, "acquire_cred failed");
113 
114     print_time(time_rec);
115 
116     test_add(cred_handle);
117     test_add(cred_handle);
118     test_add(cred_handle);
119 
120     major_status = gss_release_cred(&minor_status,
121 				    &cred_handle);
122     if (GSS_ERROR(major_status))
123 	errx(1, "release_cred failed");
124 }
125 #endif
126 
127 static gss_cred_id_t
acquire_cred_service(const char * service,gss_OID nametype,gss_OID_set oidset,int flags)128 acquire_cred_service(const char *service,
129 		     gss_OID nametype,
130 		     gss_OID_set oidset,
131 		     int flags)
132 {
133     OM_uint32 major_status, minor_status;
134     gss_cred_id_t cred_handle;
135     OM_uint32 time_rec;
136     gss_buffer_desc name_buffer;
137     gss_name_t name = GSS_C_NO_NAME;
138 
139     if (service) {
140 	name_buffer.value = rk_UNCONST(service);
141 	name_buffer.length = strlen(service);
142 
143 	major_status = gss_import_name(&minor_status,
144 				       &name_buffer,
145 				       nametype,
146 				       &name);
147 	if (GSS_ERROR(major_status))
148 	    errx(1, "import_name failed");
149     }
150 
151     major_status = gss_acquire_cred(&minor_status,
152 				    name,
153 				    0,
154 				    oidset,
155 				    flags,
156 				    &cred_handle,
157 				    NULL,
158 				    &time_rec);
159     if (GSS_ERROR(major_status)) {
160 	warnx("acquire_cred failed: %s",
161 	     gssapi_err(major_status, minor_status, GSS_C_NO_OID));
162     } else {
163 	print_time(time_rec);
164 	gss_release_cred(&minor_status, &cred_handle);
165     }
166 
167     if (name != GSS_C_NO_NAME)
168 	gss_release_name(&minor_status, &name);
169 
170     if (GSS_ERROR(major_status))
171 	exit(1);
172 
173     return cred_handle;
174 }
175 
176 static int version_flag = 0;
177 static int help_flag	= 0;
178 static int kerberos_flag = 0;
179 static int enctype = 0;
180 static char *acquire_name;
181 static char *acquire_type;
182 static char *target_name;
183 static char *name_type;
184 static char *ccache;
185 static int num_loops = 1;
186 
187 static struct getargs args[] = {
188     {"acquire-name", 0,	arg_string,	&acquire_name, "name", NULL },
189     {"acquire-type", 0,	arg_string,	&acquire_type, "type", NULL },
190     {"enctype", 0,	arg_integer,	&enctype, "enctype-num", NULL },
191     {"loops", 0,	arg_integer,	&num_loops, "enctype-num", NULL },
192     {"kerberos", 0,	arg_flag,	&kerberos_flag, "enctype-num", NULL },
193     {"target-name", 0,	arg_string,	&target_name, "name", NULL },
194     {"ccache", 0,	arg_string,	&ccache, "name", NULL },
195     {"name-type", 0,	arg_string,	&name_type, "type", NULL },
196     {"version",	0,	arg_flag,	&version_flag, "print version", NULL },
197     {"help",	0,	arg_flag,	&help_flag,  NULL, NULL }
198 };
199 
200 static void
usage(int ret)201 usage (int ret)
202 {
203     arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "");
204     exit (ret);
205 }
206 
207 int
main(int argc,char ** argv)208 main(int argc, char **argv)
209 {
210     gss_OID_set oidset = GSS_C_NULL_OID_SET;
211     gss_OID mechoid = GSS_C_NO_OID;
212     OM_uint32 maj_stat, min_stat;
213     gss_cred_id_t cred;
214     gss_name_t target = GSS_C_NO_NAME;
215     int i, optidx = 0;
216     OM_uint32 flag;
217     gss_OID type;
218 
219     setprogname(argv[0]);
220     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
221 	usage(1);
222 
223     if (help_flag)
224 	usage (0);
225 
226     if(version_flag){
227 	print_version(NULL);
228 	exit(0);
229     }
230 
231     argc -= optidx;
232     argv += optidx;
233 
234     if (argc != 0)
235 	usage(1);
236 
237     if (acquire_type) {
238 	if (strcasecmp(acquire_type, "both") == 0)
239 	    flag = GSS_C_BOTH;
240 	else if (strcasecmp(acquire_type, "accept") == 0)
241 	    flag = GSS_C_ACCEPT;
242 	else if (strcasecmp(acquire_type, "initiate") == 0)
243 	    flag = GSS_C_INITIATE;
244 	else
245 	    errx(1, "unknown type %s", acquire_type);
246     } else
247 	flag = GSS_C_ACCEPT;
248 
249     if (name_type) {
250 	if (strcasecmp("hostbased-service", name_type) == 0)
251 	    type = GSS_C_NT_HOSTBASED_SERVICE;
252 	else if (strcasecmp("user-name", name_type) == 0)
253 	    type = GSS_C_NT_USER_NAME;
254 	else
255 	    errx(1, "unknown name type %s", name_type);
256     } else
257 	type = GSS_C_NT_HOSTBASED_SERVICE;
258 
259     if (ccache) {
260 	maj_stat = gss_krb5_ccache_name(&min_stat, ccache, NULL);
261 	if (GSS_ERROR(maj_stat))
262 	    errx(1, "gss_krb5_ccache_name %s",
263 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
264     }
265 
266     if (kerberos_flag) {
267 	mechoid = GSS_KRB5_MECHANISM;
268 
269 	maj_stat = gss_create_empty_oid_set(&min_stat, &oidset);
270 	if (maj_stat != GSS_S_COMPLETE)
271 	    errx(1, "gss_create_empty_oid_set: %s",
272 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
273 
274 	maj_stat = gss_add_oid_set_member(&min_stat, GSS_KRB5_MECHANISM, &oidset);
275 	if (maj_stat != GSS_S_COMPLETE)
276 	    errx(1, "gss_add_oid_set_member: %s",
277 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
278     }
279 
280     if (target_name) {
281 	gss_buffer_desc name;
282 
283 	name.value = target_name;
284 	name.length = strlen(target_name);
285 	maj_stat = gss_import_name(&min_stat, &name,
286 				   GSS_C_NT_HOSTBASED_SERVICE, &target);
287 	if (maj_stat != GSS_S_COMPLETE)
288 	    errx(1, "gss_import_name: %s",
289 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
290     }
291 
292     for (i = 0; i < num_loops; i++) {
293 
294 	cred = acquire_cred_service(acquire_name, type, oidset, flag);
295 
296 	if (enctype) {
297 	    int32_t enctypelist = enctype;
298 
299 	    maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, cred,
300 						       1, &enctypelist);
301 	    if (maj_stat)
302 		errx(1, "gss_krb5_set_allowable_enctypes: %s",
303 		     gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
304 	}
305 
306 	if (target) {
307 	    gss_ctx_id_t context = GSS_C_NO_CONTEXT;
308 	    gss_buffer_desc out;
309 
310 	    out.length = 0;
311 	    out.value = NULL;
312 
313 	    maj_stat = gss_init_sec_context(&min_stat,
314 					    cred, &context,
315 					    target, mechoid,
316 					    GSS_C_MUTUAL_FLAG, 0, NULL,
317 					    GSS_C_NO_BUFFER, NULL,
318 					    &out, NULL, NULL);
319 	    if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
320 		errx(1, "init_sec_context failed: %s",
321 		     gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
322 
323 	    gss_release_buffer(&min_stat, &out);
324 	    gss_delete_sec_context(&min_stat, &context, NULL);
325 	}
326 	gss_release_cred(&min_stat, &cred);
327     }
328 
329 
330     return 0;
331 }
332