1178825Sdfr/*
2233294Sstas * Copyright (c) 2003-2004 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17178825Sdfr * 3. Neither the name of KTH nor the names of its contributors may be
18178825Sdfr *    used to endorse or promote products derived from this software without
19178825Sdfr *    specific prior written permission.
20178825Sdfr *
21178825Sdfr * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22178825Sdfr * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24178825Sdfr * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25178825Sdfr * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26178825Sdfr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27178825Sdfr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28178825Sdfr * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29178825Sdfr * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30178825Sdfr * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31178825Sdfr * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34178825Sdfr#ifdef HAVE_CONFIG_H
35178825Sdfr#include <config.h>
36178825Sdfr#endif
37178825Sdfr
38233294Sstas#include <roken.h>
39178825Sdfr#include <stdio.h>
40178825Sdfr#include <stdlib.h>
41178825Sdfr#include <string.h>
42178825Sdfr#include <stdarg.h>
43178825Sdfr#include <gssapi.h>
44233294Sstas#include <gssapi_krb5.h>
45233294Sstas#include <gssapi_spnego.h>
46178825Sdfr#include <err.h>
47178825Sdfr#include <getarg.h>
48178825Sdfr
49178825Sdfrstatic void
50178825Sdfrgss_print_errors (int min_stat)
51178825Sdfr{
52178825Sdfr    OM_uint32 new_stat;
53178825Sdfr    OM_uint32 msg_ctx = 0;
54178825Sdfr    gss_buffer_desc status_string;
55178825Sdfr    OM_uint32 ret;
56178825Sdfr
57178825Sdfr    do {
58178825Sdfr	ret = gss_display_status (&new_stat,
59178825Sdfr				  min_stat,
60178825Sdfr				  GSS_C_MECH_CODE,
61178825Sdfr				  GSS_C_NO_OID,
62178825Sdfr				  &msg_ctx,
63178825Sdfr				  &status_string);
64178825Sdfr	if (!GSS_ERROR(ret)) {
65233294Sstas	    fprintf (stderr, "%.*s\n", (int)status_string.length,
66233294Sstas					(char *)status_string.value);
67178825Sdfr	    gss_release_buffer (&new_stat, &status_string);
68178825Sdfr	}
69178825Sdfr    } while (!GSS_ERROR(ret) && msg_ctx != 0);
70178825Sdfr}
71178825Sdfr
72178825Sdfrstatic void
73178825Sdfrgss_err(int exitval, int status, const char *fmt, ...)
74178825Sdfr{
75178825Sdfr    va_list args;
76178825Sdfr
77178825Sdfr    va_start(args, fmt);
78178825Sdfr    vwarnx (fmt, args);
79178825Sdfr    gss_print_errors (status);
80178825Sdfr    va_end(args);
81178825Sdfr    exit (exitval);
82178825Sdfr}
83178825Sdfr
84178825Sdfrstatic void
85178825Sdfracquire_release_loop(gss_name_t name, int counter, gss_cred_usage_t usage)
86178825Sdfr{
87178825Sdfr    OM_uint32 maj_stat, min_stat;
88178825Sdfr    gss_cred_id_t cred;
89178825Sdfr    int i;
90178825Sdfr
91178825Sdfr    for (i = 0; i < counter; i++) {
92178825Sdfr	maj_stat = gss_acquire_cred(&min_stat, name,
93178825Sdfr				    GSS_C_INDEFINITE,
94178825Sdfr				    GSS_C_NO_OID_SET,
95178825Sdfr				    usage,
96178825Sdfr				    &cred,
97178825Sdfr				    NULL,
98178825Sdfr				    NULL);
99178825Sdfr	if (maj_stat != GSS_S_COMPLETE)
100233294Sstas	    gss_err(1, min_stat, "aquire %d %d != GSS_S_COMPLETE",
101178825Sdfr		    i, (int)maj_stat);
102233294Sstas
103178825Sdfr	maj_stat = gss_release_cred(&min_stat, &cred);
104178825Sdfr	if (maj_stat != GSS_S_COMPLETE)
105233294Sstas	    gss_err(1, min_stat, "release %d %d != GSS_S_COMPLETE",
106178825Sdfr		    i, (int)maj_stat);
107178825Sdfr    }
108178825Sdfr}
109178825Sdfr
110178825Sdfr
111178825Sdfrstatic void
112178825Sdfracquire_add_release_add(gss_name_t name, gss_cred_usage_t usage)
113178825Sdfr{
114178825Sdfr    OM_uint32 maj_stat, min_stat;
115178825Sdfr    gss_cred_id_t cred, cred2, cred3;
116178825Sdfr
117178825Sdfr    maj_stat = gss_acquire_cred(&min_stat, name,
118178825Sdfr				GSS_C_INDEFINITE,
119178825Sdfr				GSS_C_NO_OID_SET,
120178825Sdfr				usage,
121178825Sdfr				&cred,
122178825Sdfr				NULL,
123178825Sdfr				NULL);
124178825Sdfr    if (maj_stat != GSS_S_COMPLETE)
125178825Sdfr	gss_err(1, min_stat, "aquire %d != GSS_S_COMPLETE", (int)maj_stat);
126233294Sstas
127178825Sdfr    maj_stat = gss_add_cred(&min_stat,
128178825Sdfr			    cred,
129178825Sdfr			    GSS_C_NO_NAME,
130178825Sdfr			    GSS_KRB5_MECHANISM,
131178825Sdfr			    usage,
132178825Sdfr			    GSS_C_INDEFINITE,
133178825Sdfr			    GSS_C_INDEFINITE,
134178825Sdfr			    &cred2,
135178825Sdfr			    NULL,
136178825Sdfr			    NULL,
137178825Sdfr			    NULL);
138233294Sstas
139178825Sdfr    if (maj_stat != GSS_S_COMPLETE)
140178825Sdfr	gss_err(1, min_stat, "add_cred %d != GSS_S_COMPLETE", (int)maj_stat);
141178825Sdfr
142178825Sdfr    maj_stat = gss_release_cred(&min_stat, &cred);
143178825Sdfr    if (maj_stat != GSS_S_COMPLETE)
144178825Sdfr	gss_err(1, min_stat, "release %d != GSS_S_COMPLETE", (int)maj_stat);
145178825Sdfr
146178825Sdfr    maj_stat = gss_add_cred(&min_stat,
147178825Sdfr			    cred2,
148178825Sdfr			    GSS_C_NO_NAME,
149178825Sdfr			    GSS_KRB5_MECHANISM,
150178825Sdfr			    GSS_C_BOTH,
151178825Sdfr			    GSS_C_INDEFINITE,
152178825Sdfr			    GSS_C_INDEFINITE,
153178825Sdfr			    &cred3,
154178825Sdfr			    NULL,
155178825Sdfr			    NULL,
156178825Sdfr			    NULL);
157178825Sdfr
158178825Sdfr    maj_stat = gss_release_cred(&min_stat, &cred2);
159178825Sdfr    if (maj_stat != GSS_S_COMPLETE)
160178825Sdfr	gss_err(1, min_stat, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat);
161178825Sdfr
162178825Sdfr    maj_stat = gss_release_cred(&min_stat, &cred3);
163178825Sdfr    if (maj_stat != GSS_S_COMPLETE)
164178825Sdfr	gss_err(1, min_stat, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat);
165178825Sdfr}
166178825Sdfr
167178825Sdfrstatic int version_flag = 0;
168178825Sdfrstatic int help_flag	= 0;
169178825Sdfr
170178825Sdfrstatic struct getargs args[] = {
171178825Sdfr    {"version",	0,	arg_flag,	&version_flag, "print version", NULL },
172178825Sdfr    {"help",	0,	arg_flag,	&help_flag,  NULL, NULL }
173178825Sdfr};
174178825Sdfr
175178825Sdfrstatic void
176178825Sdfrusage (int ret)
177178825Sdfr{
178178825Sdfr    arg_printusage (args, sizeof(args)/sizeof(*args),
179178825Sdfr		    NULL, "service@host");
180178825Sdfr    exit (ret);
181178825Sdfr}
182178825Sdfr
183178825Sdfr
184178825Sdfrint
185178825Sdfrmain(int argc, char **argv)
186178825Sdfr{
187178825Sdfr    struct gss_buffer_desc_struct name_buffer;
188178825Sdfr    OM_uint32 maj_stat, min_stat;
189178825Sdfr    gss_name_t name;
190178825Sdfr    int optidx = 0;
191178825Sdfr
192178825Sdfr    setprogname(argv[0]);
193178825Sdfr    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
194178825Sdfr	usage(1);
195233294Sstas
196178825Sdfr    if (help_flag)
197178825Sdfr	usage (0);
198178825Sdfr
199178825Sdfr    if(version_flag){
200178825Sdfr	print_version(NULL);
201178825Sdfr	exit(0);
202178825Sdfr    }
203178825Sdfr
204178825Sdfr    argc -= optidx;
205178825Sdfr    argv += optidx;
206178825Sdfr
207178825Sdfr    if (argc < 1)
208178825Sdfr	errx(1, "argc < 1");
209178825Sdfr
210178825Sdfr    name_buffer.value = argv[0];
211178825Sdfr    name_buffer.length = strlen(argv[0]);
212178825Sdfr
213178825Sdfr    maj_stat = gss_import_name(&min_stat, &name_buffer,
214178825Sdfr			       GSS_C_NT_HOSTBASED_SERVICE,
215178825Sdfr			       &name);
216178825Sdfr    if (maj_stat != GSS_S_COMPLETE)
217178825Sdfr	errx(1, "import name error");
218178825Sdfr
219178825Sdfr    acquire_release_loop(name, 100, GSS_C_ACCEPT);
220178825Sdfr    acquire_release_loop(name, 100, GSS_C_INITIATE);
221178825Sdfr    acquire_release_loop(name, 100, GSS_C_BOTH);
222178825Sdfr
223178825Sdfr    acquire_add_release_add(name, GSS_C_ACCEPT);
224178825Sdfr    acquire_add_release_add(name, GSS_C_INITIATE);
225178825Sdfr    acquire_add_release_add(name, GSS_C_BOTH);
226178825Sdfr
227178825Sdfr    gss_release_name(&min_stat, &name);
228178825Sdfr
229178825Sdfr    return 0;
230178825Sdfr}
231