[2903] in Kerberos

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

memory leaks

daemon@ATHENA.MIT.EDU (Glenn NoI Machin)
Fri Nov 19 16:57:54 1993

Date: Fri, 19 Nov 1993 14:28:13 -0700
From: Glenn NoI Machin <gmachin@somnet.sandia.gov>
To: krb5_bugs@MIT.EDU
Cc: kerberos@MIT.EDU



The folllowing memory leak was found in the pre-beta3 release
of krb5.


---------------------------------------------------------------------
File: lib/keytab/file/ktf_util.c  routine: krb5_ktfileint_internal_read_entry

The problem had to do with not freeing ret_entry, when problems occurred. I
have provided the "fixed" code. The changes were extensive enough that just
marking the changes would take to long.....

krb5_error_code
krb5_ktfileint_internal_read_entry(id, entrypp, delete_point)
krb5_keytab id;
krb5_keytab_entry **entrypp;
krb5_int32 *delete_point;
{
    register krb5_keytab_entry *ret_entry;
    krb5_int16 count;
    krb5_int16 princ_size;
    register int i;
    krb5_int32 size;
    krb5_int32 start_pos;
    krb5_error_code error;
    char	*tmpdata;
    krb5_data	*princ;

    if (!(ret_entry = (krb5_keytab_entry *)calloc(1, sizeof(*ret_entry))))
	return ENOMEM;

    /* fseek to synchronise buffered I/O on the key table. */

    if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0)
    {
	error = errno;
	goto freeout;
    }

    do {
        *delete_point = ftell(KTFILEP(id));
        if (!xfread(&size, sizeof(size), 1, KTFILEP(id))) {
            error = KRB5_KT_END;
            goto freeout;
        }
	if (KTVERSION(id) != KRB5_KT_VNO_1)
		size = ntohl(size);

        if (size < 0) {
            if (fseek(KTFILEP(id), -size, SEEK_CUR)) {
		error = errno;
        	goto freeout;
            }
        }
    } while (size < 0);

    if (size == 0) {
        error = KRB5_KT_END;
        goto freeout;
    }

    start_pos = ftell(KTFILEP(id));

    /* deal with guts of parsing... */

    /* first, int16 with #princ components */
    if (!xfread(&count, sizeof(count), 1, KTFILEP(id))){
        error = KRB5_KT_END;
        goto freeout;
    }
    if (KTVERSION(id) == KRB5_KT_VNO_1) {
	    count -= 1;		/* V1 includes the realm in the count */
    } else {
	    count = ntohs(count);
    }
    if (!count || (count < 0)){
        error = KRB5_KT_END;
        goto freeout;
    }
    ret_entry->principal = (krb5_principal)malloc(sizeof(krb5_principal_data));
    if (!ret_entry->principal){
        error = ENOMEM;
        goto freeout;
    }
    
    ret_entry->principal->length = count;
    ret_entry->principal->data = (krb5_data *)calloc(count, sizeof(krb5_data));
    if (!ret_entry->principal->data) {
	free(ret_entry->principal);    
        error = ENOMEM;
        goto freeout;
    }

    /* Now, get the realm data */
    if (!xfread(&princ_size, sizeof(princ_size), 1, KTFILEP(id))) {
	    error = KRB5_KT_END;
	    goto fail;
    }
    if (KTVERSION(id) != KRB5_KT_VNO_1)
	    princ_size = ntohs(princ_size);
    if (!princ_size || (princ_size < 0)) {
	    error = KRB5_KT_END;
	    goto fail;
    }
    krb5_princ_set_realm_length(ret_entry->principal, princ_size);
    tmpdata = malloc(princ_size+1);
    if (!tmpdata) {
	    error = ENOMEM;
	    goto fail;
    }
    if (fread(tmpdata, 1, princ_size, KTFILEP(id)) != princ_size) {
	    free(tmpdata);
	    error = KRB5_KT_END;
	    goto fail;
    }
    tmpdata[princ_size] = 0;	/* Some things might be expecting null */
				/* termination...  ``Be conservative in */
				/* what you send out'' */
    krb5_princ_set_realm_data(ret_entry->principal, tmpdata);
    
    for (i = 0; i < count; i++) {
	princ = krb5_princ_component(ret_entry->principal, i);
	if (!xfread(&princ_size, sizeof(princ_size), 1, KTFILEP(id))) {
	    error = KRB5_KT_END;
	    goto fail;
        }
	if (KTVERSION(id) != KRB5_KT_VNO_1)
	    princ_size = ntohs(princ_size);
	if (!princ_size || (princ_size < 0)) {
	    error = KRB5_KT_END;
	    goto fail;
        }

	princ->length = princ_size;
	princ->data = malloc(princ_size+1);
	if (!princ->data) {
	    error = ENOMEM;
	    goto fail;
        }
	if (!xfread(princ->data, sizeof(char), princ_size, KTFILEP(id))) {
	    error = KRB5_KT_END;
	    goto fail;
        }
	princ->data[princ_size] = 0; /* Null terminate */
    }

    /* read in the principal type, if we can get it */
    if (KTVERSION(id) != KRB5_KT_VNO_1) {
	    if (!xfread(&ret_entry->principal->type,
			sizeof(ret_entry->principal->type), 1, KTFILEP(id))) {
		    error = KRB5_KT_END;
		    goto fail;
	    }
	    ret_entry->principal->type = ntohl(ret_entry->principal->type);
    }
    
    /* read in the timestamp */
    if (!xfread(&ret_entry->timestamp, sizeof(ret_entry->timestamp), 1, KTFILEP(id))) {
	error = KRB5_KT_END;
	goto fail;
    }
    if (KTVERSION(id) != KRB5_KT_VNO_1)
	ret_entry->timestamp = ntohl(ret_entry->timestamp);
    
    /* read in the version number */
    if (!xfread(&ret_entry->vno, sizeof(ret_entry->vno), 1, KTFILEP(id))) {
	error = KRB5_KT_END;
	goto fail;
    }
    
    /* key type */
    if (!xfread(&ret_entry->key.keytype, sizeof(ret_entry->key.keytype), 1,
		KTFILEP(id))) {
	error = KRB5_KT_END;
	goto fail;
    }
    if (KTVERSION(id) != KRB5_KT_VNO_1)
	ret_entry->key.keytype = ntohs(ret_entry->key.keytype);
    
    /* key contents */
    if (!xfread(&count, sizeof(count), 1, KTFILEP(id))) {
	error = KRB5_KT_END;
	goto fail;
    }
    if (KTVERSION(id) != KRB5_KT_VNO_1)
	count = ntohs(count);
    if (!count || (count < 0)) {
	error = KRB5_KT_END;
	goto fail;
    }
    ret_entry->key.length = count;
    
    ret_entry->key.contents = (krb5_octet *)malloc(count);
    if (!ret_entry->key.contents) {
	error = ENOMEM;
	goto fail;
    }		
    if (!xfread(ret_entry->key.contents, sizeof(krb5_octet), count,
		KTFILEP(id))) {
	error = KRB5_KT_END;
	goto fail;
    }

    *entrypp = ret_entry;

    /*
     * Reposition file pointer to the next inter-record length field.
     */
    fseek(KTFILEP(id), start_pos + size, SEEK_SET);
    return 0;
fail:
    
    for (i = 0; i < ret_entry->principal->length; i++) {
	    princ = krb5_princ_component(ret_entry->principal, i);
	    if (princ->data)
		    free(princ->data);
    }
    free(ret_entry->principal->data);
    free(ret_entry->principal);
freeout:
    free(ret_entry);
    return error;
}

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