155682Smarkm/* 257419Smarkm * Copyright (c) 1997 - 2000 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "test_locl.h" 3555682Smarkm#include <gssapi.h> 3655682Smarkm#include "gss_common.h" 37178825SdfrRCSID("$Id: gssapi_server.c 14762 2005-04-10 14:47:41Z lha $"); 3855682Smarkm 3955682Smarkmstatic int 4057419Smarkmprocess_it(int sock, 4157419Smarkm gss_ctx_id_t context_hdl, 4257419Smarkm gss_name_t client_name 4357419Smarkm ) 4457419Smarkm{ 4557419Smarkm OM_uint32 maj_stat, min_stat; 4657419Smarkm gss_buffer_desc real_input_token, real_output_token; 4757419Smarkm gss_buffer_t input_token = &real_input_token, 4857419Smarkm output_token = &real_output_token; 49178825Sdfr gss_name_t server_name; 50178825Sdfr int conf_flag; 5157419Smarkm 52178825Sdfr print_gss_name("User is", client_name); 53178825Sdfr 54178825Sdfr maj_stat = gss_inquire_context(&min_stat, 55178825Sdfr context_hdl, 56178825Sdfr NULL, 57178825Sdfr &server_name, 58178825Sdfr NULL, 59178825Sdfr NULL, 60178825Sdfr NULL, 61178825Sdfr NULL, 62178825Sdfr NULL); 6357419Smarkm if (GSS_ERROR(maj_stat)) 64178825Sdfr gss_err (1, min_stat, "gss_inquire_context"); 6557419Smarkm 66178825Sdfr print_gss_name("Server is", server_name); 6757419Smarkm 68178825Sdfr maj_stat = gss_release_name(&min_stat, &server_name); 69178825Sdfr if (GSS_ERROR(maj_stat)) 70178825Sdfr gss_err (1, min_stat, "gss_release_name"); 7157419Smarkm 7257419Smarkm /* gss_verify_mic */ 7357419Smarkm 7457419Smarkm read_token (sock, input_token); 7557419Smarkm read_token (sock, output_token); 7657419Smarkm 7757419Smarkm maj_stat = gss_verify_mic (&min_stat, 7857419Smarkm context_hdl, 7957419Smarkm input_token, 8057419Smarkm output_token, 8157419Smarkm NULL); 8257419Smarkm if (GSS_ERROR(maj_stat)) 8357419Smarkm gss_err (1, min_stat, "gss_verify_mic"); 8457419Smarkm 8557419Smarkm fprintf (stderr, "gss_verify_mic: %.*s\n", (int)input_token->length, 8657419Smarkm (char *)input_token->value); 8757419Smarkm 8857419Smarkm gss_release_buffer (&min_stat, input_token); 8957419Smarkm gss_release_buffer (&min_stat, output_token); 9057419Smarkm 9157419Smarkm /* gss_unwrap */ 9257419Smarkm 9357419Smarkm read_token (sock, input_token); 9457419Smarkm 9557419Smarkm maj_stat = gss_unwrap (&min_stat, 9657419Smarkm context_hdl, 9757419Smarkm input_token, 9857419Smarkm output_token, 99178825Sdfr &conf_flag, 10057419Smarkm NULL); 10157419Smarkm if(GSS_ERROR(maj_stat)) 10257419Smarkm gss_err (1, min_stat, "gss_unwrap"); 10357419Smarkm 104178825Sdfr fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length, 105178825Sdfr (char *)output_token->value, 106178825Sdfr conf_flag ? "CONF" : "INT"); 10757419Smarkm 10857419Smarkm gss_release_buffer (&min_stat, input_token); 10957419Smarkm gss_release_buffer (&min_stat, output_token); 11057419Smarkm 111178825Sdfr read_token (sock, input_token); 112178825Sdfr 113178825Sdfr maj_stat = gss_unwrap (&min_stat, 114178825Sdfr context_hdl, 115178825Sdfr input_token, 116178825Sdfr output_token, 117178825Sdfr &conf_flag, 118178825Sdfr NULL); 119178825Sdfr if(GSS_ERROR(maj_stat)) 120178825Sdfr gss_err (1, min_stat, "gss_unwrap"); 121178825Sdfr 122178825Sdfr fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length, 123178825Sdfr (char *)output_token->value, 124178825Sdfr conf_flag ? "CONF" : "INT"); 125178825Sdfr 126178825Sdfr gss_release_buffer (&min_stat, input_token); 127178825Sdfr gss_release_buffer (&min_stat, output_token); 128178825Sdfr 12957419Smarkm return 0; 13057419Smarkm} 13157419Smarkm 13257419Smarkmstatic int 13355682Smarkmproto (int sock, const char *service) 13455682Smarkm{ 13555682Smarkm struct sockaddr_in remote, local; 13672445Sassar socklen_t addrlen; 13755682Smarkm gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT; 13855682Smarkm gss_buffer_desc real_input_token, real_output_token; 13957419Smarkm gss_buffer_t input_token = &real_input_token, 14057419Smarkm output_token = &real_output_token; 14155682Smarkm OM_uint32 maj_stat, min_stat; 14255682Smarkm gss_name_t client_name; 14372445Sassar struct gss_channel_bindings_struct input_chan_bindings; 14472445Sassar gss_cred_id_t delegated_cred_handle = NULL; 14572445Sassar krb5_ccache ccache; 14672445Sassar u_char init_buf[4]; 14772445Sassar u_char acct_buf[4]; 148178825Sdfr gss_OID mech_oid; 149178825Sdfr char *mech, *p; 15055682Smarkm 15155682Smarkm addrlen = sizeof(local); 15255682Smarkm if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 15355682Smarkm || addrlen != sizeof(local)) 15455682Smarkm err (1, "getsockname)"); 15555682Smarkm 15655682Smarkm addrlen = sizeof(remote); 15755682Smarkm if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 15855682Smarkm || addrlen != sizeof(remote)) 15955682Smarkm err (1, "getpeername"); 16055682Smarkm 16172445Sassar input_chan_bindings.initiator_addrtype = GSS_C_AF_INET; 16272445Sassar input_chan_bindings.initiator_address.length = 4; 16372445Sassar init_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF; 16472445Sassar init_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF; 16572445Sassar init_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF; 16672445Sassar init_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF; 16772445Sassar 16872445Sassar input_chan_bindings.initiator_address.value = init_buf; 16972445Sassar input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET; 17072445Sassar 17172445Sassar input_chan_bindings.acceptor_address.length = 4; 17272445Sassar acct_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF; 17372445Sassar acct_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF; 17472445Sassar acct_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF; 17572445Sassar acct_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF; 17672445Sassar input_chan_bindings.acceptor_address.value = acct_buf; 17772445Sassar input_chan_bindings.application_data.value = emalloc(4); 17872445Sassar#if 0 17972445Sassar * (unsigned short *)input_chan_bindings.application_data.value = 18072445Sassar remote.sin_port; 18172445Sassar * ((unsigned short *)input_chan_bindings.application_data.value + 1) = 18272445Sassar local.sin_port; 18372445Sassar input_chan_bindings.application_data.length = 4; 18472445Sassar#else 18572445Sassar input_chan_bindings.application_data.length = 0; 18672445Sassar input_chan_bindings.application_data.value = NULL; 18772445Sassar#endif 18872445Sassar 189178825Sdfr delegated_cred_handle = GSS_C_NO_CREDENTIAL; 19072445Sassar 19155682Smarkm do { 19255682Smarkm read_token (sock, input_token); 19355682Smarkm maj_stat = 19455682Smarkm gss_accept_sec_context (&min_stat, 19555682Smarkm &context_hdl, 19655682Smarkm GSS_C_NO_CREDENTIAL, 19755682Smarkm input_token, 19872445Sassar &input_chan_bindings, 19955682Smarkm &client_name, 200178825Sdfr &mech_oid, 20155682Smarkm output_token, 20255682Smarkm NULL, 20355682Smarkm NULL, 204178825Sdfr &delegated_cred_handle); 20555682Smarkm if(GSS_ERROR(maj_stat)) 20655682Smarkm gss_err (1, min_stat, "gss_accept_sec_context"); 20755682Smarkm if (output_token->length != 0) 20855682Smarkm write_token (sock, output_token); 20955682Smarkm if (GSS_ERROR(maj_stat)) { 21055682Smarkm if (context_hdl != GSS_C_NO_CONTEXT) 21155682Smarkm gss_delete_sec_context (&min_stat, 21255682Smarkm &context_hdl, 21355682Smarkm GSS_C_NO_BUFFER); 21455682Smarkm break; 21555682Smarkm } 21655682Smarkm } while(maj_stat & GSS_S_CONTINUE_NEEDED); 21772445Sassar 218178825Sdfr p = (char *)mech_oid->elements; 219178825Sdfr if (mech_oid->length == GSS_KRB5_MECHANISM->length 220178825Sdfr && memcmp(p, GSS_KRB5_MECHANISM->elements, mech_oid->length) == 0) 221178825Sdfr mech = "Kerberos 5"; 222178825Sdfr else if (mech_oid->length == GSS_SPNEGO_MECHANISM->length 223178825Sdfr && memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_oid->length) == 0) 224178825Sdfr mech = "SPNEGO"; /* XXX Silly, wont show up */ 225178825Sdfr else 226178825Sdfr mech = "Unknown"; 227178825Sdfr 228178825Sdfr printf("Using mech: %s\n", mech); 229178825Sdfr 230178825Sdfr if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) { 23172445Sassar krb5_context context; 23255682Smarkm 233178825Sdfr printf("Delegated cred found\n"); 234178825Sdfr 23572445Sassar maj_stat = krb5_init_context(&context); 23672445Sassar maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache); 237178825Sdfr maj_stat = gss_krb5_copy_ccache(&min_stat, 238178825Sdfr delegated_cred_handle, 239178825Sdfr ccache); 240178825Sdfr if (maj_stat == 0) { 241178825Sdfr krb5_principal p; 242178825Sdfr maj_stat = krb5_cc_get_principal(context, ccache, &p); 243178825Sdfr if (maj_stat == 0) { 244178825Sdfr char *name; 245178825Sdfr maj_stat = krb5_unparse_name(context, p, &name); 246178825Sdfr if (maj_stat == 0) { 247178825Sdfr printf("Delegated user is: `%s'\n", name); 248178825Sdfr free(name); 249178825Sdfr } 250178825Sdfr krb5_free_principal(context, p); 251178825Sdfr } 252178825Sdfr } 25372445Sassar krb5_cc_close(context, ccache); 254178825Sdfr gss_release_cred(&min_stat, &delegated_cred_handle); 25572445Sassar } 25672445Sassar 25757419Smarkm if (fork_flag) { 25857419Smarkm pid_t pid; 25957419Smarkm int pipefd[2]; 26055682Smarkm 26157419Smarkm if (pipe (pipefd) < 0) 26257419Smarkm err (1, "pipe"); 26355682Smarkm 26457419Smarkm pid = fork (); 26557419Smarkm if (pid < 0) 26657419Smarkm err (1, "fork"); 26757419Smarkm if (pid != 0) { 26857419Smarkm gss_buffer_desc buf; 26955682Smarkm 27057419Smarkm maj_stat = gss_export_sec_context (&min_stat, 27157419Smarkm &context_hdl, 27257419Smarkm &buf); 27357419Smarkm if (GSS_ERROR(maj_stat)) 27457419Smarkm gss_err (1, min_stat, "gss_export_sec_context"); 27557419Smarkm write_token (pipefd[1], &buf); 27657419Smarkm exit (0); 27757419Smarkm } else { 27857419Smarkm gss_ctx_id_t context_hdl; 27957419Smarkm gss_buffer_desc buf; 28055682Smarkm 28157419Smarkm close (pipefd[1]); 28257419Smarkm read_token (pipefd[0], &buf); 28357419Smarkm close (pipefd[0]); 28457419Smarkm maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl); 28557419Smarkm if (GSS_ERROR(maj_stat)) 28657419Smarkm gss_err (1, min_stat, "gss_import_sec_context"); 28757419Smarkm gss_release_buffer (&min_stat, &buf); 28857419Smarkm return process_it (sock, context_hdl, client_name); 28957419Smarkm } 29057419Smarkm } else { 29157419Smarkm return process_it (sock, context_hdl, client_name); 29257419Smarkm } 29355682Smarkm} 29455682Smarkm 29555682Smarkmstatic int 29655682Smarkmdoit (int port, const char *service) 29755682Smarkm{ 29855682Smarkm int sock, sock2; 29955682Smarkm struct sockaddr_in my_addr; 30055682Smarkm int one = 1; 30155682Smarkm 30255682Smarkm sock = socket (AF_INET, SOCK_STREAM, 0); 30355682Smarkm if (sock < 0) 30455682Smarkm err (1, "socket"); 30555682Smarkm 30655682Smarkm memset (&my_addr, 0, sizeof(my_addr)); 30755682Smarkm my_addr.sin_family = AF_INET; 30855682Smarkm my_addr.sin_port = port; 30955682Smarkm my_addr.sin_addr.s_addr = INADDR_ANY; 31055682Smarkm 31155682Smarkm if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 31255682Smarkm (void *)&one, sizeof(one)) < 0) 31355682Smarkm warn ("setsockopt SO_REUSEADDR"); 31455682Smarkm 31555682Smarkm if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) 31655682Smarkm err (1, "bind"); 31755682Smarkm 31855682Smarkm if (listen (sock, 1) < 0) 31955682Smarkm err (1, "listen"); 32055682Smarkm 32155682Smarkm sock2 = accept (sock, NULL, NULL); 32255682Smarkm if (sock2 < 0) 32355682Smarkm err (1, "accept"); 32455682Smarkm 32555682Smarkm return proto (sock2, service); 32655682Smarkm} 32755682Smarkm 32855682Smarkmint 32955682Smarkmmain(int argc, char **argv) 33055682Smarkm{ 33155682Smarkm krb5_context context = NULL; /* XXX */ 33255682Smarkm int port = server_setup(&context, argc, argv); 33355682Smarkm return doit (port, service); 33455682Smarkm} 335