xref: /freebsd/crypto/heimdal/appl/test/gssapi_server.c (revision c19800e8cd5640693f36f2040db4ab5e8d738146)
1b528cefcSMark Murray /*
2283d988cSMark Murray  * 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"
35b528cefcSMark Murray #include <gssapi.h>
36b528cefcSMark Murray #include "gss_common.h"
37c19800e8SDoug Rabson RCSID("$Id: gssapi_server.c 14762 2005-04-10 14:47:41Z lha $");
38283d988cSMark Murray 
39283d988cSMark Murray static int
40283d988cSMark Murray process_it(int sock,
41283d988cSMark Murray 	   gss_ctx_id_t context_hdl,
42283d988cSMark Murray 	   gss_name_t client_name
43283d988cSMark Murray 	   )
44283d988cSMark Murray {
45283d988cSMark Murray     OM_uint32 maj_stat, min_stat;
46283d988cSMark Murray     gss_buffer_desc real_input_token, real_output_token;
47283d988cSMark Murray     gss_buffer_t input_token = &real_input_token,
48283d988cSMark Murray 	output_token = &real_output_token;
49c19800e8SDoug Rabson     gss_name_t server_name;
50c19800e8SDoug Rabson     int conf_flag;
51283d988cSMark Murray 
52c19800e8SDoug Rabson     print_gss_name("User is", client_name);
53c19800e8SDoug Rabson 
54c19800e8SDoug Rabson     maj_stat = gss_inquire_context(&min_stat,
55c19800e8SDoug Rabson 				   context_hdl,
56c19800e8SDoug Rabson 				   NULL,
57c19800e8SDoug Rabson 				   &server_name,
58c19800e8SDoug Rabson 				   NULL,
59c19800e8SDoug Rabson 				   NULL,
60c19800e8SDoug Rabson 				   NULL,
61c19800e8SDoug Rabson 				   NULL,
62283d988cSMark Murray 				   NULL);
63283d988cSMark Murray     if (GSS_ERROR(maj_stat))
64c19800e8SDoug Rabson 	gss_err (1, min_stat, "gss_inquire_context");
65283d988cSMark Murray 
66c19800e8SDoug Rabson     print_gss_name("Server is", server_name);
67283d988cSMark Murray 
68c19800e8SDoug Rabson     maj_stat = gss_release_name(&min_stat, &server_name);
69c19800e8SDoug Rabson     if (GSS_ERROR(maj_stat))
70c19800e8SDoug Rabson 	gss_err (1, min_stat, "gss_release_name");
71283d988cSMark Murray 
72283d988cSMark Murray     /* gss_verify_mic */
73283d988cSMark Murray 
74283d988cSMark Murray     read_token (sock, input_token);
75283d988cSMark Murray     read_token (sock, output_token);
76283d988cSMark Murray 
77283d988cSMark Murray     maj_stat = gss_verify_mic (&min_stat,
78283d988cSMark Murray 			       context_hdl,
79283d988cSMark Murray 			       input_token,
80283d988cSMark Murray 			       output_token,
81283d988cSMark Murray 			       NULL);
82283d988cSMark Murray     if (GSS_ERROR(maj_stat))
83283d988cSMark Murray 	gss_err (1, min_stat, "gss_verify_mic");
84283d988cSMark Murray 
85283d988cSMark Murray     fprintf (stderr, "gss_verify_mic: %.*s\n", (int)input_token->length,
86283d988cSMark Murray 	    (char *)input_token->value);
87283d988cSMark Murray 
88283d988cSMark Murray     gss_release_buffer (&min_stat, input_token);
89283d988cSMark Murray     gss_release_buffer (&min_stat, output_token);
90283d988cSMark Murray 
91283d988cSMark Murray     /* gss_unwrap */
92283d988cSMark Murray 
93283d988cSMark Murray     read_token (sock, input_token);
94283d988cSMark Murray 
95283d988cSMark Murray     maj_stat = gss_unwrap (&min_stat,
96283d988cSMark Murray 			   context_hdl,
97283d988cSMark Murray 			   input_token,
98283d988cSMark Murray 			   output_token,
99c19800e8SDoug Rabson 			   &conf_flag,
100283d988cSMark Murray 			   NULL);
101283d988cSMark Murray     if(GSS_ERROR(maj_stat))
102283d988cSMark Murray 	gss_err (1, min_stat, "gss_unwrap");
103283d988cSMark Murray 
104c19800e8SDoug Rabson     fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length,
105c19800e8SDoug Rabson 	    (char *)output_token->value,
106c19800e8SDoug Rabson 	     conf_flag ? "CONF" : "INT");
107c19800e8SDoug Rabson 
108c19800e8SDoug Rabson     gss_release_buffer (&min_stat, input_token);
109c19800e8SDoug Rabson     gss_release_buffer (&min_stat, output_token);
110c19800e8SDoug Rabson 
111c19800e8SDoug Rabson     read_token (sock, input_token);
112c19800e8SDoug Rabson 
113c19800e8SDoug Rabson     maj_stat = gss_unwrap (&min_stat,
114c19800e8SDoug Rabson 			   context_hdl,
115c19800e8SDoug Rabson 			   input_token,
116c19800e8SDoug Rabson 			   output_token,
117c19800e8SDoug Rabson 			   &conf_flag,
118c19800e8SDoug Rabson 			   NULL);
119c19800e8SDoug Rabson     if(GSS_ERROR(maj_stat))
120c19800e8SDoug Rabson 	gss_err (1, min_stat, "gss_unwrap");
121c19800e8SDoug Rabson 
122c19800e8SDoug Rabson     fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length,
123c19800e8SDoug Rabson 	     (char *)output_token->value,
124c19800e8SDoug Rabson 	     conf_flag ? "CONF" : "INT");
125283d988cSMark Murray 
126283d988cSMark Murray     gss_release_buffer (&min_stat, input_token);
127283d988cSMark Murray     gss_release_buffer (&min_stat, output_token);
128283d988cSMark Murray 
129283d988cSMark Murray     return 0;
130283d988cSMark Murray }
131b528cefcSMark Murray 
132b528cefcSMark Murray static int
133b528cefcSMark Murray proto (int sock, const char *service)
134b528cefcSMark Murray {
135b528cefcSMark Murray     struct sockaddr_in remote, local;
1365e9cd1aeSAssar Westerlund     socklen_t addrlen;
137b528cefcSMark Murray     gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
138b528cefcSMark Murray     gss_buffer_desc real_input_token, real_output_token;
139283d988cSMark Murray     gss_buffer_t input_token = &real_input_token,
140283d988cSMark Murray 	output_token = &real_output_token;
141b528cefcSMark Murray     OM_uint32 maj_stat, min_stat;
142b528cefcSMark Murray     gss_name_t client_name;
1435e9cd1aeSAssar Westerlund     struct gss_channel_bindings_struct input_chan_bindings;
1445e9cd1aeSAssar Westerlund     gss_cred_id_t delegated_cred_handle = NULL;
1455e9cd1aeSAssar Westerlund     krb5_ccache ccache;
1465e9cd1aeSAssar Westerlund     u_char init_buf[4];
1475e9cd1aeSAssar Westerlund     u_char acct_buf[4];
148c19800e8SDoug Rabson     gss_OID mech_oid;
149c19800e8SDoug Rabson     char *mech, *p;
150b528cefcSMark Murray 
151b528cefcSMark Murray     addrlen = sizeof(local);
152b528cefcSMark Murray     if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
153b528cefcSMark Murray 	|| addrlen != sizeof(local))
154b528cefcSMark Murray 	err (1, "getsockname)");
155b528cefcSMark Murray 
156b528cefcSMark Murray     addrlen = sizeof(remote);
157b528cefcSMark Murray     if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
158b528cefcSMark Murray 	|| addrlen != sizeof(remote))
159b528cefcSMark Murray 	err (1, "getpeername");
160b528cefcSMark Murray 
1615e9cd1aeSAssar Westerlund     input_chan_bindings.initiator_addrtype = GSS_C_AF_INET;
1625e9cd1aeSAssar Westerlund     input_chan_bindings.initiator_address.length = 4;
1635e9cd1aeSAssar Westerlund     init_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF;
1645e9cd1aeSAssar Westerlund     init_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF;
1655e9cd1aeSAssar Westerlund     init_buf[2] = (remote.sin_addr.s_addr >>  8) & 0xFF;
1665e9cd1aeSAssar Westerlund     init_buf[3] = (remote.sin_addr.s_addr >>  0) & 0xFF;
1675e9cd1aeSAssar Westerlund 
1685e9cd1aeSAssar Westerlund     input_chan_bindings.initiator_address.value = init_buf;
1695e9cd1aeSAssar Westerlund     input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET;
1705e9cd1aeSAssar Westerlund 
1715e9cd1aeSAssar Westerlund     input_chan_bindings.acceptor_address.length = 4;
1725e9cd1aeSAssar Westerlund     acct_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF;
1735e9cd1aeSAssar Westerlund     acct_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF;
1745e9cd1aeSAssar Westerlund     acct_buf[2] = (local.sin_addr.s_addr >>  8) & 0xFF;
1755e9cd1aeSAssar Westerlund     acct_buf[3] = (local.sin_addr.s_addr >>  0) & 0xFF;
1765e9cd1aeSAssar Westerlund     input_chan_bindings.acceptor_address.value = acct_buf;
1775e9cd1aeSAssar Westerlund     input_chan_bindings.application_data.value = emalloc(4);
1785e9cd1aeSAssar Westerlund #if 0
1795e9cd1aeSAssar Westerlund     * (unsigned short *)input_chan_bindings.application_data.value =
1805e9cd1aeSAssar Westerlund                           remote.sin_port;
1815e9cd1aeSAssar Westerlund     * ((unsigned short *)input_chan_bindings.application_data.value + 1) =
1825e9cd1aeSAssar Westerlund                           local.sin_port;
1835e9cd1aeSAssar Westerlund     input_chan_bindings.application_data.length = 4;
1845e9cd1aeSAssar Westerlund #else
1855e9cd1aeSAssar Westerlund     input_chan_bindings.application_data.length = 0;
1865e9cd1aeSAssar Westerlund     input_chan_bindings.application_data.value = NULL;
1875e9cd1aeSAssar Westerlund #endif
1885e9cd1aeSAssar Westerlund 
189c19800e8SDoug Rabson     delegated_cred_handle = GSS_C_NO_CREDENTIAL;
1905e9cd1aeSAssar Westerlund 
191b528cefcSMark Murray     do {
192b528cefcSMark Murray 	read_token (sock, input_token);
193b528cefcSMark Murray 	maj_stat =
194b528cefcSMark Murray 	    gss_accept_sec_context (&min_stat,
195b528cefcSMark Murray 				    &context_hdl,
196b528cefcSMark Murray 				    GSS_C_NO_CREDENTIAL,
197b528cefcSMark Murray 				    input_token,
1985e9cd1aeSAssar Westerlund 				    &input_chan_bindings,
199b528cefcSMark Murray 				    &client_name,
200c19800e8SDoug Rabson 				    &mech_oid,
201b528cefcSMark Murray 				    output_token,
202b528cefcSMark Murray 				    NULL,
203b528cefcSMark Murray 				    NULL,
204c19800e8SDoug Rabson 				    &delegated_cred_handle);
205b528cefcSMark Murray 	if(GSS_ERROR(maj_stat))
206b528cefcSMark Murray 	    gss_err (1, min_stat, "gss_accept_sec_context");
207b528cefcSMark Murray 	if (output_token->length != 0)
208b528cefcSMark Murray 	    write_token (sock, output_token);
209b528cefcSMark Murray 	if (GSS_ERROR(maj_stat)) {
210b528cefcSMark Murray 	    if (context_hdl != GSS_C_NO_CONTEXT)
211b528cefcSMark Murray 		gss_delete_sec_context (&min_stat,
212b528cefcSMark Murray 					&context_hdl,
213b528cefcSMark Murray 					GSS_C_NO_BUFFER);
214b528cefcSMark Murray 	    break;
215b528cefcSMark Murray 	}
216b528cefcSMark Murray     } while(maj_stat & GSS_S_CONTINUE_NEEDED);
217b528cefcSMark Murray 
218c19800e8SDoug Rabson     p = (char *)mech_oid->elements;
219c19800e8SDoug Rabson     if (mech_oid->length == GSS_KRB5_MECHANISM->length
220c19800e8SDoug Rabson 	&& memcmp(p, GSS_KRB5_MECHANISM->elements, mech_oid->length) == 0)
221c19800e8SDoug Rabson 	mech = "Kerberos 5";
222c19800e8SDoug Rabson     else if (mech_oid->length == GSS_SPNEGO_MECHANISM->length
223c19800e8SDoug Rabson 	&& memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_oid->length) == 0)
224c19800e8SDoug Rabson 	mech = "SPNEGO"; /* XXX Silly, wont show up */
225c19800e8SDoug Rabson     else
226c19800e8SDoug Rabson 	mech = "Unknown";
227c19800e8SDoug Rabson 
228c19800e8SDoug Rabson     printf("Using mech: %s\n", mech);
229c19800e8SDoug Rabson 
230c19800e8SDoug Rabson     if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
2315e9cd1aeSAssar Westerlund        krb5_context context;
2325e9cd1aeSAssar Westerlund 
233c19800e8SDoug Rabson        printf("Delegated cred found\n");
234c19800e8SDoug Rabson 
2355e9cd1aeSAssar Westerlund        maj_stat = krb5_init_context(&context);
2365e9cd1aeSAssar Westerlund        maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache);
237c19800e8SDoug Rabson        maj_stat = gss_krb5_copy_ccache(&min_stat,
238c19800e8SDoug Rabson 				       delegated_cred_handle,
239c19800e8SDoug Rabson 				       ccache);
240c19800e8SDoug Rabson        if (maj_stat == 0) {
241c19800e8SDoug Rabson 	   krb5_principal p;
242c19800e8SDoug Rabson 	   maj_stat = krb5_cc_get_principal(context, ccache, &p);
243c19800e8SDoug Rabson 	   if (maj_stat == 0) {
244c19800e8SDoug Rabson 	       char *name;
245c19800e8SDoug Rabson 	       maj_stat = krb5_unparse_name(context, p, &name);
246c19800e8SDoug Rabson 	       if (maj_stat == 0) {
247c19800e8SDoug Rabson 		   printf("Delegated user is: `%s'\n", name);
248c19800e8SDoug Rabson 		   free(name);
249c19800e8SDoug Rabson 	       }
250c19800e8SDoug Rabson 	       krb5_free_principal(context, p);
251c19800e8SDoug Rabson 	   }
252c19800e8SDoug Rabson        }
2535e9cd1aeSAssar Westerlund        krb5_cc_close(context, ccache);
254c19800e8SDoug Rabson        gss_release_cred(&min_stat, &delegated_cred_handle);
2555e9cd1aeSAssar Westerlund     }
2565e9cd1aeSAssar Westerlund 
257283d988cSMark Murray     if (fork_flag) {
258283d988cSMark Murray 	pid_t pid;
259283d988cSMark Murray 	int pipefd[2];
260283d988cSMark Murray 
261283d988cSMark Murray 	if (pipe (pipefd) < 0)
262283d988cSMark Murray 	    err (1, "pipe");
263283d988cSMark Murray 
264283d988cSMark Murray 	pid = fork ();
265283d988cSMark Murray 	if (pid < 0)
266283d988cSMark Murray 	    err (1, "fork");
267283d988cSMark Murray 	if (pid != 0) {
268283d988cSMark Murray 	    gss_buffer_desc buf;
269283d988cSMark Murray 
270283d988cSMark Murray 	    maj_stat = gss_export_sec_context (&min_stat,
271283d988cSMark Murray 					       &context_hdl,
272283d988cSMark Murray 					       &buf);
273b528cefcSMark Murray 	    if (GSS_ERROR(maj_stat))
274283d988cSMark Murray 		gss_err (1, min_stat, "gss_export_sec_context");
275283d988cSMark Murray 	    write_token (pipefd[1], &buf);
276283d988cSMark Murray 	    exit (0);
277283d988cSMark Murray 	} else {
278283d988cSMark Murray 	    gss_ctx_id_t context_hdl;
279283d988cSMark Murray 	    gss_buffer_desc buf;
280b528cefcSMark Murray 
281283d988cSMark Murray 	    close (pipefd[1]);
282283d988cSMark Murray 	    read_token (pipefd[0], &buf);
283283d988cSMark Murray 	    close (pipefd[0]);
284283d988cSMark Murray 	    maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl);
285b528cefcSMark Murray 	    if (GSS_ERROR(maj_stat))
286283d988cSMark Murray 		gss_err (1, min_stat, "gss_import_sec_context");
287283d988cSMark Murray 	    gss_release_buffer (&min_stat, &buf);
288283d988cSMark Murray 	    return process_it (sock, context_hdl, client_name);
289283d988cSMark Murray 	}
290283d988cSMark Murray     } else {
291283d988cSMark Murray 	return process_it (sock, context_hdl, client_name);
292283d988cSMark Murray     }
293b528cefcSMark Murray }
294b528cefcSMark Murray 
295b528cefcSMark Murray static int
296b528cefcSMark Murray doit (int port, const char *service)
297b528cefcSMark Murray {
298b528cefcSMark Murray     int sock, sock2;
299b528cefcSMark Murray     struct sockaddr_in my_addr;
300b528cefcSMark Murray     int one = 1;
301b528cefcSMark Murray 
302b528cefcSMark Murray     sock = socket (AF_INET, SOCK_STREAM, 0);
303b528cefcSMark Murray     if (sock < 0)
304b528cefcSMark Murray 	err (1, "socket");
305b528cefcSMark Murray 
306b528cefcSMark Murray     memset (&my_addr, 0, sizeof(my_addr));
307b528cefcSMark Murray     my_addr.sin_family      = AF_INET;
308b528cefcSMark Murray     my_addr.sin_port        = port;
309b528cefcSMark Murray     my_addr.sin_addr.s_addr = INADDR_ANY;
310b528cefcSMark Murray 
311b528cefcSMark Murray     if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
312b528cefcSMark Murray 		    (void *)&one, sizeof(one)) < 0)
313b528cefcSMark Murray 	warn ("setsockopt SO_REUSEADDR");
314b528cefcSMark Murray 
315b528cefcSMark Murray     if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
316b528cefcSMark Murray 	err (1, "bind");
317b528cefcSMark Murray 
318b528cefcSMark Murray     if (listen (sock, 1) < 0)
319b528cefcSMark Murray 	err (1, "listen");
320b528cefcSMark Murray 
321b528cefcSMark Murray     sock2 = accept (sock, NULL, NULL);
322b528cefcSMark Murray     if (sock2 < 0)
323b528cefcSMark Murray 	err (1, "accept");
324b528cefcSMark Murray 
325b528cefcSMark Murray     return proto (sock2, service);
326b528cefcSMark Murray }
327b528cefcSMark Murray 
328b528cefcSMark Murray int
329b528cefcSMark Murray main(int argc, char **argv)
330b528cefcSMark Murray {
331b528cefcSMark Murray     krb5_context context = NULL; /* XXX */
332b528cefcSMark Murray     int port = server_setup(&context, argc, argv);
333b528cefcSMark Murray     return doit (port, service);
334b528cefcSMark Murray }
335