Example #1
0
static krb5_error_code copy_one_entry(krb5_context context, 
				      krb5_keytab src_keytab, krb5_keytab dst_keytab, krb5_keytab_entry entry) 
{
    krb5_error_code ret;
    krb5_keytab_entry dummy;

    char *name_str;
    char *etype_str;
    ret = krb5_unparse_name (context, entry.principal, &name_str);
    if(ret) {
	krb5_set_error_message(context, ret, "krb5_unparse_name");
	name_str = NULL; /* XXX */
	return ret;
    }
    ret = krb5_enctype_to_string(context, entry.keyblock.keytype, &etype_str);
    if(ret) {
	krb5_set_error_message(context, ret, "krb5_enctype_to_string");
	etype_str = NULL; /* XXX */
	return ret;
    }
    ret = krb5_kt_get_entry(context, dst_keytab,
			    entry.principal,
			    entry.vno,
			    entry.keyblock.keytype,
			    &dummy);
    if(ret == 0) {
	/* this entry is already in the new keytab, so no need to
	   copy it; if the keyblocks are not the same, something
	   is weird, so complain about that */
	if(!compare_keyblock(&entry.keyblock, &dummy.keyblock)) {
		krb5_warn(context, 0, "entry with different keyvalue "
			  "already exists for %s, keytype %s, kvno %d",
			  name_str, etype_str, entry.vno);
	}
	krb5_kt_free_entry(context, &dummy);
	krb5_kt_free_entry (context, &entry);
	free(name_str);
	free(etype_str);
	return ret;
    } else if(ret != KRB5_KT_NOTFOUND) {
	krb5_set_error_message (context, ret, "fetching %s/%s/%u",
				name_str, etype_str, entry.vno);
	krb5_kt_free_entry (context, &entry);
	free(name_str);
	free(etype_str);
	return ret;
    } 
    ret = krb5_kt_add_entry (context, dst_keytab, &entry);
    krb5_kt_free_entry (context, &entry);
    if (ret) {
	krb5_set_error_message (context, ret, "adding %s/%s/%u",
				name_str, etype_str, entry.vno);
	free(name_str);
	free(etype_str);
	return ret;
    }
    free(name_str);
    free(etype_str);
    return ret;
}
Example #2
0
static OM_uint32 acquire_acceptor_cred
		  (OM_uint32 * minor_status,
		   krb5_context context,
		   const gss_name_t desired_name,
		   OM_uint32 time_req,
		   const gss_OID_set desired_mechs,
		   gss_cred_usage_t cred_usage,
		   gsskrb5_cred handle,
		   gss_OID_set * actual_mechs,
		   OM_uint32 * time_rec
		  )
{
    OM_uint32 ret;
    krb5_error_code kret;

    ret = GSS_S_FAILURE;
    kret = get_keytab(context, &handle->keytab);
    if (kret)
	goto end;

    /* check that the requested principal exists in the keytab */
    if (handle->principal) {
	krb5_keytab_entry entry;

	kret = krb5_kt_get_entry(context, handle->keytab,
				 handle->principal, 0, 0, &entry);
	if (kret)
	    goto end;
	krb5_kt_free_entry(context, &entry);
	ret = GSS_S_COMPLETE;
    } else {
	/*
	 * Check if there is at least one entry in the keytab before
	 * declaring it as an useful keytab.
	 */
	krb5_keytab_entry tmp;
	krb5_kt_cursor c;

	kret = krb5_kt_start_seq_get (context, handle->keytab, &c);
	if (kret)
	    goto end;
	if (krb5_kt_next_entry(context, handle->keytab, &tmp, &c) == 0) {
	    krb5_kt_free_entry(context, &tmp);
	    ret = GSS_S_COMPLETE; /* ok found one entry */
	}
	krb5_kt_end_seq_get (context, handle->keytab, &c);
    }
end:
    if (ret != GSS_S_COMPLETE) {
	if (handle->keytab != NULL)
	    krb5_kt_close(context, handle->keytab);
	if (kret != 0) {
	    *minor_status = kret;
	}
    }
    return (ret);
}
Example #3
0
krb5_error_code krb5_kt_find_realm(krb5_context context, krb5_keytab keytab,
    krb5_principal princ, krb5_data *realm) {

	krb5_kt_cursor cur;
	krb5_keytab_entry ent;
	krb5_boolean match;
	krb5_data tmp_realm;
	krb5_error_code ret, ret2;

	ret = krb5_kt_start_seq_get(context, keytab, &cur);
	if (ret != 0) {
		return (ret);
	}

	while ((ret = krb5_kt_next_entry(context, keytab, &ent, &cur)) == 0) {
		/* For the comparison the realms should be the same. */
		memcpy(&tmp_realm, &ent.principal->realm, sizeof (krb5_data));
		memcpy(&ent.principal->realm, &princ->realm,
		    sizeof (krb5_data));

		match = krb5_principal_compare(context, ent.principal, princ);

		/* Copy the realm back */
		memcpy(&ent.principal->realm, &tmp_realm, sizeof (krb5_data));

		if (match) {
			/*
			 * A suitable entry was found in the keytab.
			 * Copy its realm
			 */
			ret = krb5int_copy_data_contents(context,
			    &ent.principal->realm, realm);
			if (ret) {
				krb5_kt_free_entry(context, &ent);
				krb5_kt_end_seq_get(context, keytab, &cur);
				return (ret);
			}

			krb5_kt_free_entry(context, &ent);
			break;
		}

		krb5_kt_free_entry(context, &ent);
	}

	ret2 = krb5_kt_end_seq_get(context, keytab, &cur);

	if (ret == KRB5_KT_END) {
		return (KRB5_KT_NOTFOUND);
	}

	return (ret ? ret : ret2);
}
Example #4
0
static krb5_error_code
krb5_kt_get_entry_wrapped(krb5_context context,
			  krb5_keytab id,
			  krb5_const_principal principal,
			  krb5_kvno kvno,
			  krb5_enctype enctype,
			  krb5_keytab_entry *entry)
{
    krb5_keytab_entry tmp;
    krb5_error_code ret;
    krb5_kt_cursor cursor;

    if(id->get)
	return (*id->get)(context, id, principal, kvno, enctype, entry);

    ret = krb5_kt_start_seq_get (context, id, &cursor);
    if (ret) {
	/* This is needed for krb5_verify_init_creds, but keep error
	 * string from previous error for the human. */
	context->error_code = KRB5_KT_NOTFOUND;
	return KRB5_KT_NOTFOUND;
    }

    entry->vno = 0;
    while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) {
	if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) {
	    /* the file keytab might only store the lower 8 bits of
	       the kvno, so only compare those bits */
	    if (kvno == tmp.vno
		|| (tmp.vno < 256 && kvno % 256 == tmp.vno)) {
		krb5_kt_copy_entry_contents (context, &tmp, entry);
		krb5_kt_free_entry (context, &tmp);
		krb5_kt_end_seq_get(context, id, &cursor);
		return 0;
	    } else if (kvno == 0 && tmp.vno > entry->vno) {
		if (entry->vno)
		    krb5_kt_free_entry (context, entry);
		krb5_kt_copy_entry_contents (context, &tmp, entry);
	    }
	}
	krb5_kt_free_entry(context, &tmp);
    }
    krb5_kt_end_seq_get (context, id, &cursor);
    if (entry->vno == 0)
	return _krb5_kt_principal_not_found(context, KRB5_KT_NOTFOUND,
					    id, principal, enctype, kvno);
    return 0;
}
Example #5
0
KRB5_DEPRECATED
KRB5_LIB_FUNCTION krb5_error_code KRB5_CALLCONV
krb5_keytab_key_proc (krb5_context context,
		      krb5_enctype enctype,
		      krb5_salt salt,
		      krb5_const_pointer keyseed,
		      krb5_keyblock **key)
{
    krb5_keytab_key_proc_args *args  = rk_UNCONST(keyseed);
    krb5_keytab keytab = args->keytab;
    krb5_principal principal  = args->principal;
    krb5_error_code ret;
    krb5_keytab real_keytab;
    krb5_keytab_entry entry;

    if(keytab == NULL)
	krb5_kt_default(context, &real_keytab);
    else
	real_keytab = keytab;

    ret = krb5_kt_get_entry (context, real_keytab, principal,
			     0, enctype, &entry);

    if (keytab == NULL)
	krb5_kt_close (context, real_keytab);

    if (ret)
	return ret;

    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
    krb5_kt_free_entry(context, &entry);
    return ret;
}
Example #6
0
/*
 * Find the principal of the first entry of a keytab and return it.  The
 * caller is responsible for freeing the result with krb5_free_principal.
 * Exit on error.
 */
krb5_principal
kerberos_keytab_principal(krb5_context ctx, const char *path)
{
    krb5_keytab keytab;
    krb5_kt_cursor cursor;
    krb5_keytab_entry entry;
    krb5_principal princ;
    krb5_error_code status;

    status = krb5_kt_resolve(ctx, path, &keytab);
    if (status != 0)
        bail_krb5(ctx, status, "error opening %s", path);
    status = krb5_kt_start_seq_get(ctx, keytab, &cursor);
    if (status != 0)
        bail_krb5(ctx, status, "error reading %s", path);
    status = krb5_kt_next_entry(ctx, keytab, &entry, &cursor);
    if (status == 0) {
        status = krb5_copy_principal(ctx, entry.principal, &princ);
        if (status != 0)
            bail_krb5(ctx, status, "error copying principal from %s", path);
        krb5_kt_free_entry(ctx, &entry);
    }
    if (status != 0)
        bail("no principal found in keytab file %s", path);
    krb5_kt_end_seq_get(ctx, keytab, &cursor);
    krb5_kt_close(ctx, keytab);
    return princ;
}
Example #7
0
static krb5_error_code
mkt_close(krb5_context context, krb5_keytab id)
{
    struct mkt_data *d = id->data, **dp;
    int i;

    HEIMDAL_MUTEX_lock(&mkt_mutex);
    if (d->refcount < 1)
	krb5_abortx(context, 
		    "krb5 internal error, memory keytab refcount < 1 on close");

    if (--d->refcount > 0) {
	HEIMDAL_MUTEX_unlock(&mkt_mutex);
	return 0;
    }
    for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) {
	if (*dp == d) {
	    *dp = d->next;
	    break;
	}
    }
    HEIMDAL_MUTEX_unlock(&mkt_mutex);

    free(d->name);
    for(i = 0; i < d->num_entries; i++)
	krb5_kt_free_entry(context, &d->entries[i]);
    free(d->entries);
    free(d);
    return 0;
}
Example #8
0
/*
 * Given two files containing keytab data, second keytab, merge the keys into
 * the new file.  Currently, this doesn't do any cleanup of old kvnos and
 * doesn't handle duplicate kvnos correctly.  Dies on any error.
 */
static void
merge_keytab(krb5_context ctx, const char *newfile, const char *file)
{
    char *oldfile;
    krb5_keytab old = NULL, temp = NULL;
    krb5_kt_cursor cursor;
    krb5_keytab_entry entry;
    krb5_error_code status;

    memset(&entry, 0, sizeof(entry));
    xasprintf(&oldfile, "WRFILE:%s", file);
    status = krb5_kt_resolve(ctx, oldfile, &old);
    if (status != 0)
        die_krb5(ctx, status, "cannot open keytab %s", file);
    free(oldfile);
    status = krb5_kt_resolve(ctx, newfile, &temp);
    if (status != 0)
        die_krb5(ctx, status, "cannot open temporary keytab %s", newfile);
    status = krb5_kt_start_seq_get(ctx, temp, &cursor);
    if (status != 0)
        die_krb5(ctx, status, "cannot read temporary keytab %s", newfile);
    while ((status = krb5_kt_next_entry(ctx, temp, &entry, &cursor)) == 0) {
        status = krb5_kt_add_entry(ctx, old, &entry);
        if (status != 0)
            die_krb5(ctx, status, "cannot write to keytab %s", file);
        krb5_kt_free_entry(ctx, &entry);
    }
    if (status != KRB5_KT_END)
        die_krb5(ctx, status, "error reading temporary keytab %s", newfile);
    krb5_kt_end_seq_get(ctx, temp, &cursor);
    if (old != NULL)
        krb5_kt_close(ctx, old);
    if (temp != NULL)
        krb5_kt_close(ctx, temp);
}
Example #9
0
static krb5_error_code
mkt_remove_entry(krb5_context context,
		 krb5_keytab id,
		 krb5_keytab_entry *entry)
{
    struct mkt_data *d = id->data;
    krb5_keytab_entry *e, *end;
    int found = 0;
    
    if (d->num_entries == 0) {
	krb5_clear_error_string(context);
        return KRB5_KT_NOTFOUND;
    }

    /* do this backwards to minimize copying */
    for(end = d->entries + d->num_entries, e = end - 1; e >= d->entries; e--) {
	if(krb5_kt_compare(context, e, entry->principal, 
			   entry->vno, entry->keyblock.keytype)) {
	    krb5_kt_free_entry(context, e);
	    memmove(e, e + 1, (end - e - 1) * sizeof(*e));
	    memset(end - 1, 0, sizeof(*end));
	    d->num_entries--;
	    end--;
	    found = 1;
	}
    }
    if (!found) {
	krb5_clear_error_string (context);
	return KRB5_KT_NOTFOUND;
    }
    e = realloc(d->entries, d->num_entries * sizeof(*d->entries));
    if(e != NULL || d->num_entries == 0)
	d->entries = e;
    return 0;
}
mit_krb5_error_code KRB5_CALLCONV
krb5_kt_read_service_key(mit_krb5_context context,
			 mit_krb5_pointer keyprocarg,
			 mit_krb5_principal principal,
			 mit_krb5_kvno vno,
			 mit_krb5_enctype enctype,
			 mit_krb5_keyblock **key)
{
    mit_krb5_keytab keytab;
    mit_krb5_keytab_entry entry;
    mit_krb5_error_code ret;

    LOG_ENTRY();

    if (keyprocarg)
	ret = krb5_kt_resolve (context, keyprocarg, &keytab);
    else
	ret = krb5_kt_default (context, &keytab);

    if (ret)
	return ret;

    ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry);
    krb5_kt_close (context, keytab);
    if (ret)
	return ret;
    ret = krb5_copy_keyblock (context, &entry.key, key);
    krb5_kt_free_entry(context, &entry);
    return ret;
}
Example #11
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_read_service_key(krb5_context context,
			 krb5_pointer keyprocarg,
			 krb5_principal principal,
			 krb5_kvno vno,
			 krb5_enctype enctype,
			 krb5_keyblock **key)
{
    krb5_keytab keytab;
    krb5_keytab_entry entry;
    krb5_error_code ret;

    if (keyprocarg)
	ret = krb5_kt_resolve (context, keyprocarg, &keytab);
    else
	ret = krb5_kt_default (context, &keytab);

    if (ret)
	return ret;

    ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry);
    krb5_kt_close (context, keytab);
    if (ret)
	return ret;
    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
    krb5_kt_free_entry(context, &entry);
    return ret;
}
Example #12
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_kt_have_content(krb5_context context,
		     krb5_keytab id)
{
    krb5_keytab_entry entry;
    krb5_kt_cursor cursor;
    krb5_error_code ret;
    char *name;

    ret = krb5_kt_start_seq_get(context, id, &cursor);
    if (ret)
	goto notfound;

    ret = krb5_kt_next_entry(context, id, &entry, &cursor);
    krb5_kt_end_seq_get(context, id, &cursor);
    if (ret)
	goto notfound;

    krb5_kt_free_entry(context, &entry);

    return 0;

 notfound:
    ret = krb5_kt_get_full_name(context, id, &name);
    if (ret == 0) {
	krb5_set_error_message(context, KRB5_KT_NOTFOUND,
			       N_("No entry in keytab: %s", ""), name);
	free(name);
    }
    return KRB5_KT_NOTFOUND;
}
Example #13
0
/*
 * Given a context, a keytab file, and a realm, return a list of all
 * principals in that file.
 */
static struct principal_name *
keytab_principals(krb5_context ctx, const char *file, char *realm)
{
    char *princname = NULL, *princrealm = NULL;
    bool found;
    krb5_keytab keytab = NULL;
    krb5_kt_cursor cursor;
    krb5_keytab_entry entry;
    krb5_error_code status;
    struct principal_name *names = NULL, *current = NULL, *last = NULL;

    memset(&entry, 0, sizeof(entry));
    status = krb5_kt_resolve(ctx, file, &keytab);
    if (status != 0)
        die_krb5(ctx, status, "cannot open keytab %s", file);
    status = krb5_kt_start_seq_get(ctx, keytab, &cursor);
    if (status != 0)
        die_krb5(ctx, status, "cannot read keytab %s", file);
    while ((status = krb5_kt_next_entry(ctx, keytab, &entry, &cursor)) == 0) {
        status = krb5_unparse_name(ctx, entry.principal, &princname);
        if (status != 0)
            die_krb5(ctx, status, "cannot unparse name for a principal");

        /* Separate into principal and realm. */
        princrealm = strchr(princname, '@');
        if (princrealm != NULL) {
            *princrealm = '\0';
            princrealm++;
        }
        if (princrealm == NULL || strcmp(princrealm, realm) != 0)
            continue;

        /* Check to see if the principal has already been listed. */
        found = false;
        for (current = names; current != NULL; current = current->next) {
            if (strcmp(current->princ, princname) == 0) {
                found = true;
                break;
            }
            last = current;
        }
        if (found == false) {
            current = xmalloc(sizeof(struct principal_name));
            current->princ = xstrdup(princname);
            current->next = NULL;
            if (last == NULL)
                names = current;
            else
                last->next = current;
        }
        krb5_kt_free_entry(ctx, &entry);
        free(princname);
    }
    if (status != KRB5_KT_END)
        die_krb5(ctx, status, "error reading keytab %s", file);
    krb5_kt_end_seq_get(ctx, keytab, &cursor);
    krb5_kt_close(ctx, keytab);
    return names;
}
Example #14
0
static krb5_error_code
update_keytab_entry(krb5_context context,
		    kcm_ccache ccache,
		    krb5_enctype etype,
		    char *cpn,
		    char *spn,
		    char *newpw,
		    krb5_salt salt,
		    unsigned kvno)
{
    krb5_error_code ret;
    krb5_keytab_entry entry;
    krb5_data pw;

    memset(&entry, 0, sizeof(entry));

    pw.data = (char *)newpw;
    pw.length = strlen(newpw);

    ret = krb5_string_to_key_data_salt(context, etype, pw,
				       salt, &entry.keyblock);
    if (ret) {
	kcm_log(0, "String to key conversion failed for principal %s "
		"and etype %d: %s",
		cpn, etype, krb5_get_err_text(context, ret)); 
	return ret;
    }

    if (spn == NULL) {
	ret = krb5_copy_principal(context, ccache->client,
				  &entry.principal);
	if (ret) {
	    kcm_log(0, "Failed to copy principal name %s: %s",
		    cpn, krb5_get_err_text(context, ret));
	    return ret;
	}
    } else {
	ret = krb5_parse_name(context, spn, &entry.principal);
	if (ret) {
	    kcm_log(0, "Failed to parse SPN alias %s: %s",
		    spn, krb5_get_err_text(context, ret));
	    return ret;
	}
    }

    entry.vno = kvno;
    entry.timestamp = time(NULL);

    ret = krb5_kt_add_entry(context, ccache->key.keytab, &entry);
    if (ret) {
	kcm_log(0, "Failed to update keytab for principal %s "
		"and etype %d: %s",
		cpn, etype, krb5_get_err_text(context, ret));
    }

    krb5_kt_free_entry(context, &entry);

    return ret; 
}
mit_krb5_error_code KRB5_CALLCONV
krb5_kt_get_entry(mit_krb5_context context,
		  mit_krb5_keytab id,
		  mit_krb5_const_principal principal,
		  mit_krb5_kvno kvno,
		  mit_krb5_enctype enctype,
		  mit_krb5_keytab_entry *entry)
{
    mit_krb5_keytab_entry tmp;
    mit_krb5_error_code ret;
    mit_krb5_kt_cursor cursor;

    LOG_ENTRY();

    memset(entry, 0, sizeof(*entry));

    ret = krb5_kt_start_seq_get (context, id, &cursor);
    if (ret)
	return KRB5_KT_NOTFOUND;

    entry->vno = 0;
    while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) {
	if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) {
	    /* the file keytab might only store the lower 8 bits of
	       the kvno, so only compare those bits */
	    if (kvno == tmp.vno
		|| (tmp.vno < 256 && kvno % 256 == tmp.vno)) {
		krb5_kt_copy_entry_contents (context, &tmp, entry);
		krb5_kt_free_entry (context, &tmp);
		krb5_kt_end_seq_get(context, id, &cursor);
		return 0;
	    } else if (kvno == 0 && tmp.vno > entry->vno) {
		if (entry->vno)
		    krb5_kt_free_entry (context, entry);
		krb5_kt_copy_entry_contents (context, &tmp, entry);
	    }
	}
	krb5_kt_free_entry(context, &tmp);
    }
    krb5_kt_end_seq_get (context, id, &cursor);
    if (entry->vno == 0)
	return KRB5_KT_NOTFOUND;
    return 0;
}
Example #16
0
int
kssl_keytab_is_available(KSSL_CTX *kssl_ctx)
{
	krb5_context		krb5context = NULL;
	krb5_keytab 		krb5keytab = NULL;
	krb5_keytab_entry           entry;
	krb5_principal              princ = NULL;
	krb5_error_code  		krb5rc = KRB5KRB_ERR_GENERIC;
	int rc = 0;

	if ((krb5rc = krb5_init_context(&krb5context)))
		return (0);

    /*	kssl_ctx->keytab_file == NULL ==> use Kerberos default
    */
	if (kssl_ctx->keytab_file) {
		krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file,
		    &krb5keytab);
		if (krb5rc)
			goto exit;
	} else {
		krb5rc = krb5_kt_default(krb5context, &krb5keytab);
		if (krb5rc)
			goto exit;
	}

	/* the host key we are looking for */
	krb5rc = krb5_sname_to_principal(krb5context, NULL,
	    kssl_ctx->service_name ? kssl_ctx->service_name : KRB5SVC,
	    KRB5_NT_SRV_HST, &princ);

	if (krb5rc)
		goto exit;

	krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, princ,
	    0 /* IGNORE_VNO */,
	    0 /* IGNORE_ENCTYPE */,
	    &entry);
	if (krb5rc == KRB5_KT_NOTFOUND) {
		rc = 1;
		goto exit;
	} else if (krb5rc)
		goto exit;

	krb5_kt_free_entry(krb5context, &entry);
	rc = 1;

	exit:
	if (krb5keytab)
		krb5_kt_close(krb5context, krb5keytab);
	if (princ)
		krb5_free_principal(krb5context, princ);
	if (krb5context)
		krb5_free_context(krb5context);
	return (rc);
}
Example #17
0
 krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry)
{
#if defined(HAVE_KRB5_KT_FREE_ENTRY)
	return krb5_kt_free_entry(context, kt_entry);
#elif defined(HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS)
	return krb5_free_keytab_entry_contents(context, kt_entry);
#else
#error UNKNOWN_KT_FREE_FUNCTION
#endif
}
Example #18
0
static krb5_error_code
hkt_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal,
	       unsigned flags, krb5_kvno kvno, hdb_entry_ex * entry)
{
    hdb_keytab k = (hdb_keytab)db->hdb_db;
    krb5_error_code ret;
    krb5_keytab_entry ktentry;

    if (!(flags & HDB_F_KVNO_SPECIFIED)) {
	    /* Preserve previous behaviour if no kvno specified */
	    kvno = 0;
    }

    memset(&ktentry, 0, sizeof(ktentry));

    entry->entry.flags.server = 1;
    entry->entry.flags.forwardable = 1;
    entry->entry.flags.renewable = 1;

    /* Not recorded in the OD backend, make something up */
    ret = krb5_parse_name(context, "hdb/keytab@WELL-KNOWN:KEYTAB-BACKEND",
			  &entry->entry.created_by.principal);
    if (ret)
	goto out;

    /*
     * XXX really needs to try all enctypes and just not pick the
     * first one, even if that happens to be des3-cbc-sha1 (ie best
     * enctype) in the Apple case. A while loop over all known
     * enctypes should work.
     */

    ret = krb5_kt_get_entry(context, k->keytab, principal, kvno, 0, &ktentry);
    if (ret) {
	ret = HDB_ERR_NOENTRY;
	goto out;
    }

    ret = krb5_copy_principal(context, principal, &entry->entry.principal);
    if (ret)
	goto out;

    ret = _hdb_keytab2hdb_entry(context, &ktentry, entry);

 out:
    if (ret) {
	free_hdb_entry(&entry->entry);
	memset(&entry->entry, 0, sizeof(entry->entry));
    }
    krb5_kt_free_entry(context, &ktentry);

    return ret;
}
Example #19
0
static krb5_error_code
get_as_key_keytab(krb5_context context,
                  krb5_principal client,
                  krb5_enctype etype,
                  krb5_prompter_fct prompter,
                  void *prompter_data,
                  krb5_data *salt,
                  krb5_data *params,
                  krb5_keyblock *as_key,
                  void *gak_data,
                  k5_response_items *ritems)
{
    krb5_keytab keytab = (krb5_keytab) gak_data;
    krb5_error_code ret;
    krb5_keytab_entry kt_ent;
    krb5_keyblock *kt_key;

    /* We don't need the password from the responder to create the AS key. */
    if (as_key == NULL)
        return 0;

    /* if there's already a key of the correct etype, we're done.
       if the etype is wrong, free the existing key, and make
       a new one. */

    if (as_key->length) {
        if (as_key->enctype == etype)
            return(0);

        krb5_free_keyblock_contents(context, as_key);
        as_key->length = 0;
    }

    if (!krb5_c_valid_enctype(etype))
        return(KRB5_PROG_ETYPE_NOSUPP);

    if ((ret = krb5_kt_get_entry(context, keytab, client,
                                 0, /* don't have vno available */
                                 etype, &kt_ent)))
        return(ret);

    ret = krb5_copy_keyblock(context, &kt_ent.key, &kt_key);

    /* again, krb5's memory management is lame... */

    *as_key = *kt_key;
    free(kt_key);

    (void) krb5_kt_free_entry(context, &kt_ent);

    return(ret);
}
Example #20
0
static krb5_error_code
copy_keytab(krb5_context context, krb5_keytab from, krb5_keytab to)
{
    krb5_keytab_entry entry;
    krb5_kt_cursor cursor;
    krb5_error_code ret;

    ret = krb5_kt_start_seq_get(context, from, &cursor);
    if (ret)
	return ret;
    while((ret = krb5_kt_next_entry(context, from, &entry, &cursor)) == 0){
	krb5_kt_add_entry(context, to, &entry);
	krb5_kt_free_entry(context, &entry);
    }
    return krb5_kt_end_seq_get(context, from, &cursor);
}	    
Example #21
0
static OM_uint32 acquire_acceptor_cred
		  (OM_uint32 * minor_status,
		   const gss_name_t desired_name,
		   OM_uint32 time_req,
		   const gss_OID_set desired_mechs,
		   gss_cred_usage_t cred_usage,
		   gss_cred_id_t handle,
		   gss_OID_set * actual_mechs,
		   OM_uint32 * time_rec
		  )
{
    OM_uint32 ret;
    krb5_error_code kret;

    kret = 0;
    ret = GSS_S_FAILURE;
    kret = get_keytab(&handle->keytab);
    if (kret)
	goto end;
    
    /* check that the requested principal exists in the keytab */
    if (handle->principal) {
	krb5_keytab_entry entry;

	kret = krb5_kt_get_entry(gssapi_krb5_context, handle->keytab, 
				 handle->principal, 0, 0, &entry);
	if (kret)
	    goto end;
	krb5_kt_free_entry(gssapi_krb5_context, &entry);
    }
    ret = GSS_S_COMPLETE;
 
end:
    if (ret != GSS_S_COMPLETE) {
	if (handle->keytab != NULL)
	    krb5_kt_close(gssapi_krb5_context, handle->keytab);
	if (kret != 0) {
	    *minor_status = kret;
	    gssapi_krb5_set_error_string ();
	}
    }
    return (ret);
}
Example #22
0
static krb5_error_code
krb5_rd_req_decrypt_tkt_part(krb5_context context, const krb5_ap_req *req, krb5_keytab keytab)
{
    krb5_error_code 	  retval;
    krb5_enctype 	  enctype;
    krb5_keytab_entry 	  ktent;

    enctype = req->ticket->enc_part.enctype;

    if ((retval = krb5_kt_get_entry(context, keytab, req->ticket->server,
				    req->ticket->enc_part.kvno,
				    enctype, &ktent)))
	return retval;

    retval = krb5_decrypt_tkt_part(context, &ktent.key, req->ticket);
    /* Upon error, Free keytab entry first, then return */

    (void) krb5_kt_free_entry(context, &ktent);
    return retval;
}
Example #23
0
static krb5_error_code KRB5_CALLCONV
fkt_remove_entry(krb5_context context,
		 krb5_keytab id,
		 krb5_keytab_entry *entry)
{
    krb5_keytab_entry e;
    krb5_kt_cursor cursor;
    off_t pos_start, pos_end;
    int found = 0;
    krb5_error_code ret;

    ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY | O_CLOEXEC, 1, &cursor);
    if(ret != 0)
	goto out; /* return other error here? */
    while(fkt_next_entry_int(context, id, &e, &cursor,
			     &pos_start, &pos_end) == 0) {
	if(krb5_kt_compare(context, &e, entry->principal,
			   entry->vno, entry->keyblock.keytype)) {
	    int32_t len;
	    unsigned char buf[128];
	    found = 1;
	    krb5_storage_seek(cursor.sp, pos_start, SEEK_SET);
	    len = pos_end - pos_start - 4;
	    krb5_store_int32(cursor.sp, -len);
	    memset(buf, 0, sizeof(buf));
	    while(len > 0) {
		krb5_storage_write(cursor.sp, buf,
		    min((size_t)len, sizeof(buf)));
		len -= min((size_t)len, sizeof(buf));
	    }
	}
	krb5_kt_free_entry(context, &e);
    }
    krb5_kt_end_seq_get(context, id, &cursor);
  out:
    if (!found) {
	krb5_clear_error_message (context);
	return KRB5_KT_NOTFOUND;
    }
    return 0;
}
Example #24
0
/*
 * In a couple of places we need to get a principal name from a keytab: when
 * verifying credentials against a keytab, and when querying the name of a
 * default GSS acceptor cred.  Keytabs do not have the concept of a default
 * principal like ccaches do, so for now we just return the first principal
 * listed in the keytab, or an error if it's not iterable.  In the future we
 * could consider elevating this to a public API and giving keytab types an
 * operation to return a default principal, and maybe extending the file format
 * and tools to support it.  Returns KRB5_KT_NOTFOUND if the keytab is empty
 * or non-iterable.
 */
krb5_error_code
k5_kt_get_principal(krb5_context context, krb5_keytab keytab,
                    krb5_principal *princ_out)
{
    krb5_error_code ret;
    krb5_kt_cursor cursor;
    krb5_keytab_entry kte;

    *princ_out = NULL;
    if (keytab->ops->start_seq_get == NULL)
        return KRB5_KT_NOTFOUND;
    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    if (ret)
        return ret;
    ret = krb5_kt_next_entry(context, keytab, &kte, &cursor);
    (void)krb5_kt_end_seq_get(context, keytab, &cursor);
    if (ret)
        return (ret == KRB5_KT_END) ? KRB5_KT_NOTFOUND : ret;
    ret = krb5_copy_principal(context, kte.principal, princ_out);
    krb5_kt_free_entry(context, &kte);
    return ret;
}
Example #25
0
static krb5_error_code
get_key_from_keytab(krb5_context context,
		    krb5_auth_context *auth_context,
		    krb5_ap_req *ap_req,
		    krb5_const_principal server,
		    krb5_keytab keytab,
		    krb5_keyblock **out_key)
{
    krb5_keytab_entry entry;
    krb5_error_code ret;
    int kvno;
    krb5_keytab real_keytab;

    if(keytab == NULL)
	krb5_kt_default(context, &real_keytab);
    else
	real_keytab = keytab;
    
    if (ap_req->ticket.enc_part.kvno)
	kvno = *ap_req->ticket.enc_part.kvno;
    else
	kvno = 0;

    ret = krb5_kt_get_entry (context,
			     real_keytab,
			     server,
			     kvno,
			     ap_req->ticket.enc_part.etype,
			     &entry);
    if(ret)
	goto out;
    ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);
    krb5_kt_free_entry (context, &entry);
out:    
    if(keytab == NULL)
	krb5_kt_close(context, real_keytab);
    
    return ret;
}
Example #26
0
krb5_error_code	KRB5_CALLCONV
krb5_server_decrypt_ticket_keytab(krb5_context context,
				  const krb5_keytab kt,
				  krb5_ticket *ticket)
{
    krb5_error_code       retval;
    krb5_enctype          enctype;
    krb5_keytab_entry     ktent;

    enctype = ticket->enc_part.enctype;

    if ((retval = krb5_kt_get_entry(context, kt, ticket->server,
                                    ticket->enc_part.kvno,
                                    enctype, &ktent)))
        return retval;

    retval = krb5int_server_decrypt_ticket_keyblock(context,
						    &ktent.key, ticket);
    /* Upon error, Free keytab entry first, then return */

    (void) krb5_kt_free_entry(context, &ktent);
    return retval;
}
Example #27
0
krb5_error_code KRB5_CALLCONV
krb5_mkt_remove(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
{
    krb5_mkt_cursor *pcursor, next;
    krb5_error_code err = 0;

    err = KTLOCK(id);
    if (err)
	return err;

    if ( KTLINK(id) == NULL ) {
	err = KRB5_KT_NOTFOUND;
	goto done;
    }

    for ( pcursor = &KTLINK(id); *pcursor; pcursor = &(*pcursor)->next ) {
	if ( (*pcursor)->entry->vno == entry->vno &&
	     (*pcursor)->entry->key.enctype == entry->key.enctype &&
	     krb5_principal_compare(context, (*pcursor)->entry->principal, entry->principal))
	     break;
    }

    if (!*pcursor) {
	err = KRB5_KT_NOTFOUND;
	goto done;
    }

    krb5_kt_free_entry(context, (*pcursor)->entry);
    free((*pcursor)->entry);
    next = (*pcursor)->next;
    free(*pcursor);
    (*pcursor) = next;

  done:
    KTUNLOCK(id);
    return err;
}
Example #28
0
/*
 * effects: If keyprocarg is not NULL, it is taken to be the name of a 
 *	keytab.  Otherwise, the default keytab will be used.  This 
 *	routine opens the keytab and finds the principal associated with
 *	principal, vno, and enctype and returns the resulting key in *key 
 *	or returning an error code if it is not	found. 
 * returns: Either KSUCCESS or error code.
 * errors: error code if not found or keyprocarg is invalid.
 */
krb5_error_code KRB5_CALLCONV
krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock **key)
{
    krb5_error_code kerror = KSUCCESS;
    char keytabname[MAX_KEYTAB_NAME_LEN + 1]; /* + 1 for NULL termination */
    krb5_keytab id;
    krb5_keytab_entry entry;
        
    /*
     * Get the name of the file that we should use. 
     */
    if (!keyprocarg) {
	if ((kerror = krb5_kt_default_name(context, (char *)keytabname, 
					   sizeof(keytabname) - 1))!= KSUCCESS)
	    return (kerror);
    } else {
	memset(keytabname, 0, sizeof(keytabname));
	(void) strncpy(keytabname, (char *)keyprocarg, 
		       sizeof(keytabname) - 1);
    }

    if ((kerror = krb5_kt_resolve(context, (char *)keytabname, &id)))
	return (kerror);

    kerror = krb5_kt_get_entry(context, id, principal, vno, enctype, &entry);
    krb5_kt_close(context, id);

    if (kerror)
	return(kerror);

    krb5_copy_keyblock(context, &entry.key, key);

    krb5_kt_free_entry(context, &entry);

    return (KSUCCESS);
}
static int
check_keytab(krb5_context context,
	     gsskrb5_cred handle,
	     const char *service,
	     int require_lkdc)
{
    krb5_keytab_entry tmp;
    krb5_error_code ret;
    krb5_kt_cursor c;
    int found = 0;

    ret = krb5_kt_start_seq_get (context, handle->keytab, &c);
    if (ret)
	return 0;
    while (!found && krb5_kt_next_entry(context, handle->keytab, &tmp, &c) == 0) {
	krb5_principal principal = tmp.principal;

	if (service) {
	    if (principal->name.name_string.len < 1
		|| strcmp(principal->name.name_string.val[0], service) != 0)
		goto next;
	}
	if (require_lkdc) {
	    if (krb5_principal_is_lkdc(context, principal))
		found = 1;
	    if (krb5_principal_is_pku2u(context, principal))
		found = 1;
	} else
	    found = 1;
      next:
	krb5_kt_free_entry(context, &tmp);
    }
    krb5_kt_end_seq_get (context, handle->keytab, &c);

    return found;
}
Example #30
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_copy_entry_contents(krb5_context context,
			    const krb5_keytab_entry *in,
			    krb5_keytab_entry *out)
{
    krb5_error_code ret;

    memset(out, 0, sizeof(*out));
    out->vno = in->vno;

    ret = krb5_copy_principal (context, in->principal, &out->principal);
    if (ret)
	goto fail;
    ret = krb5_copy_keyblock_contents (context,
				       &in->keyblock,
				       &out->keyblock);
    if (ret)
	goto fail;
    out->timestamp = in->timestamp;
    return 0;
fail:
    krb5_kt_free_entry (context, out);
    return ret;
}