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

/*#ifdef HAVE_UNISTD_H*/
#include <unistd.h>
/*#endif*/
#include <syslog.h>
#include <errno.h>

#include "gfw-misc.h"
#include "gfw.h"

#ifndef gss_nt_service_name
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#endif

/*#ifdef USE_STRING_H*/
#include <string.h>
/*#else
#include <strings.h>
#endif*/


/*
 * Function: gfw_accept_sec_context
 *
 * Purpose: accept a context initiated by a client
 *
 * Arguments:
 *
 *  minor_status    (w) the second status
 * 	is              (r) the input stream socket
 * 	os              (r) the output stream socket
 *  server_creds    (r) the credential for the context to be accepted
 * 	client_name     (w) the name (certificate subject) of the client who wants to
 *                      establish a context
 *
 * Returns: major status
 *
 * Effects:
 * 
 * gfw_accept_sec_context establishes a GSS-API context required by a client 
 * over the connection designated by the two sockets. 
 */
OM_uint32 gfw_accept_sec_context(
OM_uint32 *         minor_status,
int                 is, 
int                 os, 
gss_cred_id_t       server_creds, 
gss_buffer_t        client_name)
{
    gss_buffer_desc send_tok, recv_tok;
    gss_name_t client;
    gss_OID doid;
    OM_uint32 maj_stat, min_stat;
    gss_buffer_desc	oid_name;
    gss_ctx_id_t   context;
     
    context = GSS_C_NO_CONTEXT;
     
    do {
#ifdef DEBUG 
        fprintf(display_file, "receiving token...\n");
#endif
        if (recv_token(is, &recv_tok) < 0)
            return -1;

#ifdef DEBUG 
        fprintf(display_file, "Received token (size=%d): \n", recv_tok.length);
#endif

        maj_stat = gss_accept_sec_context(minor_status,
                                            &context,
                                            server_creds,
                                            &recv_tok,
                                            GSS_C_NO_CHANNEL_BINDINGS,
                                            &client,
                                            &doid,
                                            &send_tok,
                                            NULL,
                                            NULL, 	/* ignore time_rec */
                                            NULL); 	/* ignore del_cred_handle */

        if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
            display_status("accepting context", maj_stat, *minor_status);
            (void) gss_release_buffer(&min_stat, &recv_tok);
            /* send a void token to close conversation */
            (void) gss_release_buffer(&min_stat, &send_tok);
            if (send_token(os, &send_tok) < 0) {
                fprintf(display_file, "failure sending token\n");
                return -1;
            }
            return maj_stat;
        }

        (void) gss_release_buffer(&min_stat, &recv_tok);

        if (send_tok.length != 0) {
#ifdef DEBUG 
            fprintf(display_file, "Sending accept_sec_context token (size=%d):\n", send_tok.length);
#endif
            if (send_token(os, &send_tok) < 0) {
                fprintf(display_file, "failure sending token\n");
                return -1;
            }
#ifdef DEBUG 
            fprintf(display_file, "token sent\n");
#endif

            (void) gss_release_buffer(&min_stat, &send_tok);
        }

    } while (maj_stat & GSS_S_CONTINUE_NEEDED);
#ifdef DEBUG 
    fprintf(display_file, "COMPLETE\n");
#endif

    maj_stat = gss_display_name(minor_status, client, client_name, &doid);
    if (maj_stat != GSS_S_COMPLETE) {
/*        *minor_status = min_stat;*/
        display_status("displaying name", maj_stat, *minor_status);
        return maj_stat;
    }
    (void) gss_release_name(&min_stat, &client);

     /* Delete context */
    (void) gss_delete_sec_context(&min_stat, &context, NULL);

    return maj_stat;

}




syntax highlighted by Code2HTML, v. 0.9.1