/* Copyright 2009 Justin Erenkrantz and Greg Stein
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "serf.h"
#include "serf_private.h"
#include "auth_kerb.h"

#ifdef SERF_USE_GSSAPI
#include <apr_strings.h>
#include <gssapi/gssapi.h>


/* This module can support all authentication mechanisms as provided by
   the GSS-API implementation, but for now it only supports SPNEGO for
   Negotiate.
   SPNEGO can delegate authentication to Kerberos if supported by the
   host. */

#ifndef GSS_SPNEGO_MECHANISM
static gss_OID_desc spnego_mech_oid = { 6, "\x2b\x06\x01\x05\x05\x02" };
#define GSS_SPNEGO_MECHANISM &spnego_mech_oid
#endif

struct serf__kerb_context_t
{
    /* GSSAPI context */
    gss_ctx_id_t gss_ctx;

    /* Mechanism used to authenticate. */
    gss_OID gss_mech;
};

static void
log_error(int verbose_flag, const char *filename,
          serf__kerb_context_t *ctx,
          OM_uint32 err_maj_stat,
          OM_uint32 err_min_stat,
          const char *msg)
{
    OM_uint32 maj_stat, min_stat;
    gss_buffer_desc stat_buff;
    OM_uint32 msg_ctx = 0;

    if (verbose_flag) {
        maj_stat = gss_display_status(&min_stat,
                                      err_maj_stat,
                                      GSS_C_GSS_CODE,
                                      ctx->gss_mech,
                                      &msg_ctx,
                                      &stat_buff);
        if (maj_stat == GSS_S_COMPLETE ||
            maj_stat == GSS_S_FAILURE) {
            maj_stat = gss_display_status(&min_stat,
                                          err_min_stat,
                                          GSS_C_MECH_CODE,
                                          ctx->gss_mech,
                                          &msg_ctx,
                                          &stat_buff);
        }

        serf__log(verbose_flag, filename,
                  "%s (%x,%d): %s\n", msg,
                  err_maj_stat, err_min_stat, stat_buff.value);
    }
}

/* Cleans the GSS context object, when the pool used to create it gets
   cleared or destroyed. */
static apr_status_t
cleanup_ctx(void *data)
{
    OM_uint32 min_stat;
    serf__kerb_context_t *ctx = data;

    if (ctx->gss_ctx != GSS_C_NO_CONTEXT) {
        if (gss_delete_sec_context(&min_stat, &ctx->gss_ctx,
                                   GSS_C_NO_BUFFER) == GSS_S_FAILURE)
            return APR_EGENERAL;
    }

    return APR_SUCCESS;
}

static apr_status_t
cleanup_sec_buffer(void *data)
{
    OM_uint32 min_stat;
    gss_buffer_desc *gss_buf = data;

    gss_release_buffer(&min_stat, gss_buf);

    return APR_SUCCESS;
}

apr_status_t
serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
                              apr_pool_t *scratch_pool,
                              apr_pool_t *result_pool)
{
    serf__kerb_context_t *ctx;

    ctx = apr_pcalloc(result_pool, sizeof(*ctx));

    ctx->gss_ctx = GSS_C_NO_CONTEXT;
    ctx->gss_mech = GSS_SPNEGO_MECHANISM;

    apr_pool_cleanup_register(result_pool, ctx,
                              cleanup_ctx,
                              apr_pool_cleanup_null);

    *ctx_p = ctx;

    return APR_SUCCESS;
}

apr_status_t
serf__kerb_reset_sec_context(serf__kerb_context_t *ctx)
{
    OM_uint32 dummy_stat;

    if (ctx->gss_ctx)
        (void)gss_delete_sec_context(&dummy_stat, &ctx->gss_ctx,
                                     GSS_C_NO_BUFFER);
    ctx->gss_ctx = GSS_C_NO_CONTEXT;

    return APR_SUCCESS;
}

apr_status_t
serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
                            const char *service,
                            const char *hostname,
                            serf__kerb_buffer_t *input_buf,
                            serf__kerb_buffer_t *output_buf,
                            apr_pool_t *scratch_pool,
                            apr_pool_t *result_pool
                            )
{
    gss_buffer_desc gss_input_buf = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc *gss_output_buf_p;
    OM_uint32 gss_min_stat, gss_maj_stat;
    gss_name_t host_gss_name;
    gss_buffer_desc bufdesc;
    gss_OID dummy; /* unused */

    /* Get the name for the HTTP service at the target host. */
    /* TODO: should be shared between multiple requests. */
    bufdesc.value = apr_pstrcat(scratch_pool, service, "@", hostname, NULL);
    bufdesc.length = strlen(bufdesc.value);
    serf__log(AUTH_VERBOSE, __FILE__, "Get principal for %s\n", bufdesc.value);
    gss_maj_stat = gss_import_name (&gss_min_stat, &bufdesc,
                                    GSS_C_NT_HOSTBASED_SERVICE,
                                    &host_gss_name);
    if(GSS_ERROR(gss_maj_stat)) {
        return APR_EGENERAL;
    }

    /* If the server sent us a token, pass it to gss_init_sec_token for
       validation. */
    gss_input_buf.value = input_buf->value;
    gss_input_buf.length = input_buf->length;

    gss_output_buf_p = apr_pcalloc(result_pool, sizeof(*gss_output_buf_p));

    /* Establish a security context to the server. */
    gss_maj_stat = gss_init_sec_context
        (&gss_min_stat,             /* minor_status */
         GSS_C_NO_CREDENTIAL,       /* XXXXX claimant_cred_handle */
         &ctx->gss_ctx,              /* gssapi context handle */
         host_gss_name,             /* HTTP@server name */
         ctx->gss_mech,             /* mech_type (SPNEGO) */
         GSS_C_MUTUAL_FLAG,         /* ensure the peer authenticates itself */
         0,                         /* default validity period */
         GSS_C_NO_CHANNEL_BINDINGS, /* do not use channel bindings */
         &gss_input_buf,            /* server token, initially empty */
         &dummy,                    /* actual mech type */
         gss_output_buf_p,           /* output_token */
         NULL,                      /* ret_flags */
         NULL                       /* not interested in remaining validity */
         );

    apr_pool_cleanup_register(result_pool, gss_output_buf_p,
                              cleanup_sec_buffer,
                              apr_pool_cleanup_null);

    output_buf->value = gss_output_buf_p->value;
    output_buf->length = gss_output_buf_p->length;

    switch(gss_maj_stat) {
    case GSS_S_COMPLETE:
        return APR_SUCCESS;
    case GSS_S_CONTINUE_NEEDED:
        return APR_EAGAIN;
    default:
        log_error(AUTH_VERBOSE, __FILE__, ctx,
                  gss_maj_stat, gss_min_stat,
                  "Error during Kerberos handshake");
        return APR_EGENERAL;
    }
}

#endif /* SERF_USE_GSSAPI */
