155682Smarkm/*
2233294Sstas * Copyright (c) 1997 - 1999 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"
3555682Smarkm#include <gssapi.h>
3655682Smarkm#include "nt_gss_common.h"
3755682Smarkm
38233294SstasRCSID("$Id$");
3955682Smarkm
4055682Smarkm/*
4155682Smarkm * This program tries to act as a client for the sample in `Sample
4255682Smarkm * SSPI Code' in Windows 2000 RC1 SDK.
4355682Smarkm */
4455682Smarkm
4555682Smarkmstatic int
4655682Smarkmproto (int sock, const char *hostname, const char *service)
4755682Smarkm{
4855682Smarkm    struct sockaddr_in remote, local;
4972445Sassar    socklen_t addrlen;
5055682Smarkm
5155682Smarkm    int context_established = 0;
5255682Smarkm    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
5355682Smarkm    gss_buffer_t input_token, output_token;
5455682Smarkm    gss_buffer_desc real_input_token, real_output_token;
5555682Smarkm    OM_uint32 maj_stat, min_stat;
5655682Smarkm    gss_name_t server;
5755682Smarkm    gss_buffer_desc name_token;
58178825Sdfr    char *str;
5955682Smarkm
60178825Sdfr    name_token.length = asprintf (&str,
6155682Smarkm				  "%s@%s", service, hostname);
62178825Sdfr    if (str == NULL)
63178825Sdfr	errx(1, "out of memory");
64178825Sdfr    name_token.value = str;
6555682Smarkm
6655682Smarkm    maj_stat = gss_import_name (&min_stat,
6755682Smarkm				&name_token,
6855682Smarkm				GSS_C_NT_HOSTBASED_SERVICE,
6955682Smarkm				&server);
7055682Smarkm    if (GSS_ERROR(maj_stat))
7155682Smarkm	gss_err (1, min_stat,
7255682Smarkm		 "Error importing name `%s@%s':\n", service, hostname);
7355682Smarkm
7455682Smarkm    addrlen = sizeof(local);
7555682Smarkm    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
7655682Smarkm	|| addrlen != sizeof(local))
7755682Smarkm	err (1, "getsockname(%s)", hostname);
7855682Smarkm
7955682Smarkm    addrlen = sizeof(remote);
8055682Smarkm    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
8155682Smarkm	|| addrlen != sizeof(remote))
8255682Smarkm	err (1, "getpeername(%s)", hostname);
8355682Smarkm
8455682Smarkm    input_token = &real_input_token;
8555682Smarkm    output_token = &real_output_token;
8655682Smarkm
8755682Smarkm    input_token->length = 0;
8855682Smarkm    output_token->length = 0;
8955682Smarkm
9055682Smarkm    while(!context_established) {
9155682Smarkm	maj_stat =
9255682Smarkm	    gss_init_sec_context(&min_stat,
9355682Smarkm				 GSS_C_NO_CREDENTIAL,
9455682Smarkm				 &context_hdl,
9555682Smarkm				 server,
9655682Smarkm				 GSS_C_NO_OID,
9755682Smarkm				 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
9855682Smarkm				 0,
9955682Smarkm				 GSS_C_NO_CHANNEL_BINDINGS,
10055682Smarkm				 input_token,
10155682Smarkm				 NULL,
10255682Smarkm				 output_token,
10355682Smarkm				 NULL,
10455682Smarkm				 NULL);
10555682Smarkm	if (GSS_ERROR(maj_stat))
10655682Smarkm	    gss_err (1, min_stat, "gss_init_sec_context");
10755682Smarkm	if (output_token->length != 0)
10855682Smarkm	    nt_write_token (sock, output_token);
10955682Smarkm	if (GSS_ERROR(maj_stat)) {
11055682Smarkm	    if (context_hdl != GSS_C_NO_CONTEXT)
11155682Smarkm		gss_delete_sec_context (&min_stat,
11255682Smarkm					&context_hdl,
11355682Smarkm					GSS_C_NO_BUFFER);
11455682Smarkm	    break;
11555682Smarkm	}
11655682Smarkm	if (maj_stat & GSS_S_CONTINUE_NEEDED) {
11755682Smarkm	    nt_read_token (sock, input_token);
11855682Smarkm	} else {
11955682Smarkm	    context_established = 1;
12055682Smarkm	}
12155682Smarkm
12255682Smarkm    }
12355682Smarkm
12455682Smarkm    /* get_mic */
12555682Smarkm
12655682Smarkm    input_token->length = 3;
12755682Smarkm    input_token->value  = strdup("hej");
12855682Smarkm
12955682Smarkm    maj_stat = gss_get_mic(&min_stat,
13055682Smarkm			   context_hdl,
13155682Smarkm			   GSS_C_QOP_DEFAULT,
13255682Smarkm			   input_token,
13355682Smarkm			   output_token);
13455682Smarkm    if (GSS_ERROR(maj_stat))
13555682Smarkm	gss_err (1, min_stat, "gss_get_mic");
13655682Smarkm
13755682Smarkm    nt_write_token (sock, input_token);
13855682Smarkm    nt_write_token (sock, output_token);
13955682Smarkm
14055682Smarkm    /* wrap */
14155682Smarkm
14255682Smarkm    input_token->length = 7;
14355682Smarkm    input_token->value  = "hemligt";
14455682Smarkm
14555682Smarkm
14655682Smarkm    maj_stat = gss_wrap (&min_stat,
14755682Smarkm			 context_hdl,
14855682Smarkm			 1,
14955682Smarkm			 GSS_C_QOP_DEFAULT,
15055682Smarkm			 input_token,
15155682Smarkm			 NULL,
15255682Smarkm			 output_token);
15355682Smarkm    if (GSS_ERROR(maj_stat))
15455682Smarkm	gss_err (1, min_stat, "gss_wrap");
15555682Smarkm
15655682Smarkm    nt_write_token (sock, output_token);
15755682Smarkm
15855682Smarkm    return 0;
15955682Smarkm}
16055682Smarkm
16155682Smarkmint
16255682Smarkmmain(int argc, char **argv)
16355682Smarkm{
16455682Smarkm    krb5_context context; /* XXX */
16555682Smarkm    int port = client_setup(&context, &argc, argv);
16655682Smarkm    return client_doit (argv[argc], port, service, proto);
16755682Smarkm}
168