[31402] in Kerberos

home help back first fref pref prev next nref lref last post

Memory leak or programing error

daemon@ATHENA.MIT.EDU (Markus Moeller)
Mon Aug 24 11:14:38 2009

Message-ID: <375B84AD6FFC48A2A53BF6AAAB01ECB7@VAIOLaptop>
From: "Markus Moeller" <huaraz@moeller.plus.com>
To: <kerberos@mit.edu>
Date: Sun, 23 Aug 2009 22:41:55 +0100
MIME-Version: 1.0
Content-Type: multipart/mixed;
	boundary="----=_NextPart_000_0C7F_01CA2442.EA775110"
Errors-To: kerberos-bounces@mit.edu

This is a multi-part message in MIME format.

------=_NextPart_000_0C7F_01CA2442.EA775110
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

I am working on an application to do gssapi authentication and noticed
increased memory usage. I created the following test application:

/*
 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>


#ifndef HEIMDAL
#define HEIMDAL 0
#endif
#if HEIMDAL
#define HAVE_HEIMDAL_KERBEROS 1
#define HAVE_GSSAPI_GSSAPI_H 1
#else
#define HAVE_MIT_KERBEROS 1
#define HAVE_GSSAPI_GSSAPI_GENERIC_H 1
#define HAVE_GSSAPI_GSSAPI_H 1
#define HAVE_GSSAPI_GSSAPI_KRB5_H 1
#endif

#ifdef HAVE_HEIMDAL_KERBEROS
#ifdef HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
#elif defined(HAVE_GSSAPI_H)
#include <gssapi.h>
#else
#error "GSSAPI header required"
#endif
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#else
#ifdef HAVE_SEAM_KERBEROS
#ifdef HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
#elif defined(HAVE_GSSAPI_H)
#include <gssapi.h>
#else
#error "GSSAPI header required"
#endif
#ifdef HAVE_GSSAPI_GSSAPI_EXT_H
#include <gssapi/gssapi_ext.h>
#endif
#define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE
#else /*MIT*/
#ifdef HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
#elif defined(HAVE_GSSAPI_H)
#include <gssapi.h>
#else
#error "GSSAPI header required"
#endif
#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
#include <gssapi/gssapi_krb5.h>
#endif
#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
#include <gssapi/gssapi_generic.h>
#endif
#endif
#endif

#include "base64.h"

#ifndef MAX_AUTHTOKEN_LEN
#define MAX_AUTHTOKEN_LEN   65535
#endif

static const unsigned char ntlmProtocol [] =3D {'N', 'T', 'L', 'M', 'S', =
'S',
'P', 0};

int main(int argc, char * const argv[])
{
  char buf[MAX_AUTHTOKEN_LEN];
  char *c;
  int length=3D0;
  static int err=3D0;
  OM_uint32 ret_flags=3D0;
  char *service_name=3D(char *)"HTTP";
  char *host_name=3D(char *)"opensuse11.suse.home";
  char *token =3D NULL;
  OM_uint32 major_status, minor_status;
  gss_ctx_id_t          gss_context =3D GSS_C_NO_CONTEXT;
  gss_name_t            client_name =3D GSS_C_NO_NAME;
  gss_name_t            server_name =3D GSS_C_NO_NAME;
  gss_cred_id_t         server_creds =3D GSS_C_NO_CREDENTIAL;
  gss_buffer_desc       service =3D GSS_C_EMPTY_BUFFER;
  gss_buffer_desc       input_token =3D GSS_C_EMPTY_BUFFER;
  gss_buffer_desc       output_token =3D GSS_C_EMPTY_BUFFER;

  setbuf(stdout,NULL);
  setbuf(stdin,NULL);

  if ( !host_name ) {
      fprintf(stderr, "Local hostname could not be determined. Please
specify the service principal\n");
      exit(-1);
    }
  service.value =3D malloc(strlen(service_name)+strlen(host_name)+2);
  =
snprintf(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",s=
ervice_name,host_name);
  service.length =3D strlen((char *)service.value);
  fprintf(stderr, "Use service %.*s \n",service.length,service.value);

  while (1) {
    if (fgets(buf, sizeof(buf)-1, stdin) =3D=3D NULL) {
      if (ferror(stdin)) {
        fprintf(stderr, "fgets() failed! dying..... errno=3D%d (%s)\n",
ferror(stdin), strerror(ferror(stdin)));
        exit(1);    /* BIIG buffer */
      }
      exit(0);
    }

    c=3Dmemchr(buf,'\n',sizeof(buf)-1);
    if (c) {
      *c =3D '\0';
      length =3D c-buf;
    } else {
      err =3D 1;
    }
    if (err) {
      fprintf(stderr, "Oversized message\n");
      err =3D 0;
      continue;
    }

    if (buf[0] =3D=3D '\0') {
      fprintf(stderr, "Invalid request\n");
      continue;
    }

    if (!strncmp(buf,"QQ",2)){
      gss_release_buffer(&minor_status, &input_token);
      gss_release_buffer(&minor_status, &output_token);
      gss_delete_sec_context(&minor_status, &gss_context, =
&output_token);
      gss_release_buffer(&minor_status, &output_token);
      gss_context =3D GSS_C_NO_CONTEXT;
      gss_release_cred(&minor_status, &server_creds);
      if (server_name)
        gss_release_name(&minor_status, &server_name);
      if (client_name)
        gss_release_name(&minor_status, &client_name);
      if (token) {
        free(token);
        token=3DNULL;
      }
      fprintf(stderr, "Quit\n");
      exit (1);
    }

    input_token.length =3D base64_decode_len(buf);
    input_token.value =3D malloc(input_token.length);

    base64_decode(input_token.value,buf,input_token.length);


    if ((input_token.length >=3D sizeof ntlmProtocol + 1) &&
        (!memcmp (input_token.value, ntlmProtocol, sizeof =
ntlmProtocol))) {
      fprintf(stderr, "received type %d NTLM token\n", (int) *((unsigned
char *)input_token.value + sizeof ntlmProtocol));
      goto cleanup;
    }

    major_status =3D gss_import_name(&minor_status, &service,
                                     gss_nt_service_name, &server_name);

    if (GSS_ERROR(major_status)) {
      fprintf(stderr, "gss_import_name error\n");
      goto cleanup;
    }

    major_status =3D gss_acquire_cred(&minor_status, server_name,
GSS_C_INDEFINITE,
                                    GSS_C_NO_OID_SET, GSS_C_ACCEPT,
&server_creds,
                                    NULL, NULL);
    if (GSS_ERROR(major_status)) {
      fprintf(stderr, "gss_acquire_cred error\n");
      goto cleanup;
    }

    major_status =3D gss_accept_sec_context(&minor_status,
                                          &gss_context,
                                          server_creds,
                                          &input_token,
                                          GSS_C_NO_CHANNEL_BINDINGS,
                                          &client_name,
                                          NULL,
                                          &output_token,
                                          &ret_flags,
                                          NULL,
                                          NULL);


    if (output_token.length) {
      token =3D malloc(base64_encode_len(output_token.length));
      if (token =3D=3D NULL) {
        fprintf(stderr, "Not enough memory\n");
        goto cleanup;
      }

      base64_encode(token,(const char
*)output_token.value,base64_encode_len(output_token.length),output_token.=
length);

      if (GSS_ERROR(major_status)) {
        fprintf(stderr, "gss_accept_sec_context error\n");
        goto cleanup;
      }
      if (major_status & GSS_S_CONTINUE_NEEDED) {
        fprintf(stderr, "continuation needed\n");
        goto cleanup;
      }
      gss_release_buffer(&minor_status, &output_token);
      major_status =3D gss_display_name(&minor_status, client_name,
&output_token, NULL);

      if (GSS_ERROR(major_status)) {
        fprintf(stderr, "gss_display_name error\n");
        goto cleanup;
      }
      fprintf(stderr, "User %s authenticated\n", (char
*)output_token.value);
      goto cleanup;
    } else {
      if (GSS_ERROR(major_status)) {
        fprintf(stderr, "gss_accept_sec_context error\n");
        goto cleanup;
      }
      if (major_status & GSS_S_CONTINUE_NEEDED) {
        fprintf(stderr, "continuation needed\n");
        goto cleanup;
      }
      gss_release_buffer(&minor_status, &output_token);
      major_status =3D gss_display_name(&minor_status, client_name,
&output_token, NULL);

      if (GSS_ERROR(major_status)) {
        fprintf(stderr, "gss_display_name error\n");
        goto cleanup;
      }
      fprintf(stderr, "User %s authenticated\n", (char
*)output_token.value);
    }
cleanup:
    gss_release_buffer(&minor_status, &input_token);
    gss_release_buffer(&minor_status, &output_token);
    gss_delete_sec_context(&minor_status, &gss_context, &output_token);
    gss_release_buffer(&minor_status, &output_token);
    gss_context =3D GSS_C_NO_CONTEXT;
    gss_release_cred(&minor_status, &server_creds);
    if (server_name)
      gss_release_name(&minor_status, &server_name);
    if (client_name)
      gss_release_name(&minor_status, &client_name);
    if (token) {
      free(token);
      token=3DNULL;
    }
    continue;
  }
}

It works fine with MIT 1.6.3 for successful authentications, but when I =
get=20
errors in gss_accept_sec_context I get memory leaks when using spnego =
tokens=20
as input.

Find attached my valgrind output for 20 runs. In the failure case it =
means=20
the first is successful and the others are replays.

I also see problems when I don't use a replay cache by using even with =
no gss_accept_sec_context failure.=20

export KRB5RCACHETYPE=3Dnone


Thank you
Markus


------=_NextPart_000_0C7F_01CA2442.EA775110
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

________________________________________________
Kerberos mailing list           Kerberos@mit.edu
https://mailman.mit.edu/mailman/listinfo/kerberos

------=_NextPart_000_0C7F_01CA2442.EA775110--



home help back first fref pref prev next nref lref last post