155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2000 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 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. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "test_locl.h" 35233294Sstas#include <gssapi/gssapi.h> 36233294Sstas#include <gssapi/gssapi_krb5.h> 37233294Sstas#include <gssapi/gssapi_spnego.h> 3855682Smarkm#include "gss_common.h" 39233294SstasRCSID("$Id$"); 4055682Smarkm 4155682Smarkmstatic int 4257419Smarkmprocess_it(int sock, 4357419Smarkm gss_ctx_id_t context_hdl, 4457419Smarkm gss_name_t client_name 4557419Smarkm ) 4657419Smarkm{ 4757419Smarkm OM_uint32 maj_stat, min_stat; 4857419Smarkm gss_buffer_desc real_input_token, real_output_token; 4957419Smarkm gss_buffer_t input_token = &real_input_token, 5057419Smarkm output_token = &real_output_token; 51178825Sdfr gss_name_t server_name; 52178825Sdfr int conf_flag; 5357419Smarkm 54178825Sdfr print_gss_name("User is", client_name); 55178825Sdfr 56178825Sdfr maj_stat = gss_inquire_context(&min_stat, 57178825Sdfr context_hdl, 58178825Sdfr NULL, 59178825Sdfr &server_name, 60178825Sdfr NULL, 61178825Sdfr NULL, 62178825Sdfr NULL, 63178825Sdfr NULL, 64178825Sdfr NULL); 6557419Smarkm if (GSS_ERROR(maj_stat)) 66178825Sdfr gss_err (1, min_stat, "gss_inquire_context"); 6757419Smarkm 68178825Sdfr print_gss_name("Server is", server_name); 6957419Smarkm 70178825Sdfr maj_stat = gss_release_name(&min_stat, &server_name); 71178825Sdfr if (GSS_ERROR(maj_stat)) 72178825Sdfr gss_err (1, min_stat, "gss_release_name"); 7357419Smarkm 7457419Smarkm /* gss_verify_mic */ 7557419Smarkm 7657419Smarkm read_token (sock, input_token); 7757419Smarkm read_token (sock, output_token); 7857419Smarkm 7957419Smarkm maj_stat = gss_verify_mic (&min_stat, 8057419Smarkm context_hdl, 8157419Smarkm input_token, 8257419Smarkm output_token, 8357419Smarkm NULL); 8457419Smarkm if (GSS_ERROR(maj_stat)) 8557419Smarkm gss_err (1, min_stat, "gss_verify_mic"); 8657419Smarkm 8757419Smarkm fprintf (stderr, "gss_verify_mic: %.*s\n", (int)input_token->length, 8857419Smarkm (char *)input_token->value); 8957419Smarkm 9057419Smarkm gss_release_buffer (&min_stat, input_token); 9157419Smarkm gss_release_buffer (&min_stat, output_token); 9257419Smarkm 9357419Smarkm /* gss_unwrap */ 9457419Smarkm 9557419Smarkm read_token (sock, input_token); 9657419Smarkm 9757419Smarkm maj_stat = gss_unwrap (&min_stat, 9857419Smarkm context_hdl, 9957419Smarkm input_token, 10057419Smarkm output_token, 101178825Sdfr &conf_flag, 10257419Smarkm NULL); 10357419Smarkm if(GSS_ERROR(maj_stat)) 10457419Smarkm gss_err (1, min_stat, "gss_unwrap"); 10557419Smarkm 106178825Sdfr fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length, 107178825Sdfr (char *)output_token->value, 108178825Sdfr conf_flag ? "CONF" : "INT"); 10957419Smarkm 11057419Smarkm gss_release_buffer (&min_stat, input_token); 11157419Smarkm gss_release_buffer (&min_stat, output_token); 11257419Smarkm 113178825Sdfr read_token (sock, input_token); 114178825Sdfr 115178825Sdfr maj_stat = gss_unwrap (&min_stat, 116178825Sdfr context_hdl, 117178825Sdfr input_token, 118178825Sdfr output_token, 119178825Sdfr &conf_flag, 120178825Sdfr NULL); 121178825Sdfr if(GSS_ERROR(maj_stat)) 122178825Sdfr gss_err (1, min_stat, "gss_unwrap"); 123178825Sdfr 124178825Sdfr fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length, 125178825Sdfr (char *)output_token->value, 126178825Sdfr conf_flag ? "CONF" : "INT"); 127178825Sdfr 128178825Sdfr gss_release_buffer (&min_stat, input_token); 129178825Sdfr gss_release_buffer (&min_stat, output_token); 130178825Sdfr 13157419Smarkm return 0; 13257419Smarkm} 13357419Smarkm 13457419Smarkmstatic int 13555682Smarkmproto (int sock, const char *service) 13655682Smarkm{ 13755682Smarkm struct sockaddr_in remote, local; 13872445Sassar socklen_t addrlen; 13955682Smarkm gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT; 14055682Smarkm gss_buffer_desc real_input_token, real_output_token; 14157419Smarkm gss_buffer_t input_token = &real_input_token, 14257419Smarkm output_token = &real_output_token; 14355682Smarkm OM_uint32 maj_stat, min_stat; 14455682Smarkm gss_name_t client_name; 14572445Sassar struct gss_channel_bindings_struct input_chan_bindings; 14672445Sassar gss_cred_id_t delegated_cred_handle = NULL; 14772445Sassar krb5_ccache ccache; 14872445Sassar u_char init_buf[4]; 14972445Sassar u_char acct_buf[4]; 150178825Sdfr gss_OID mech_oid; 151178825Sdfr char *mech, *p; 15255682Smarkm 15355682Smarkm addrlen = sizeof(local); 15455682Smarkm if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 15555682Smarkm || addrlen != sizeof(local)) 15655682Smarkm err (1, "getsockname)"); 15755682Smarkm 15855682Smarkm addrlen = sizeof(remote); 15955682Smarkm if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 16055682Smarkm || addrlen != sizeof(remote)) 16155682Smarkm err (1, "getpeername"); 16255682Smarkm 16372445Sassar input_chan_bindings.initiator_addrtype = GSS_C_AF_INET; 16472445Sassar input_chan_bindings.initiator_address.length = 4; 16572445Sassar init_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF; 16672445Sassar init_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF; 16772445Sassar init_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF; 16872445Sassar init_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF; 16972445Sassar 17072445Sassar input_chan_bindings.initiator_address.value = init_buf; 17172445Sassar input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET; 17272445Sassar 17372445Sassar input_chan_bindings.acceptor_address.length = 4; 17472445Sassar acct_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF; 17572445Sassar acct_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF; 17672445Sassar acct_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF; 17772445Sassar acct_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF; 17872445Sassar input_chan_bindings.acceptor_address.value = acct_buf; 17972445Sassar input_chan_bindings.application_data.value = emalloc(4); 18072445Sassar#if 0 18172445Sassar * (unsigned short *)input_chan_bindings.application_data.value = 18272445Sassar remote.sin_port; 18372445Sassar * ((unsigned short *)input_chan_bindings.application_data.value + 1) = 18472445Sassar local.sin_port; 18572445Sassar input_chan_bindings.application_data.length = 4; 18672445Sassar#else 18772445Sassar input_chan_bindings.application_data.length = 0; 18872445Sassar input_chan_bindings.application_data.value = NULL; 18972445Sassar#endif 190233294Sstas 191178825Sdfr delegated_cred_handle = GSS_C_NO_CREDENTIAL; 192233294Sstas 19355682Smarkm do { 19455682Smarkm read_token (sock, input_token); 19555682Smarkm maj_stat = 19655682Smarkm gss_accept_sec_context (&min_stat, 19755682Smarkm &context_hdl, 19855682Smarkm GSS_C_NO_CREDENTIAL, 19955682Smarkm input_token, 20072445Sassar &input_chan_bindings, 20155682Smarkm &client_name, 202178825Sdfr &mech_oid, 20355682Smarkm output_token, 20455682Smarkm NULL, 20555682Smarkm NULL, 206178825Sdfr &delegated_cred_handle); 20755682Smarkm if(GSS_ERROR(maj_stat)) 20855682Smarkm gss_err (1, min_stat, "gss_accept_sec_context"); 20955682Smarkm if (output_token->length != 0) 21055682Smarkm write_token (sock, output_token); 21155682Smarkm if (GSS_ERROR(maj_stat)) { 21255682Smarkm if (context_hdl != GSS_C_NO_CONTEXT) 21355682Smarkm gss_delete_sec_context (&min_stat, 21455682Smarkm &context_hdl, 21555682Smarkm GSS_C_NO_BUFFER); 21655682Smarkm break; 21755682Smarkm } 21855682Smarkm } while(maj_stat & GSS_S_CONTINUE_NEEDED); 219233294Sstas 220178825Sdfr p = (char *)mech_oid->elements; 221178825Sdfr if (mech_oid->length == GSS_KRB5_MECHANISM->length 222178825Sdfr && memcmp(p, GSS_KRB5_MECHANISM->elements, mech_oid->length) == 0) 223178825Sdfr mech = "Kerberos 5"; 224178825Sdfr else if (mech_oid->length == GSS_SPNEGO_MECHANISM->length 225178825Sdfr && memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_oid->length) == 0) 226178825Sdfr mech = "SPNEGO"; /* XXX Silly, wont show up */ 227178825Sdfr else 228178825Sdfr mech = "Unknown"; 229178825Sdfr 230178825Sdfr printf("Using mech: %s\n", mech); 231178825Sdfr 232178825Sdfr if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) { 23372445Sassar krb5_context context; 23455682Smarkm 235178825Sdfr printf("Delegated cred found\n"); 236178825Sdfr 23772445Sassar maj_stat = krb5_init_context(&context); 23872445Sassar maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache); 239178825Sdfr maj_stat = gss_krb5_copy_ccache(&min_stat, 240178825Sdfr delegated_cred_handle, 241178825Sdfr ccache); 242178825Sdfr if (maj_stat == 0) { 243178825Sdfr krb5_principal p; 244178825Sdfr maj_stat = krb5_cc_get_principal(context, ccache, &p); 245178825Sdfr if (maj_stat == 0) { 246178825Sdfr char *name; 247178825Sdfr maj_stat = krb5_unparse_name(context, p, &name); 248178825Sdfr if (maj_stat == 0) { 249178825Sdfr printf("Delegated user is: `%s'\n", name); 250178825Sdfr free(name); 251178825Sdfr } 252178825Sdfr krb5_free_principal(context, p); 253178825Sdfr } 254178825Sdfr } 25572445Sassar krb5_cc_close(context, ccache); 256178825Sdfr gss_release_cred(&min_stat, &delegated_cred_handle); 25772445Sassar } 25872445Sassar 25957419Smarkm if (fork_flag) { 26057419Smarkm pid_t pid; 26157419Smarkm int pipefd[2]; 26255682Smarkm 26357419Smarkm if (pipe (pipefd) < 0) 26457419Smarkm err (1, "pipe"); 26555682Smarkm 26657419Smarkm pid = fork (); 26757419Smarkm if (pid < 0) 26857419Smarkm err (1, "fork"); 26957419Smarkm if (pid != 0) { 27057419Smarkm gss_buffer_desc buf; 27155682Smarkm 27257419Smarkm maj_stat = gss_export_sec_context (&min_stat, 27357419Smarkm &context_hdl, 27457419Smarkm &buf); 27557419Smarkm if (GSS_ERROR(maj_stat)) 27657419Smarkm gss_err (1, min_stat, "gss_export_sec_context"); 27757419Smarkm write_token (pipefd[1], &buf); 27857419Smarkm exit (0); 27957419Smarkm } else { 28057419Smarkm gss_ctx_id_t context_hdl; 28157419Smarkm gss_buffer_desc buf; 28255682Smarkm 28357419Smarkm close (pipefd[1]); 28457419Smarkm read_token (pipefd[0], &buf); 28557419Smarkm close (pipefd[0]); 28657419Smarkm maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl); 28757419Smarkm if (GSS_ERROR(maj_stat)) 28857419Smarkm gss_err (1, min_stat, "gss_import_sec_context"); 28957419Smarkm gss_release_buffer (&min_stat, &buf); 29057419Smarkm return process_it (sock, context_hdl, client_name); 29157419Smarkm } 29257419Smarkm } else { 29357419Smarkm return process_it (sock, context_hdl, client_name); 29457419Smarkm } 29555682Smarkm} 29655682Smarkm 29755682Smarkmstatic int 29855682Smarkmdoit (int port, const char *service) 29955682Smarkm{ 30055682Smarkm int sock, sock2; 30155682Smarkm struct sockaddr_in my_addr; 30255682Smarkm int one = 1; 303233294Sstas int ret; 30455682Smarkm 30555682Smarkm sock = socket (AF_INET, SOCK_STREAM, 0); 30655682Smarkm if (sock < 0) 30755682Smarkm err (1, "socket"); 30855682Smarkm 30955682Smarkm memset (&my_addr, 0, sizeof(my_addr)); 31055682Smarkm my_addr.sin_family = AF_INET; 31155682Smarkm my_addr.sin_port = port; 31255682Smarkm my_addr.sin_addr.s_addr = INADDR_ANY; 31355682Smarkm 31455682Smarkm if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 31555682Smarkm (void *)&one, sizeof(one)) < 0) 31655682Smarkm warn ("setsockopt SO_REUSEADDR"); 31755682Smarkm 31855682Smarkm if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) 31955682Smarkm err (1, "bind"); 32055682Smarkm 321233294Sstas while (1) { 322233294Sstas if (listen (sock, 1) < 0) 323233294Sstas err (1, "listen"); 32455682Smarkm 325233294Sstas sock2 = accept (sock, NULL, NULL); 326233294Sstas if (sock2 < 0) 327233294Sstas err (1, "accept"); 32855682Smarkm 329233294Sstas ret = proto (sock2, service); 330233294Sstas } 331233294Sstas return ret; 33255682Smarkm} 33355682Smarkm 33455682Smarkmint 33555682Smarkmmain(int argc, char **argv) 33655682Smarkm{ 33755682Smarkm krb5_context context = NULL; /* XXX */ 33855682Smarkm int port = server_setup(&context, argc, argv); 33955682Smarkm return doit (port, service); 34055682Smarkm} 341233294Sstas 342