Files correlati : Commento : Aggiornata cUrl alla ultima versione su Github: 7.56.1 git-svn-id: svn://10.65.10.50/branches/R_10_00@24203 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			398 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			398 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/***************************************************************************
 | 
						|
 *                                  _   _ ____  _
 | 
						|
 *  Project                     ___| | | |  _ \| |
 | 
						|
 *                             / __| | | | |_) | |
 | 
						|
 *                            | (__| |_| |  _ <| |___
 | 
						|
 *                             \___|\___/|_| \_\_____|
 | 
						|
 *
 | 
						|
 * Copyright (C) 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
 | 
						|
 *
 | 
						|
 * This software is licensed as described in the file COPYING, which
 | 
						|
 * you should have received as part of this distribution. The terms
 | 
						|
 * are also available at https://curl.haxx.se/docs/copyright.html.
 | 
						|
 *
 | 
						|
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 | 
						|
 * copies of the Software, and permit persons to whom the Software is
 | 
						|
 * furnished to do so, under the terms of the COPYING file.
 | 
						|
 *
 | 
						|
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 | 
						|
 * KIND, either express or implied.
 | 
						|
 *
 | 
						|
 ***************************************************************************/
 | 
						|
 | 
						|
/* Only provides the bare minimum to link with libcurl */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include "stub_gssapi.h"
 | 
						|
 | 
						|
#define MAX_CREDS_LENGTH 250
 | 
						|
#define APPROX_TOKEN_LEN 250
 | 
						|
 | 
						|
enum min_err_code {
 | 
						|
    GSS_OK = 0,
 | 
						|
    GSS_NO_MEMORY,
 | 
						|
    GSS_INVALID_ARGS,
 | 
						|
    GSS_INVALID_CREDS,
 | 
						|
    GSS_INVALID_CTX,
 | 
						|
    GSS_SERVER_ERR,
 | 
						|
    GSS_NO_MECH,
 | 
						|
    GSS_LAST
 | 
						|
};
 | 
						|
 | 
						|
const char *min_err_table[] = {
 | 
						|
    "stub-gss: no error",
 | 
						|
    "stub-gss: no memory",
 | 
						|
    "stub-gss: invalid arguments",
 | 
						|
    "stub-gss: invalid credentials",
 | 
						|
    "stub-gss: invalid context",
 | 
						|
    "stub-gss: server returned error",
 | 
						|
    "stub-gss: cannot find a mechanism",
 | 
						|
    NULL
 | 
						|
};
 | 
						|
 | 
						|
struct gss_ctx_id_t_desc_struct {
 | 
						|
  enum { NONE, KRB5, NTLM1, NTLM3 } sent;
 | 
						|
  int have_krb5;
 | 
						|
  int have_ntlm;
 | 
						|
  OM_uint32 flags;
 | 
						|
  char creds[MAX_CREDS_LENGTH];
 | 
						|
};
 | 
						|
 | 
						|
OM_uint32 gss_init_sec_context(OM_uint32 *min,
 | 
						|
            gss_const_cred_id_t initiator_cred_handle,
 | 
						|
            gss_ctx_id_t *context_handle,
 | 
						|
            gss_const_name_t target_name,
 | 
						|
            const gss_OID mech_type,
 | 
						|
            OM_uint32 req_flags,
 | 
						|
            OM_uint32 time_req,
 | 
						|
            const gss_channel_bindings_t input_chan_bindings,
 | 
						|
            const gss_buffer_t input_token,
 | 
						|
            gss_OID *actual_mech_type,
 | 
						|
            gss_buffer_t output_token,
 | 
						|
            OM_uint32 *ret_flags,
 | 
						|
            OM_uint32 *time_rec)
 | 
						|
{
 | 
						|
  /* The token will be encoded in base64 */
 | 
						|
  int length = APPROX_TOKEN_LEN * 3 / 4;
 | 
						|
  int used = 0;
 | 
						|
  char *token = NULL;
 | 
						|
  const char *creds = NULL;
 | 
						|
  gss_ctx_id_t ctx = NULL;
 | 
						|
 | 
						|
  if(!min)
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
 | 
						|
  *min = 0;
 | 
						|
 | 
						|
  if(!context_handle || !target_name || !output_token) {
 | 
						|
    *min = GSS_INVALID_ARGS;
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  creds = getenv("CURL_STUB_GSS_CREDS");
 | 
						|
  if(!creds || strlen(creds) >= MAX_CREDS_LENGTH) {
 | 
						|
    *min = GSS_INVALID_CREDS;
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  ctx = *context_handle;
 | 
						|
  if(ctx && strcmp(ctx->creds, creds)) {
 | 
						|
    *min = GSS_INVALID_CREDS;
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  output_token->length = 0;
 | 
						|
  output_token->value = NULL;
 | 
						|
 | 
						|
  if(input_token && input_token->length) {
 | 
						|
    if(!ctx) {
 | 
						|
      *min = GSS_INVALID_CTX;
 | 
						|
      return GSS_S_FAILURE;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Server response, either D (RA==) or C (Qw==) */
 | 
						|
    if(((char *) input_token->value)[0] == 'D') {
 | 
						|
      /* Done */
 | 
						|
      switch(ctx->sent) {
 | 
						|
      case KRB5:
 | 
						|
      case NTLM3:
 | 
						|
        if(ret_flags)
 | 
						|
          *ret_flags = ctx->flags;
 | 
						|
        if(time_rec)
 | 
						|
          *time_rec = GSS_C_INDEFINITE;
 | 
						|
        return GSS_S_COMPLETE;
 | 
						|
      default:
 | 
						|
        *min = GSS_SERVER_ERR;
 | 
						|
        return GSS_S_FAILURE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if(((char *) input_token->value)[0] != 'C') {
 | 
						|
      /* We only support Done or Continue */
 | 
						|
      *min = GSS_SERVER_ERR;
 | 
						|
      return GSS_S_FAILURE;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Continue */
 | 
						|
    switch(ctx->sent) {
 | 
						|
    case KRB5:
 | 
						|
      /* We sent KRB5 and it failed, let's try NTLM */
 | 
						|
      if(ctx->have_ntlm) {
 | 
						|
        ctx->sent = NTLM1;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        *min = GSS_SERVER_ERR;
 | 
						|
        return GSS_S_FAILURE;
 | 
						|
      }
 | 
						|
    case NTLM1:
 | 
						|
      ctx->sent = NTLM3;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      *min = GSS_SERVER_ERR;
 | 
						|
      return GSS_S_FAILURE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    if(ctx) {
 | 
						|
      *min = GSS_INVALID_CTX;
 | 
						|
      return GSS_S_FAILURE;
 | 
						|
    }
 | 
						|
 | 
						|
    ctx = (gss_ctx_id_t) calloc(sizeof(*ctx), 1);
 | 
						|
    if(!ctx) {
 | 
						|
      *min = GSS_NO_MEMORY;
 | 
						|
      return GSS_S_FAILURE;
 | 
						|
    }
 | 
						|
 | 
						|
    if(strstr(creds, "KRB5"))
 | 
						|
      ctx->have_krb5 = 1;
 | 
						|
 | 
						|
    if(strstr(creds, "NTLM"))
 | 
						|
      ctx->have_ntlm = 1;
 | 
						|
 | 
						|
    if(ctx->have_krb5)
 | 
						|
      ctx->sent = KRB5;
 | 
						|
    else if(ctx->have_ntlm)
 | 
						|
      ctx->sent = NTLM1;
 | 
						|
    else {
 | 
						|
      free(ctx);
 | 
						|
      *min = GSS_NO_MECH;
 | 
						|
      return GSS_S_FAILURE;
 | 
						|
    }
 | 
						|
 | 
						|
    strcpy(ctx->creds, creds);
 | 
						|
    ctx->flags = req_flags;
 | 
						|
  }
 | 
						|
 | 
						|
  token = malloc(length);
 | 
						|
  if(!token) {
 | 
						|
    free(ctx);
 | 
						|
    *min = GSS_NO_MEMORY;
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Token format: creds:target:type:padding */
 | 
						|
  used = snprintf(token, length, "%s:%s:%d:", creds,
 | 
						|
                  (char *) target_name, ctx->sent);
 | 
						|
 | 
						|
  if(used >= length) {
 | 
						|
    free(token);
 | 
						|
    free(ctx);
 | 
						|
    *min = GSS_NO_MEMORY;
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Overwrite null terminator */
 | 
						|
  memset(token + used, 'A', length - used);
 | 
						|
 | 
						|
  *context_handle = ctx;
 | 
						|
 | 
						|
  output_token->value = token;
 | 
						|
  output_token->length = length;
 | 
						|
 | 
						|
  return GSS_S_CONTINUE_NEEDED;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_delete_sec_context(OM_uint32 *min,
 | 
						|
                                 gss_ctx_id_t *context_handle,
 | 
						|
                                 gss_buffer_t output_token)
 | 
						|
{
 | 
						|
  if(!min)
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
 | 
						|
  if(!context_handle) {
 | 
						|
    *min = GSS_INVALID_CTX;
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  free(*context_handle);
 | 
						|
  *context_handle = NULL;
 | 
						|
  *min = 0;
 | 
						|
 | 
						|
  return GSS_S_COMPLETE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_release_buffer(OM_uint32 *min,
 | 
						|
                             gss_buffer_t buffer)
 | 
						|
{
 | 
						|
  if(min)
 | 
						|
    *min = 0;
 | 
						|
 | 
						|
  if(buffer && buffer->length) {
 | 
						|
    free(buffer->value);
 | 
						|
    buffer->length = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return GSS_S_COMPLETE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_import_name(OM_uint32 *min,
 | 
						|
                          const gss_buffer_t input_name_buffer,
 | 
						|
                          const gss_OID input_name_type,
 | 
						|
                          gss_name_t *output_name)
 | 
						|
{
 | 
						|
  char *name = NULL;
 | 
						|
 | 
						|
  if(!min)
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
 | 
						|
  if(!input_name_buffer || !output_name) {
 | 
						|
    *min = GSS_INVALID_ARGS;
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  name = strndup(input_name_buffer->value, input_name_buffer->length);
 | 
						|
  if(!name) {
 | 
						|
    *min = GSS_NO_MEMORY;
 | 
						|
    return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  *output_name = (gss_name_t) name;
 | 
						|
  *min = 0;
 | 
						|
 | 
						|
  return GSS_S_COMPLETE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_release_name(OM_uint32 *min,
 | 
						|
                           gss_name_t *input_name)
 | 
						|
{
 | 
						|
  if(min)
 | 
						|
    *min = 0;
 | 
						|
 | 
						|
  if(input_name)
 | 
						|
    free(*input_name);
 | 
						|
 | 
						|
  return GSS_S_COMPLETE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_display_status(OM_uint32 *min,
 | 
						|
                             OM_uint32 status_value,
 | 
						|
                             int status_type,
 | 
						|
                             const gss_OID mech_type,
 | 
						|
                             OM_uint32 *message_context,
 | 
						|
                             gss_buffer_t status_string)
 | 
						|
{
 | 
						|
  const char maj_str[] = "Stub GSS error";
 | 
						|
  if(min)
 | 
						|
    *min = 0;
 | 
						|
 | 
						|
  if(message_context)
 | 
						|
    *message_context = 0;
 | 
						|
 | 
						|
  if(status_string) {
 | 
						|
    status_string->value = NULL;
 | 
						|
    status_string->length = 0;
 | 
						|
 | 
						|
    if(status_value >= GSS_LAST)
 | 
						|
      return GSS_S_FAILURE;
 | 
						|
 | 
						|
    switch(status_type) {
 | 
						|
      case GSS_C_GSS_CODE:
 | 
						|
        status_string->value = strdup(maj_str);
 | 
						|
        break;
 | 
						|
      case GSS_C_MECH_CODE:
 | 
						|
        status_string->value = strdup(min_err_table[status_value]);
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        return GSS_S_FAILURE;
 | 
						|
    }
 | 
						|
 | 
						|
    if(status_string->value)
 | 
						|
      status_string->length = strlen(status_string->value);
 | 
						|
    else
 | 
						|
       return GSS_S_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  return GSS_S_COMPLETE;
 | 
						|
}
 | 
						|
 | 
						|
/* Stubs returning error */
 | 
						|
 | 
						|
OM_uint32 gss_display_name(OM_uint32 *min,
 | 
						|
                           gss_const_name_t input_name,
 | 
						|
                           gss_buffer_t output_name_buffer,
 | 
						|
                           gss_OID *output_name_type)
 | 
						|
{
 | 
						|
  return GSS_S_FAILURE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_inquire_context(OM_uint32 *min,
 | 
						|
                              gss_const_ctx_id_t context_handle,
 | 
						|
                              gss_name_t *src_name,
 | 
						|
                              gss_name_t *targ_name,
 | 
						|
                              OM_uint32 *lifetime_rec,
 | 
						|
                              gss_OID *mech_type,
 | 
						|
                              OM_uint32 *ctx_flags,
 | 
						|
                              int *locally_initiated,
 | 
						|
                              int *open_context)
 | 
						|
{
 | 
						|
  return GSS_S_FAILURE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_wrap(OM_uint32 *min,
 | 
						|
                   gss_const_ctx_id_t context_handle,
 | 
						|
                   int conf_req_flag,
 | 
						|
                   gss_qop_t qop_req,
 | 
						|
                   const gss_buffer_t input_message_buffer,
 | 
						|
                   int *conf_state,
 | 
						|
                   gss_buffer_t output_message_buffer)
 | 
						|
{
 | 
						|
  return GSS_S_FAILURE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_unwrap(OM_uint32 *min,
 | 
						|
                     gss_const_ctx_id_t context_handle,
 | 
						|
                     const gss_buffer_t input_message_buffer,
 | 
						|
                     gss_buffer_t output_message_buffer,
 | 
						|
                     int *conf_state,
 | 
						|
                     gss_qop_t *qop_state)
 | 
						|
{
 | 
						|
  return GSS_S_FAILURE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_seal(OM_uint32 *min,
 | 
						|
                   gss_ctx_id_t context_handle,
 | 
						|
                   int conf_req_flag,
 | 
						|
                   int qop_req,
 | 
						|
                   gss_buffer_t input_message_buffer,
 | 
						|
                   int *conf_state,
 | 
						|
                   gss_buffer_t output_message_buffer)
 | 
						|
{
 | 
						|
  return GSS_S_FAILURE;
 | 
						|
}
 | 
						|
 | 
						|
OM_uint32 gss_unseal(OM_uint32 *min,
 | 
						|
                     gss_ctx_id_t context_handle,
 | 
						|
                     gss_buffer_t input_message_buffer,
 | 
						|
                     gss_buffer_t output_message_buffer,
 | 
						|
                     int *conf_state,
 | 
						|
                     int *qop_state)
 | 
						|
{
 | 
						|
  return GSS_S_FAILURE;
 | 
						|
}
 | 
						|
 |