[31402] in Kerberos
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--