/*
 * Copyright 2001 by Lionel Schwarz, Computing Center IN2P3
 * 
 */

#include <stdio.h>
#include "gfw-misc.h"
#include "gfw.h"

#ifndef gss_nt_service_name
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#endif

/*
 * Function: gfw_init_sec_context
 *
 * Purpose: initiate a context
 *
 * Arguments:
 *
 *  minor_status    (w) the second status
 * 	is              (r) the input stream socket
 * 	os              (r) the output stream socket
 * 	service_name    (r) the GSS-API service name to authenticate to	
 *
 * Returns: major status
 *
 * Effects:
 * 
 * gfw_init_sec_context establishes a GSS-API context with service_name 
 * over the connection designated by the two sockets. 
 */

OM_uint32 gfw_init_sec_context(
OM_uint32 * minor_status, 
int         is, 
int         os, 
char *      service_name)
{
    gss_ctx_id_t gss_context;
    OM_uint32 ret_flags;
    OM_uint32 maj_stat, min_stat;
    size_t	i;
    gss_buffer_desc send_tok, recv_tok, *token_ptr;
    gss_name_t target_name;

    OM_uint32 deleg_flag=0;
    gss_OID oid = GSS_C_NULL_OID;

    gss_name_t		src_name, targ_name;
    gss_buffer_desc	sname, tname;
    gss_buffer_desc client_name, xmit_buf, logon_buf;
    OM_uint32		lifetime;
    gss_OID		mechanism, name_type;
    int		is_local;
    OM_uint32		context_flags;
    int		is_open;
    char 		*userid;
    int		conf_state=0;
    display_file = stdout;

    /*
     * Import the name into target_name.  Use send_tok to save
     * local variable space.
     */
    if (service_name) {
        send_tok.value = service_name;
        send_tok.length = strlen(service_name) + 1;
        maj_stat = gss_import_name(minor_status, 
                                    &send_tok,
                                    (gss_OID) gss_nt_service_name, 
                                    &target_name);
        if (maj_stat != GSS_S_COMPLETE) {
            return maj_stat;
        }
    }
     
     /*
      * Perform the context-establishement loop.
      *
      */
     
    token_ptr = GSS_C_NO_BUFFER;
    gss_context = GSS_C_NO_CONTEXT;

    do {
        maj_stat = gss_init_sec_context(minor_status,
                                        GSS_C_NO_CREDENTIAL,
                                        &gss_context,
                                        target_name,
                                        oid,
                                        GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |	deleg_flag,
                                        0,
                                        NULL,	/* no channel bindings */
                                        token_ptr,
                                        NULL,	/* ignore mech type */
                                        &send_tok,
                                        &ret_flags,
                                        NULL);	/* ignore time_rec */

        if (token_ptr != GSS_C_NO_BUFFER)
            (void) gss_release_buffer(&min_stat, &recv_tok);

        if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
            /*(void) gss_release_name(&min_stat, &target_name);*/
            return maj_stat;
        }

        if (send_tok.length != 0) {
#ifdef DEBUG 
            fprintf(stdout, "sending token...\n");
#endif
            if (send_token(os, &send_tok) < 0) {
                (void) gss_release_buffer(&min_stat, &send_tok);
                (void) gss_release_name(&min_stat, &target_name);
                return maj_stat;
            }
#ifdef DEBUG 
            fprintf(stdout, "token sent (size=%d)\n",send_tok.length);
#endif
        }
        (void) gss_release_buffer(&min_stat, &send_tok);

        if (maj_stat == GSS_S_CONTINUE_NEEDED) {
#ifdef DEBUG 
            fprintf(stdout, "receiving token...\n");
#endif
            if (recv_token(is, &recv_tok) < 0) {
                (void) gss_release_name(&min_stat, &target_name);
                return maj_stat;
            }
            /* if token is void, conversation has been closed by the server */
            token_ptr = &recv_tok;
            if (recv_tok.length > 0) {
#ifdef DEBUG 
                fprintf(stdout, "token received (size=%d)\n",recv_tok.length);
#endif
            } else {
#ifdef DEBUG 
                fprintf(stdout, "void token received\n");
#endif
                minor_status = NULL ;
                return -1 ;
            }
        }
    } while (maj_stat & GSS_S_CONTINUE_NEEDED);

#ifdef DEBUG 
    fprintf(stdout, "COMPLETE\n");
#endif
    (void) gss_release_name(&min_stat, &target_name);

    (void) gss_delete_sec_context(&min_stat, &gss_context, GSS_C_NO_BUFFER);

    return maj_stat;
}




syntax highlighted by Code2HTML, v. 0.9.1