1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "test_locl.h"
35*ae771770SStanislav Sedov #include <gssapi/gssapi.h>
36*ae771770SStanislav Sedov #include <gssapi/gssapi_krb5.h>
37*ae771770SStanislav Sedov #include <gssapi/gssapi_spnego.h>
38b528cefcSMark Murray #include "gss_common.h"
39*ae771770SStanislav Sedov RCSID("$Id$");
40283d988cSMark Murray
41283d988cSMark Murray static int
process_it(int sock,gss_ctx_id_t context_hdl,gss_name_t client_name)42283d988cSMark Murray process_it(int sock,
43283d988cSMark Murray gss_ctx_id_t context_hdl,
44283d988cSMark Murray gss_name_t client_name
45283d988cSMark Murray )
46283d988cSMark Murray {
47283d988cSMark Murray OM_uint32 maj_stat, min_stat;
48283d988cSMark Murray gss_buffer_desc real_input_token, real_output_token;
49283d988cSMark Murray gss_buffer_t input_token = &real_input_token,
50283d988cSMark Murray output_token = &real_output_token;
51c19800e8SDoug Rabson gss_name_t server_name;
52c19800e8SDoug Rabson int conf_flag;
53283d988cSMark Murray
54c19800e8SDoug Rabson print_gss_name("User is", client_name);
55c19800e8SDoug Rabson
56c19800e8SDoug Rabson maj_stat = gss_inquire_context(&min_stat,
57c19800e8SDoug Rabson context_hdl,
58c19800e8SDoug Rabson NULL,
59c19800e8SDoug Rabson &server_name,
60c19800e8SDoug Rabson NULL,
61c19800e8SDoug Rabson NULL,
62c19800e8SDoug Rabson NULL,
63c19800e8SDoug Rabson NULL,
64283d988cSMark Murray NULL);
65283d988cSMark Murray if (GSS_ERROR(maj_stat))
66c19800e8SDoug Rabson gss_err (1, min_stat, "gss_inquire_context");
67283d988cSMark Murray
68c19800e8SDoug Rabson print_gss_name("Server is", server_name);
69283d988cSMark Murray
70c19800e8SDoug Rabson maj_stat = gss_release_name(&min_stat, &server_name);
71c19800e8SDoug Rabson if (GSS_ERROR(maj_stat))
72c19800e8SDoug Rabson gss_err (1, min_stat, "gss_release_name");
73283d988cSMark Murray
74283d988cSMark Murray /* gss_verify_mic */
75283d988cSMark Murray
76283d988cSMark Murray read_token (sock, input_token);
77283d988cSMark Murray read_token (sock, output_token);
78283d988cSMark Murray
79283d988cSMark Murray maj_stat = gss_verify_mic (&min_stat,
80283d988cSMark Murray context_hdl,
81283d988cSMark Murray input_token,
82283d988cSMark Murray output_token,
83283d988cSMark Murray NULL);
84283d988cSMark Murray if (GSS_ERROR(maj_stat))
85283d988cSMark Murray gss_err (1, min_stat, "gss_verify_mic");
86283d988cSMark Murray
87283d988cSMark Murray fprintf (stderr, "gss_verify_mic: %.*s\n", (int)input_token->length,
88283d988cSMark Murray (char *)input_token->value);
89283d988cSMark Murray
90283d988cSMark Murray gss_release_buffer (&min_stat, input_token);
91283d988cSMark Murray gss_release_buffer (&min_stat, output_token);
92283d988cSMark Murray
93283d988cSMark Murray /* gss_unwrap */
94283d988cSMark Murray
95283d988cSMark Murray read_token (sock, input_token);
96283d988cSMark Murray
97283d988cSMark Murray maj_stat = gss_unwrap (&min_stat,
98283d988cSMark Murray context_hdl,
99283d988cSMark Murray input_token,
100283d988cSMark Murray output_token,
101c19800e8SDoug Rabson &conf_flag,
102283d988cSMark Murray NULL);
103283d988cSMark Murray if(GSS_ERROR(maj_stat))
104283d988cSMark Murray gss_err (1, min_stat, "gss_unwrap");
105283d988cSMark Murray
106c19800e8SDoug Rabson fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length,
107c19800e8SDoug Rabson (char *)output_token->value,
108c19800e8SDoug Rabson conf_flag ? "CONF" : "INT");
109c19800e8SDoug Rabson
110c19800e8SDoug Rabson gss_release_buffer (&min_stat, input_token);
111c19800e8SDoug Rabson gss_release_buffer (&min_stat, output_token);
112c19800e8SDoug Rabson
113c19800e8SDoug Rabson read_token (sock, input_token);
114c19800e8SDoug Rabson
115c19800e8SDoug Rabson maj_stat = gss_unwrap (&min_stat,
116c19800e8SDoug Rabson context_hdl,
117c19800e8SDoug Rabson input_token,
118c19800e8SDoug Rabson output_token,
119c19800e8SDoug Rabson &conf_flag,
120c19800e8SDoug Rabson NULL);
121c19800e8SDoug Rabson if(GSS_ERROR(maj_stat))
122c19800e8SDoug Rabson gss_err (1, min_stat, "gss_unwrap");
123c19800e8SDoug Rabson
124c19800e8SDoug Rabson fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length,
125c19800e8SDoug Rabson (char *)output_token->value,
126c19800e8SDoug Rabson conf_flag ? "CONF" : "INT");
127283d988cSMark Murray
128283d988cSMark Murray gss_release_buffer (&min_stat, input_token);
129283d988cSMark Murray gss_release_buffer (&min_stat, output_token);
130283d988cSMark Murray
131283d988cSMark Murray return 0;
132283d988cSMark Murray }
133b528cefcSMark Murray
134b528cefcSMark Murray static int
proto(int sock,const char * service)135b528cefcSMark Murray proto (int sock, const char *service)
136b528cefcSMark Murray {
137b528cefcSMark Murray struct sockaddr_in remote, local;
1385e9cd1aeSAssar Westerlund socklen_t addrlen;
139b528cefcSMark Murray gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
140b528cefcSMark Murray gss_buffer_desc real_input_token, real_output_token;
141283d988cSMark Murray gss_buffer_t input_token = &real_input_token,
142283d988cSMark Murray output_token = &real_output_token;
143b528cefcSMark Murray OM_uint32 maj_stat, min_stat;
144b528cefcSMark Murray gss_name_t client_name;
1455e9cd1aeSAssar Westerlund struct gss_channel_bindings_struct input_chan_bindings;
1465e9cd1aeSAssar Westerlund gss_cred_id_t delegated_cred_handle = NULL;
1475e9cd1aeSAssar Westerlund krb5_ccache ccache;
1485e9cd1aeSAssar Westerlund u_char init_buf[4];
1495e9cd1aeSAssar Westerlund u_char acct_buf[4];
150c19800e8SDoug Rabson gss_OID mech_oid;
151c19800e8SDoug Rabson char *mech, *p;
152b528cefcSMark Murray
153b528cefcSMark Murray addrlen = sizeof(local);
154b528cefcSMark Murray if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
155b528cefcSMark Murray || addrlen != sizeof(local))
156b528cefcSMark Murray err (1, "getsockname)");
157b528cefcSMark Murray
158b528cefcSMark Murray addrlen = sizeof(remote);
159b528cefcSMark Murray if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
160b528cefcSMark Murray || addrlen != sizeof(remote))
161b528cefcSMark Murray err (1, "getpeername");
162b528cefcSMark Murray
1635e9cd1aeSAssar Westerlund input_chan_bindings.initiator_addrtype = GSS_C_AF_INET;
1645e9cd1aeSAssar Westerlund input_chan_bindings.initiator_address.length = 4;
1655e9cd1aeSAssar Westerlund init_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF;
1665e9cd1aeSAssar Westerlund init_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF;
1675e9cd1aeSAssar Westerlund init_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF;
1685e9cd1aeSAssar Westerlund init_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF;
1695e9cd1aeSAssar Westerlund
1705e9cd1aeSAssar Westerlund input_chan_bindings.initiator_address.value = init_buf;
1715e9cd1aeSAssar Westerlund input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET;
1725e9cd1aeSAssar Westerlund
1735e9cd1aeSAssar Westerlund input_chan_bindings.acceptor_address.length = 4;
1745e9cd1aeSAssar Westerlund acct_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF;
1755e9cd1aeSAssar Westerlund acct_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF;
1765e9cd1aeSAssar Westerlund acct_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF;
1775e9cd1aeSAssar Westerlund acct_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF;
1785e9cd1aeSAssar Westerlund input_chan_bindings.acceptor_address.value = acct_buf;
1795e9cd1aeSAssar Westerlund input_chan_bindings.application_data.value = emalloc(4);
1805e9cd1aeSAssar Westerlund #if 0
1815e9cd1aeSAssar Westerlund * (unsigned short *)input_chan_bindings.application_data.value =
1825e9cd1aeSAssar Westerlund remote.sin_port;
1835e9cd1aeSAssar Westerlund * ((unsigned short *)input_chan_bindings.application_data.value + 1) =
1845e9cd1aeSAssar Westerlund local.sin_port;
1855e9cd1aeSAssar Westerlund input_chan_bindings.application_data.length = 4;
1865e9cd1aeSAssar Westerlund #else
1875e9cd1aeSAssar Westerlund input_chan_bindings.application_data.length = 0;
1885e9cd1aeSAssar Westerlund input_chan_bindings.application_data.value = NULL;
1895e9cd1aeSAssar Westerlund #endif
1905e9cd1aeSAssar Westerlund
191c19800e8SDoug Rabson delegated_cred_handle = GSS_C_NO_CREDENTIAL;
1925e9cd1aeSAssar Westerlund
193b528cefcSMark Murray do {
194b528cefcSMark Murray read_token (sock, input_token);
195b528cefcSMark Murray maj_stat =
196b528cefcSMark Murray gss_accept_sec_context (&min_stat,
197b528cefcSMark Murray &context_hdl,
198b528cefcSMark Murray GSS_C_NO_CREDENTIAL,
199b528cefcSMark Murray input_token,
2005e9cd1aeSAssar Westerlund &input_chan_bindings,
201b528cefcSMark Murray &client_name,
202c19800e8SDoug Rabson &mech_oid,
203b528cefcSMark Murray output_token,
204b528cefcSMark Murray NULL,
205b528cefcSMark Murray NULL,
206c19800e8SDoug Rabson &delegated_cred_handle);
207b528cefcSMark Murray if(GSS_ERROR(maj_stat))
208b528cefcSMark Murray gss_err (1, min_stat, "gss_accept_sec_context");
209b528cefcSMark Murray if (output_token->length != 0)
210b528cefcSMark Murray write_token (sock, output_token);
211b528cefcSMark Murray if (GSS_ERROR(maj_stat)) {
212b528cefcSMark Murray if (context_hdl != GSS_C_NO_CONTEXT)
213b528cefcSMark Murray gss_delete_sec_context (&min_stat,
214b528cefcSMark Murray &context_hdl,
215b528cefcSMark Murray GSS_C_NO_BUFFER);
216b528cefcSMark Murray break;
217b528cefcSMark Murray }
218b528cefcSMark Murray } while(maj_stat & GSS_S_CONTINUE_NEEDED);
219b528cefcSMark Murray
220c19800e8SDoug Rabson p = (char *)mech_oid->elements;
221c19800e8SDoug Rabson if (mech_oid->length == GSS_KRB5_MECHANISM->length
222c19800e8SDoug Rabson && memcmp(p, GSS_KRB5_MECHANISM->elements, mech_oid->length) == 0)
223c19800e8SDoug Rabson mech = "Kerberos 5";
224c19800e8SDoug Rabson else if (mech_oid->length == GSS_SPNEGO_MECHANISM->length
225c19800e8SDoug Rabson && memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_oid->length) == 0)
226c19800e8SDoug Rabson mech = "SPNEGO"; /* XXX Silly, wont show up */
227c19800e8SDoug Rabson else
228c19800e8SDoug Rabson mech = "Unknown";
229c19800e8SDoug Rabson
230c19800e8SDoug Rabson printf("Using mech: %s\n", mech);
231c19800e8SDoug Rabson
232c19800e8SDoug Rabson if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
2335e9cd1aeSAssar Westerlund krb5_context context;
2345e9cd1aeSAssar Westerlund
235c19800e8SDoug Rabson printf("Delegated cred found\n");
236c19800e8SDoug Rabson
2375e9cd1aeSAssar Westerlund maj_stat = krb5_init_context(&context);
2385e9cd1aeSAssar Westerlund maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache);
239c19800e8SDoug Rabson maj_stat = gss_krb5_copy_ccache(&min_stat,
240c19800e8SDoug Rabson delegated_cred_handle,
241c19800e8SDoug Rabson ccache);
242c19800e8SDoug Rabson if (maj_stat == 0) {
243c19800e8SDoug Rabson krb5_principal p;
244c19800e8SDoug Rabson maj_stat = krb5_cc_get_principal(context, ccache, &p);
245c19800e8SDoug Rabson if (maj_stat == 0) {
246c19800e8SDoug Rabson char *name;
247c19800e8SDoug Rabson maj_stat = krb5_unparse_name(context, p, &name);
248c19800e8SDoug Rabson if (maj_stat == 0) {
249c19800e8SDoug Rabson printf("Delegated user is: `%s'\n", name);
250c19800e8SDoug Rabson free(name);
251c19800e8SDoug Rabson }
252c19800e8SDoug Rabson krb5_free_principal(context, p);
253c19800e8SDoug Rabson }
254c19800e8SDoug Rabson }
2555e9cd1aeSAssar Westerlund krb5_cc_close(context, ccache);
256c19800e8SDoug Rabson gss_release_cred(&min_stat, &delegated_cred_handle);
2575e9cd1aeSAssar Westerlund }
2585e9cd1aeSAssar Westerlund
259283d988cSMark Murray if (fork_flag) {
260283d988cSMark Murray pid_t pid;
261283d988cSMark Murray int pipefd[2];
262283d988cSMark Murray
263283d988cSMark Murray if (pipe (pipefd) < 0)
264283d988cSMark Murray err (1, "pipe");
265283d988cSMark Murray
266283d988cSMark Murray pid = fork ();
267283d988cSMark Murray if (pid < 0)
268283d988cSMark Murray err (1, "fork");
269283d988cSMark Murray if (pid != 0) {
270283d988cSMark Murray gss_buffer_desc buf;
271283d988cSMark Murray
272283d988cSMark Murray maj_stat = gss_export_sec_context (&min_stat,
273283d988cSMark Murray &context_hdl,
274283d988cSMark Murray &buf);
275b528cefcSMark Murray if (GSS_ERROR(maj_stat))
276283d988cSMark Murray gss_err (1, min_stat, "gss_export_sec_context");
277283d988cSMark Murray write_token (pipefd[1], &buf);
278283d988cSMark Murray exit (0);
279283d988cSMark Murray } else {
280283d988cSMark Murray gss_ctx_id_t context_hdl;
281283d988cSMark Murray gss_buffer_desc buf;
282b528cefcSMark Murray
283283d988cSMark Murray close (pipefd[1]);
284283d988cSMark Murray read_token (pipefd[0], &buf);
285283d988cSMark Murray close (pipefd[0]);
286283d988cSMark Murray maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl);
287b528cefcSMark Murray if (GSS_ERROR(maj_stat))
288283d988cSMark Murray gss_err (1, min_stat, "gss_import_sec_context");
289283d988cSMark Murray gss_release_buffer (&min_stat, &buf);
290283d988cSMark Murray return process_it (sock, context_hdl, client_name);
291283d988cSMark Murray }
292283d988cSMark Murray } else {
293283d988cSMark Murray return process_it (sock, context_hdl, client_name);
294283d988cSMark Murray }
295b528cefcSMark Murray }
296b528cefcSMark Murray
297b528cefcSMark Murray static int
doit(int port,const char * service)298b528cefcSMark Murray doit (int port, const char *service)
299b528cefcSMark Murray {
300b528cefcSMark Murray int sock, sock2;
301b528cefcSMark Murray struct sockaddr_in my_addr;
302b528cefcSMark Murray int one = 1;
303*ae771770SStanislav Sedov int ret;
304b528cefcSMark Murray
305b528cefcSMark Murray sock = socket (AF_INET, SOCK_STREAM, 0);
306b528cefcSMark Murray if (sock < 0)
307b528cefcSMark Murray err (1, "socket");
308b528cefcSMark Murray
309b528cefcSMark Murray memset (&my_addr, 0, sizeof(my_addr));
310b528cefcSMark Murray my_addr.sin_family = AF_INET;
311b528cefcSMark Murray my_addr.sin_port = port;
312b528cefcSMark Murray my_addr.sin_addr.s_addr = INADDR_ANY;
313b528cefcSMark Murray
314b528cefcSMark Murray if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
315b528cefcSMark Murray (void *)&one, sizeof(one)) < 0)
316b528cefcSMark Murray warn ("setsockopt SO_REUSEADDR");
317b528cefcSMark Murray
318b528cefcSMark Murray if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
319b528cefcSMark Murray err (1, "bind");
320b528cefcSMark Murray
321*ae771770SStanislav Sedov while (1) {
322b528cefcSMark Murray if (listen (sock, 1) < 0)
323b528cefcSMark Murray err (1, "listen");
324b528cefcSMark Murray
325b528cefcSMark Murray sock2 = accept (sock, NULL, NULL);
326b528cefcSMark Murray if (sock2 < 0)
327b528cefcSMark Murray err (1, "accept");
328b528cefcSMark Murray
329*ae771770SStanislav Sedov ret = proto (sock2, service);
330*ae771770SStanislav Sedov }
331*ae771770SStanislav Sedov return ret;
332b528cefcSMark Murray }
333b528cefcSMark Murray
334b528cefcSMark Murray int
main(int argc,char ** argv)335b528cefcSMark Murray main(int argc, char **argv)
336b528cefcSMark Murray {
337b528cefcSMark Murray krb5_context context = NULL; /* XXX */
338b528cefcSMark Murray int port = server_setup(&context, argc, argv);
339b528cefcSMark Murray return doit (port, service);
340b528cefcSMark Murray }
341*ae771770SStanislav Sedov
342