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
4257419Smarkmdo_trans (int sock, gss_ctx_id_t context_hdl)
4357419Smarkm{
4457419Smarkm    OM_uint32 maj_stat, min_stat;
4557419Smarkm    gss_buffer_desc real_input_token, real_output_token;
4657419Smarkm    gss_buffer_t input_token = &real_input_token,
4757419Smarkm	output_token = &real_output_token;
4857419Smarkm
4957419Smarkm    /* get_mic */
5057419Smarkm
5157419Smarkm    input_token->length = 3;
5257419Smarkm    input_token->value  = strdup("hej");
5357419Smarkm
5457419Smarkm    maj_stat = gss_get_mic(&min_stat,
5557419Smarkm			   context_hdl,
5657419Smarkm			   GSS_C_QOP_DEFAULT,
5757419Smarkm			   input_token,
5857419Smarkm			   output_token);
5957419Smarkm    if (GSS_ERROR(maj_stat))
6057419Smarkm	gss_err (1, min_stat, "gss_get_mic");
6157419Smarkm
6257419Smarkm    write_token (sock, input_token);
6357419Smarkm    write_token (sock, output_token);
6457419Smarkm
6557419Smarkm    /* wrap */
6657419Smarkm
6757419Smarkm    input_token->length = 7;
6857419Smarkm    input_token->value  = "hemligt";
6957419Smarkm
70178825Sdfr    maj_stat = gss_wrap (&min_stat,
71178825Sdfr			 context_hdl,
72178825Sdfr			 0,
73178825Sdfr			 GSS_C_QOP_DEFAULT,
74178825Sdfr			 input_token,
75178825Sdfr			 NULL,
76178825Sdfr			 output_token);
77178825Sdfr    if (GSS_ERROR(maj_stat))
78178825Sdfr	gss_err (1, min_stat, "gss_wrap");
7957419Smarkm
80178825Sdfr    write_token (sock, output_token);
81178825Sdfr
8257419Smarkm    maj_stat = gss_wrap (&min_stat,
8357419Smarkm			 context_hdl,
8457419Smarkm			 1,
8557419Smarkm			 GSS_C_QOP_DEFAULT,
8657419Smarkm			 input_token,
8757419Smarkm			 NULL,
8857419Smarkm			 output_token);
8957419Smarkm    if (GSS_ERROR(maj_stat))
9057419Smarkm	gss_err (1, min_stat, "gss_wrap");
9157419Smarkm
9257419Smarkm    write_token (sock, output_token);
9357419Smarkm
9457419Smarkm    return 0;
9557419Smarkm}
9657419Smarkm
97233294Sstasextern char *password;
98233294Sstas
9957419Smarkmstatic int
10055682Smarkmproto (int sock, const char *hostname, const char *service)
10155682Smarkm{
102233294Sstas    struct sockaddr_storage remote, local;
10372445Sassar    socklen_t addrlen;
10455682Smarkm
10555682Smarkm    int context_established = 0;
10655682Smarkm    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
107233294Sstas    gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
10855682Smarkm    gss_buffer_desc real_input_token, real_output_token;
10957419Smarkm    gss_buffer_t input_token = &real_input_token,
11057419Smarkm	output_token = &real_output_token;
11155682Smarkm    OM_uint32 maj_stat, min_stat;
11255682Smarkm    gss_name_t server;
11355682Smarkm    gss_buffer_desc name_token;
11472445Sassar    u_char init_buf[4];
11572445Sassar    u_char acct_buf[4];
116178825Sdfr    gss_OID mech_oid;
117178825Sdfr    char *str;
11855682Smarkm
119178825Sdfr    mech_oid = select_mech(mech);
120178825Sdfr
121178825Sdfr    name_token.length = asprintf (&str,
12255682Smarkm				  "%s@%s", service, hostname);
123178825Sdfr    if (str == NULL)
124178825Sdfr	errx(1, "malloc - out of memory");
125178825Sdfr    name_token.value = str;
126233294Sstas
12755682Smarkm    maj_stat = gss_import_name (&min_stat,
12855682Smarkm				&name_token,
12955682Smarkm				GSS_C_NT_HOSTBASED_SERVICE,
13055682Smarkm				&server);
13155682Smarkm    if (GSS_ERROR(maj_stat))
13255682Smarkm	gss_err (1, min_stat,
13355682Smarkm		 "Error importing name `%s@%s':\n", service, hostname);
13455682Smarkm
135233294Sstas    if (password) {
136233294Sstas        gss_buffer_desc pw;
137233294Sstas
138233294Sstas        pw.value = password;
139233294Sstas        pw.length = strlen(password);
140233294Sstas
141233294Sstas        maj_stat = gss_acquire_cred_with_password(&min_stat,
142233294Sstas						  GSS_C_NO_NAME,
143233294Sstas						  &pw,
144233294Sstas						  GSS_C_INDEFINITE,
145233294Sstas						  GSS_C_NO_OID_SET,
146233294Sstas						  GSS_C_INITIATE,
147233294Sstas						  &cred,
148233294Sstas						  NULL,
149233294Sstas						  NULL);
150233294Sstas        if (GSS_ERROR(maj_stat))
151233294Sstas            gss_err (1, min_stat,
152233294Sstas                     "Error acquiring default initiator credentials");
153233294Sstas    }
154233294Sstas
15555682Smarkm    addrlen = sizeof(local);
15655682Smarkm    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
157233294Sstas	|| addrlen > sizeof(local))
15855682Smarkm	err (1, "getsockname(%s)", hostname);
15955682Smarkm
16055682Smarkm    addrlen = sizeof(remote);
16155682Smarkm    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
162233294Sstas	|| addrlen > sizeof(remote))
16355682Smarkm	err (1, "getpeername(%s)", hostname);
16455682Smarkm
16555682Smarkm    input_token->length = 0;
16655682Smarkm    output_token->length = 0;
16755682Smarkm
168233294Sstas#if 0
169233294Sstas    struct gss_channel_bindings_struct input_chan_bindings;
170233294Sstas
17172445Sassar    input_chan_bindings.initiator_addrtype = GSS_C_AF_INET;
17272445Sassar    input_chan_bindings.initiator_address.length = 4;
17372445Sassar    init_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF;
17472445Sassar    init_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF;
17572445Sassar    init_buf[2] = (local.sin_addr.s_addr >>  8) & 0xFF;
17672445Sassar    init_buf[3] = (local.sin_addr.s_addr >>  0) & 0xFF;
17772445Sassar    input_chan_bindings.initiator_address.value = init_buf;
17872445Sassar
17972445Sassar    input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET;
18072445Sassar    input_chan_bindings.acceptor_address.length = 4;
18172445Sassar    acct_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF;
18272445Sassar    acct_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF;
18372445Sassar    acct_buf[2] = (remote.sin_addr.s_addr >>  8) & 0xFF;
18472445Sassar    acct_buf[3] = (remote.sin_addr.s_addr >>  0) & 0xFF;
18572445Sassar    input_chan_bindings.acceptor_address.value = acct_buf;
186233294Sstas
18772445Sassar    input_chan_bindings.application_data.value = emalloc(4);
18872445Sassar    * (unsigned short*)input_chan_bindings.application_data.value = local.sin_port;
18972445Sassar    * ((unsigned short *)input_chan_bindings.application_data.value + 1) = remote.sin_port;
19072445Sassar    input_chan_bindings.application_data.length = 4;
191233294Sstas
19272445Sassar    input_chan_bindings.application_data.length = 0;
19372445Sassar    input_chan_bindings.application_data.value = NULL;
19472445Sassar#endif
19572445Sassar
19655682Smarkm    while(!context_established) {
19755682Smarkm	maj_stat =
19855682Smarkm	    gss_init_sec_context(&min_stat,
199233294Sstas				 cred,
20055682Smarkm				 &context_hdl,
20155682Smarkm				 server,
202178825Sdfr				 mech_oid,
203233294Sstas				 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
20455682Smarkm				 0,
205233294Sstas				 NULL,
20655682Smarkm				 input_token,
20755682Smarkm				 NULL,
20855682Smarkm				 output_token,
20955682Smarkm				 NULL,
21055682Smarkm				 NULL);
21155682Smarkm	if (GSS_ERROR(maj_stat))
21255682Smarkm	    gss_err (1, min_stat, "gss_init_sec_context");
21355682Smarkm	if (output_token->length != 0)
21455682Smarkm	    write_token (sock, output_token);
21555682Smarkm	if (GSS_ERROR(maj_stat)) {
21655682Smarkm	    if (context_hdl != GSS_C_NO_CONTEXT)
21755682Smarkm		gss_delete_sec_context (&min_stat,
21855682Smarkm					&context_hdl,
21955682Smarkm					GSS_C_NO_BUFFER);
22055682Smarkm	    break;
22155682Smarkm	}
22255682Smarkm	if (maj_stat & GSS_S_CONTINUE_NEEDED) {
22355682Smarkm	    read_token (sock, input_token);
22455682Smarkm	} else {
22555682Smarkm	    context_established = 1;
22655682Smarkm	}
22755682Smarkm
22855682Smarkm    }
22957419Smarkm    if (fork_flag) {
23057419Smarkm	pid_t pid;
23157419Smarkm	int pipefd[2];
23255682Smarkm
23357419Smarkm	if (pipe (pipefd) < 0)
23457419Smarkm	    err (1, "pipe");
23555682Smarkm
23657419Smarkm	pid = fork ();
23757419Smarkm	if (pid < 0)
23857419Smarkm	    err (1, "fork");
23957419Smarkm	if (pid != 0) {
24057419Smarkm	    gss_buffer_desc buf;
24155682Smarkm
24257419Smarkm	    maj_stat = gss_export_sec_context (&min_stat,
24357419Smarkm					       &context_hdl,
24457419Smarkm					       &buf);
24557419Smarkm	    if (GSS_ERROR(maj_stat))
24657419Smarkm		gss_err (1, min_stat, "gss_export_sec_context");
24757419Smarkm	    write_token (pipefd[1], &buf);
24857419Smarkm	    exit (0);
24957419Smarkm	} else {
25057419Smarkm	    gss_ctx_id_t context_hdl;
25157419Smarkm	    gss_buffer_desc buf;
25255682Smarkm
25357419Smarkm	    close (pipefd[1]);
25457419Smarkm	    read_token (pipefd[0], &buf);
25557419Smarkm	    close (pipefd[0]);
25657419Smarkm	    maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl);
25757419Smarkm	    if (GSS_ERROR(maj_stat))
25857419Smarkm		gss_err (1, min_stat, "gss_import_sec_context");
25957419Smarkm	    gss_release_buffer (&min_stat, &buf);
26057419Smarkm	    return do_trans (sock, context_hdl);
26157419Smarkm	}
26257419Smarkm    } else {
26357419Smarkm	return do_trans (sock, context_hdl);
26457419Smarkm    }
26555682Smarkm}
26655682Smarkm
26755682Smarkmint
26855682Smarkmmain(int argc, char **argv)
26955682Smarkm{
27055682Smarkm    krb5_context context; /* XXX */
27155682Smarkm    int port = client_setup(&context, &argc, argv);
27255682Smarkm    return client_doit (argv[argc], port, service, proto);
27355682Smarkm}
274