xref: /freebsd/crypto/heimdal/appl/test/gssapi_server.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
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