wmi-1.3.16 from opsview.com

This commit is contained in:
Are Casilla
2019-02-16 00:16:52 +01:00
parent 163fdd3d1b
commit 17b3af2911
2146 changed files with 678824 additions and 0 deletions
+935
View File
@@ -0,0 +1,935 @@
/*
* Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include <krb5_ccapi.h>
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
RCSID("$Id: acache.c,v 1.16 2006/10/19 11:41:38 lha Exp $");
/* XXX should we fetch these for each open ? */
static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
static cc_initialize_func init_func;
#ifdef HAVE_DLOPEN
static void *cc_handle;
#endif
typedef struct krb5_acc {
char *cache_name;
cc_context_t context;
cc_ccache_t ccache;
} krb5_acc;
static krb5_error_code acc_close(krb5_context, krb5_ccache);
#define ACACHE(X) ((krb5_acc *)(X)->data.data)
static const struct {
cc_int32 error;
krb5_error_code ret;
} cc_errors[] = {
{ ccErrBadName, KRB5_CC_BADNAME },
{ ccErrCredentialsNotFound, KRB5_CC_NOTFOUND },
{ ccErrCCacheNotFound, KRB5_FCC_NOFILE },
{ ccErrContextNotFound, KRB5_CC_NOTFOUND },
{ ccIteratorEnd, KRB5_CC_END },
{ ccErrNoMem, KRB5_CC_NOMEM },
{ ccErrServerUnavailable, KRB5_CC_NOSUPP },
{ ccNoError, 0 }
};
static krb5_error_code
translate_cc_error(krb5_context context, cc_int32 error)
{
int i;
krb5_clear_error_string(context);
for(i = 0; i < sizeof(cc_errors)/sizeof(cc_errors[0]); i++)
if (cc_errors[i].error == error)
return cc_errors[i].ret;
return KRB5_FCC_INTERNAL;
}
static krb5_error_code
init_ccapi(krb5_context context)
{
const char *lib;
HEIMDAL_MUTEX_lock(&acc_mutex);
if (init_func) {
HEIMDAL_MUTEX_unlock(&acc_mutex);
krb5_clear_error_string(context);
return 0;
}
lib = krb5_config_get_string(context, NULL,
"libdefaults", "ccapi_library",
NULL);
if (lib == NULL) {
#ifdef __APPLE__
lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos";
#else
lib = "/usr/lib/libkrb5_cc.so";
#endif
}
#ifdef HAVE_DLOPEN
cc_handle = dlopen(lib, 0);
if (cc_handle == NULL) {
HEIMDAL_MUTEX_unlock(&acc_mutex);
krb5_set_error_string(context, "Failed to load %s", lib);
return KRB5_CC_NOSUPP;
}
init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize");
HEIMDAL_MUTEX_unlock(&acc_mutex);
if (init_func == NULL) {
krb5_set_error_string(context, "Failed to find cc_initialize"
"in %s: %s", lib, dlerror());
dlclose(cc_handle);
return KRB5_CC_NOSUPP;
}
return 0;
#else
HEIMDAL_MUTEX_unlock(&acc_mutex);
krb5_set_error_string(context, "no support for shared object");
return KRB5_CC_NOSUPP;
#endif
}
static krb5_error_code
make_cred_from_ccred(krb5_context context,
const cc_credentials_v5_t *incred,
krb5_creds *cred)
{
krb5_error_code ret;
int i;
memset(cred, 0, sizeof(*cred));
ret = krb5_parse_name(context, incred->client, &cred->client);
if (ret)
goto fail;
ret = krb5_parse_name(context, incred->server, &cred->server);
if (ret)
goto fail;
cred->session.keytype = incred->keyblock.type;
cred->session.keyvalue.length = incred->keyblock.length;
cred->session.keyvalue.data = malloc(incred->keyblock.length);
if (cred->session.keyvalue.data == NULL)
goto nomem;
memcpy(cred->session.keyvalue.data, incred->keyblock.data,
incred->keyblock.length);
cred->times.authtime = incred->authtime;
cred->times.starttime = incred->starttime;
cred->times.endtime = incred->endtime;
cred->times.renew_till = incred->renew_till;
ret = krb5_data_copy(&cred->ticket,
incred->ticket.data,
incred->ticket.length);
if (ret)
goto nomem;
ret = krb5_data_copy(&cred->second_ticket,
incred->second_ticket.data,
incred->second_ticket.length);
if (ret)
goto nomem;
cred->authdata.val = NULL;
cred->authdata.len = 0;
cred->addresses.val = NULL;
cred->addresses.len = 0;
for (i = 0; incred->authdata && incred->authdata[i]; i++)
;
if (i) {
cred->authdata.val = malloc(sizeof(cred->authdata.val[0]) * i);
if (cred->authdata.val == NULL)
goto nomem;
cred->authdata.len = i;
memset(cred->authdata.val, 0, sizeof(cred->authdata.val[0]) * i);
for (i = 0; i < cred->authdata.len; i++) {
cred->authdata.val[i].ad_type = incred->authdata[i]->type;
ret = krb5_data_copy(&cred->authdata.val[i].ad_data,
incred->authdata[i]->data,
incred->authdata[i]->length);
if (ret)
goto nomem;
}
}
for (i = 0; incred->addresses && incred->addresses[i]; i++)
;
if (i) {
cred->addresses.val = malloc(sizeof(cred->addresses.val[0]) * i);
if (cred->addresses.val == NULL)
goto nomem;
cred->addresses.len = i;
memset(cred->addresses.val, 0, sizeof(cred->addresses.val[0]) * i);
for (i = 0; i < cred->addresses.len; i++) {
cred->addresses.val[i].addr_type = incred->addresses[i]->type;
ret = krb5_data_copy(&cred->addresses.val[i].address,
incred->addresses[i]->data,
incred->addresses[i]->length);
if (ret)
goto nomem;
}
}
cred->flags.i = 0;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDABLE)
cred->flags.b.forwardable = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDED)
cred->flags.b.forwarded = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXIABLE)
cred->flags.b.proxiable = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXY)
cred->flags.b.proxy = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_MAY_POSTDATE)
cred->flags.b.may_postdate = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_POSTDATED)
cred->flags.b.postdated = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INVALID)
cred->flags.b.invalid = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_RENEWABLE)
cred->flags.b.renewable = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INITIAL)
cred->flags.b.initial = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PRE_AUTH)
cred->flags.b.pre_authent = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_HW_AUTH)
cred->flags.b.hw_authent = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED)
cred->flags.b.transited_policy_checked = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE)
cred->flags.b.ok_as_delegate = 1;
if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_ANONYMOUS)
cred->flags.b.anonymous = 1;
return 0;
nomem:
ret = ENOMEM;
krb5_set_error_string(context, "malloc - out of memory");
fail:
krb5_free_creds_contents(context, cred);
return ret;
}
static void
free_ccred(cc_credentials_v5_t *cred)
{
int i;
if (cred->addresses) {
for (i = 0; cred->addresses[i] != 0; i++) {
if (cred->addresses[i]->data)
free(cred->addresses[i]->data);
free(cred->addresses[i]);
}
free(cred->addresses);
}
if (cred->server)
free(cred->server);
if (cred->client)
free(cred->client);
memset(cred, 0, sizeof(*cred));
}
static krb5_error_code
make_ccred_from_cred(krb5_context context,
const krb5_creds *incred,
cc_credentials_v5_t *cred)
{
krb5_error_code ret;
int i;
memset(cred, 0, sizeof(*cred));
ret = krb5_unparse_name(context, incred->client, &cred->client);
if (ret)
goto fail;
ret = krb5_unparse_name(context, incred->server, &cred->server);
if (ret)
goto fail;
cred->keyblock.type = incred->session.keytype;
cred->keyblock.length = incred->session.keyvalue.length;
cred->keyblock.data = incred->session.keyvalue.data;
cred->authtime = incred->times.authtime;
cred->starttime = incred->times.starttime;
cred->endtime = incred->times.endtime;
cred->renew_till = incred->times.renew_till;
cred->ticket.length = incred->ticket.length;
cred->ticket.data = incred->ticket.data;
cred->second_ticket.length = incred->second_ticket.length;
cred->second_ticket.data = incred->second_ticket.data;
/* XXX this one should also be filled in */
cred->authdata = NULL;
cred->addresses = calloc(incred->addresses.len + 1,
sizeof(cred->addresses[0]));
if (cred->addresses == NULL) {
ret = ENOMEM;
goto fail;
}
for (i = 0; i < incred->addresses.len; i++) {
cc_data *addr;
addr = malloc(sizeof(*addr));
addr->type = incred->addresses.val[i].addr_type;
addr->length = incred->addresses.val[i].address.length;
addr->data = malloc(addr->length);
if (addr->data == NULL) {
ret = ENOMEM;
goto fail;
}
memcpy(addr->data, incred->addresses.val[i].address.data,
addr->length);
cred->addresses[i] = addr;
}
cred->addresses[i] = NULL;
cred->ticket_flags = 0;
if (incred->flags.b.forwardable)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDABLE;
if (incred->flags.b.forwarded)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDED;
if (incred->flags.b.proxiable)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXIABLE;
if (incred->flags.b.proxy)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXY;
if (incred->flags.b.may_postdate)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE;
if (incred->flags.b.postdated)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_POSTDATED;
if (incred->flags.b.invalid)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INVALID;
if (incred->flags.b.renewable)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_RENEWABLE;
if (incred->flags.b.initial)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INITIAL;
if (incred->flags.b.pre_authent)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PRE_AUTH;
if (incred->flags.b.hw_authent)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_HW_AUTH;
if (incred->flags.b.transited_policy_checked)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED;
if (incred->flags.b.ok_as_delegate)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE;
if (incred->flags.b.anonymous)
cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_ANONYMOUS;
return 0;
fail:
free_ccred(cred);
krb5_clear_error_string(context);
return ret;
}
static char *
get_cc_name(cc_ccache_t cache)
{
cc_string_t name;
cc_int32 error;
char *str;
error = (*cache->func->get_name)(cache, &name);
if (error)
return NULL;
str = strdup(name->data);
(*name->func->release)(name);
return str;
}
static const char*
acc_get_name(krb5_context context,
krb5_ccache id)
{
krb5_acc *a = ACACHE(id);
static char n[255];
char *name;
name = get_cc_name(a->ccache);
if (name == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return NULL;
}
strlcpy(n, name, sizeof(n));
free(name);
return n;
}
static krb5_error_code
acc_alloc(krb5_context context, krb5_ccache *id)
{
krb5_error_code ret;
cc_int32 error;
krb5_acc *a;
ret = init_ccapi(context);
if (ret)
return ret;
ret = krb5_data_alloc(&(*id)->data, sizeof(*a));
if (ret) {
krb5_clear_error_string(context);
return ret;
}
a = ACACHE(*id);
error = (*init_func)(&a->context, ccapi_version_3, NULL, NULL);
if (error) {
krb5_data_free(&(*id)->data);
return translate_cc_error(context, error);
}
a->cache_name = NULL;
return 0;
}
static krb5_error_code
get_default_principal(krb5_context context, char **p)
{
krb5_error_code ret;
krb5_principal principal;
*p = NULL;
ret = _krb5_get_default_principal_local(context, &principal);
if (ret)
return ret;
ret = krb5_unparse_name(context, principal, p);
krb5_free_principal(context, principal);
return ret;
}
static krb5_error_code
acc_resolve(krb5_context context, krb5_ccache *id, const char *res)
{
krb5_error_code ret;
cc_int32 error;
krb5_acc *a;
ret = acc_alloc(context, id);
if (ret)
return ret;
a = ACACHE(*id);
if (res == NULL || res[0] == '\0') {
error = (*a->context->func->open_default_ccache)(a->context,
&a->ccache);
if (error == ccErrCCacheNotFound) {
char *p;
ret = get_default_principal(context, &p);
if (ret == 0) {
error = (*a->context->func->create_default_ccache)(a->context,
cc_credentials_v5,
p,
&a->ccache);
free(p);
}
}
if (error == 0)
a->cache_name = get_cc_name(a->ccache);
} else {
error = (*a->context->func->open_ccache)(a->context, res, &a->ccache);
if (error == 0)
a->cache_name = strdup(res);
}
if (error != 0) {
*id = NULL;
return translate_cc_error(context, error);
}
if (a->cache_name == NULL) {
acc_close(context, *id);
*id = NULL;
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
return 0;
}
static krb5_error_code
acc_gen_new(krb5_context context, krb5_ccache *id)
{
krb5_error_code ret;
cc_int32 error;
krb5_acc *a;
char *p;
ret = get_default_principal(context, &p);
ret = acc_alloc(context, id);
if (ret) {
free(p);
return ret;
}
a = ACACHE(*id);
error = (*a->context->func->create_new_ccache)(a->context,
cc_credentials_v5,
p, &a->ccache);
free(p);
if (error) {
*id = NULL;
return translate_cc_error(context, error);
}
a->cache_name = get_cc_name(a->ccache);
if (a->cache_name == NULL) {
acc_close(context, *id);
*id = NULL;
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
return 0;
}
static krb5_error_code
acc_initialize(krb5_context context,
krb5_ccache id,
krb5_principal primary_principal)
{
cc_credentials_iterator_t iter;
krb5_acc *a = ACACHE(id);
cc_credentials_t ccred;
krb5_error_code ret;
int32_t error;
char *name;
ret = krb5_unparse_name(context, primary_principal, &name);
if (ret)
return ret;
if (a->ccache == NULL) {
error = (*a->context->func->create_new_ccache)(a->context,
cc_credentials_v5,
name,
&a->ccache);
} else {
error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
if (error) {
free(name);
return translate_cc_error(context, error);
}
while (1) {
error = (*iter->func->next)(iter, &ccred);
if (error)
break;
(*a->ccache->func->remove_credentials)(a->ccache, ccred);
(*ccred->func->release)(ccred);
}
(*iter->func->release)(iter);
error = (*a->ccache->func->set_principal)(a->ccache,
cc_credentials_v5,
name);
}
free(name);
return translate_cc_error(context, error);
}
static krb5_error_code
acc_close(krb5_context context,
krb5_ccache id)
{
krb5_acc *a = ACACHE(id);
if (a->ccache) {
(*a->ccache->func->release)(a->ccache);
a->ccache = NULL;
}
if (a->cache_name) {
free(a->cache_name);
a->cache_name = NULL;
}
(*a->context->func->release)(a->context);
a->context = NULL;
krb5_data_free(&id->data);
return 0;
}
static krb5_error_code
acc_destroy(krb5_context context,
krb5_ccache id)
{
krb5_acc *a = ACACHE(id);
cc_int32 error = 0;
if (a->ccache) {
error = (*a->ccache->func->destroy)(a->ccache);
a->ccache = NULL;
}
return translate_cc_error(context, error);
}
static krb5_error_code
acc_store_cred(krb5_context context,
krb5_ccache id,
krb5_creds *creds)
{
krb5_acc *a = ACACHE(id);
cc_credentials_union cred;
cc_credentials_v5_t v5cred;
krb5_error_code ret;
cc_int32 error;
cred.version = cc_credentials_v5;
cred.credentials.credentials_v5 = &v5cred;
ret = make_ccred_from_cred(context,
creds,
&v5cred);
if (ret)
return ret;
error = (*a->ccache->func->store_credentials)(a->ccache, &cred);
if (error)
ret = translate_cc_error(context, error);
free_ccred(&v5cred);
return ret;
}
static krb5_error_code
acc_get_principal(krb5_context context,
krb5_ccache id,
krb5_principal *principal)
{
krb5_acc *a = ACACHE(id);
krb5_error_code ret;
int32_t error;
cc_string_t name;
if (a->ccache == NULL)
return ENOENT;
error = (*a->ccache->func->get_principal)(a->ccache,
cc_credentials_v5,
&name);
if (error)
return translate_cc_error(context, error);
ret = krb5_parse_name(context, name->data, principal);
(*name->func->release)(name);
return ret;
}
static krb5_error_code
acc_get_first (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor)
{
cc_credentials_iterator_t iter;
krb5_acc *a = ACACHE(id);
int32_t error;
error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
if (error) {
krb5_clear_error_string(context);
return ENOENT;
}
*cursor = iter;
return 0;
}
static krb5_error_code
acc_get_next (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor,
krb5_creds *creds)
{
cc_credentials_iterator_t iter = *cursor;
cc_credentials_t cred;
krb5_error_code ret;
int32_t error;
while (1) {
error = (*iter->func->next)(iter, &cred);
if (error)
return translate_cc_error(context, error);
if (cred->data->version == cc_credentials_v5)
break;
(*cred->func->release)(cred);
}
ret = make_cred_from_ccred(context,
cred->data->credentials.credentials_v5,
creds);
(*cred->func->release)(cred);
return ret;
}
static krb5_error_code
acc_end_get (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor)
{
cc_credentials_iterator_t iter = *cursor;
(*iter->func->release)(iter);
return 0;
}
static krb5_error_code
acc_remove_cred(krb5_context context,
krb5_ccache id,
krb5_flags which,
krb5_creds *cred)
{
cc_credentials_iterator_t iter;
krb5_acc *a = ACACHE(id);
cc_credentials_t ccred;
krb5_error_code ret;
cc_int32 error;
char *client, *server;
if (cred->client) {
ret = krb5_unparse_name(context, cred->client, &client);
if (ret)
return ret;
} else
client = NULL;
ret = krb5_unparse_name(context, cred->server, &server);
if (ret) {
free(client);
return ret;
}
error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
if (error) {
free(server);
free(client);
return translate_cc_error(context, error);
}
ret = KRB5_CC_NOTFOUND;
while (1) {
cc_credentials_v5_t *v5cred;
error = (*iter->func->next)(iter, &ccred);
if (error)
break;
if (ccred->data->version != cc_credentials_v5)
goto next;
v5cred = ccred->data->credentials.credentials_v5;
if (client && strcmp(v5cred->client, client) != 0)
goto next;
if (strcmp(v5cred->server, server) != 0)
goto next;
(*a->ccache->func->remove_credentials)(a->ccache, ccred);
ret = 0;
next:
(*ccred->func->release)(ccred);
}
(*iter->func->release)(iter);
if (ret)
krb5_set_error_string(context, "Can't find credential %s in cache",
server);
free(server);
free(client);
return ret;
}
static krb5_error_code
acc_set_flags(krb5_context context,
krb5_ccache id,
krb5_flags flags)
{
return 0;
}
static krb5_error_code
acc_get_version(krb5_context context,
krb5_ccache id)
{
return 0;
}
struct cache_iter {
cc_context_t context;
cc_ccache_iterator_t iter;
};
static krb5_error_code
acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
{
struct cache_iter *iter;
krb5_error_code ret;
cc_int32 error;
ret = init_ccapi(context);
if (ret)
return ret;
iter = calloc(1, sizeof(*iter));
if (iter == NULL) {
krb5_set_error_string(context, "malloc - out of memory");
return ENOMEM;
}
error = (*init_func)(&iter->context, ccapi_version_3, NULL, NULL);
if (error) {
free(iter);
return translate_cc_error(context, error);
}
error = (*iter->context->func->new_ccache_iterator)(iter->context,
&iter->iter);
if (error) {
free(iter);
krb5_clear_error_string(context);
return ENOENT;
}
*cursor = iter;
return 0;
}
static krb5_error_code
acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
{
struct cache_iter *iter = cursor;
cc_ccache_t cache;
krb5_acc *a;
krb5_error_code ret;
int32_t error;
error = (*iter->iter->func->next)(iter->iter, &cache);
if (error)
return translate_cc_error(context, error);
ret = _krb5_cc_allocate(context, &krb5_acc_ops, id);
if (ret) {
(*cache->func->release)(cache);
return ret;
}
ret = acc_alloc(context, id);
if (ret) {
(*cache->func->release)(cache);
free(*id);
return ret;
}
a = ACACHE(*id);
a->ccache = cache;
a->cache_name = get_cc_name(a->ccache);
if (a->cache_name == NULL) {
acc_close(context, *id);
*id = NULL;
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
return 0;
}
static krb5_error_code
acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
{
struct cache_iter *iter = cursor;
(*iter->iter->func->release)(iter->iter);
iter->iter = NULL;
(*iter->context->func->release)(iter->context);
iter->context = NULL;
free(iter);
return 0;
}
const krb5_cc_ops krb5_acc_ops = {
"API",
acc_get_name,
acc_resolve,
acc_gen_new,
acc_initialize,
acc_destroy,
acc_close,
acc_store_cred,
NULL, /* acc_retrieve */
acc_get_principal,
acc_get_first,
acc_get_next,
acc_end_get,
acc_remove_cred,
acc_set_flags,
acc_get_version,
acc_get_cache_first,
acc_get_cache_next,
acc_end_cache_get
};
@@ -0,0 +1,50 @@
/*
* Copyright (c) 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: add_et_list.c,v 1.3 2004/04/13 14:33:45 lha Exp $");
/*
* Add a specified list of error messages to the et list in context.
* Call func (probably a comerr-generated function) with a pointer to
* the current et_list.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_add_et_list (krb5_context context,
void (*func)(struct et_list **))
{
(*func)(&context->et_list);
return 0;
}
File diff suppressed because it is too large Load Diff
+142
View File
@@ -0,0 +1,142 @@
/*
* Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: appdefault.c,v 1.10 2005/01/05 05:40:59 lukeh Exp $");
void KRB5_LIB_FUNCTION
krb5_appdefault_boolean(krb5_context context, const char *appname,
krb5_const_realm realm, const char *option,
krb5_boolean def_val, krb5_boolean *ret_val)
{
if(appname == NULL)
appname = getprogname();
def_val = krb5_config_get_bool_default(context, NULL, def_val,
"libdefaults", option, NULL);
if(realm != NULL)
def_val = krb5_config_get_bool_default(context, NULL, def_val,
"realms", realm, option, NULL);
def_val = krb5_config_get_bool_default(context, NULL, def_val,
"appdefaults",
option,
NULL);
if(realm != NULL)
def_val = krb5_config_get_bool_default(context, NULL, def_val,
"appdefaults",
realm,
option,
NULL);
if(appname != NULL) {
def_val = krb5_config_get_bool_default(context, NULL, def_val,
"appdefaults",
appname,
option,
NULL);
if(realm != NULL)
def_val = krb5_config_get_bool_default(context, NULL, def_val,
"appdefaults",
appname,
realm,
option,
NULL);
}
*ret_val = def_val;
}
void KRB5_LIB_FUNCTION
krb5_appdefault_string(krb5_context context, const char *appname,
krb5_const_realm realm, const char *option,
const char *def_val, char **ret_val)
{
if(appname == NULL)
appname = getprogname();
def_val = krb5_config_get_string_default(context, NULL, def_val,
"libdefaults", option, NULL);
if(realm != NULL)
def_val = krb5_config_get_string_default(context, NULL, def_val,
"realms", realm, option, NULL);
def_val = krb5_config_get_string_default(context, NULL, def_val,
"appdefaults",
option,
NULL);
if(realm != NULL)
def_val = krb5_config_get_string_default(context, NULL, def_val,
"appdefaults",
realm,
option,
NULL);
if(appname != NULL) {
def_val = krb5_config_get_string_default(context, NULL, def_val,
"appdefaults",
appname,
option,
NULL);
if(realm != NULL)
def_val = krb5_config_get_string_default(context, NULL, def_val,
"appdefaults",
appname,
realm,
option,
NULL);
}
if(def_val != NULL)
*ret_val = strdup(def_val);
else
*ret_val = NULL;
}
void KRB5_LIB_FUNCTION
krb5_appdefault_time(krb5_context context, const char *appname,
krb5_const_realm realm, const char *option,
time_t def_val, time_t *ret_val)
{
krb5_deltat t;
char *val;
krb5_appdefault_string(context, appname, realm, option, NULL, &val);
if (val == NULL) {
*ret_val = def_val;
return;
}
if (krb5_string_to_deltat(val, &t))
*ret_val = def_val;
else
*ret_val = t;
free(val);
}
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (c) 1997 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
*
*/
#include "krb5_locl.h"
RCSID("$Id: asn1_glue.c,v 1.10 2006/10/06 17:02:48 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
_krb5_principal2principalname (PrincipalName *p,
const krb5_principal from)
{
return copy_PrincipalName(&from->name, p);
}
krb5_error_code KRB5_LIB_FUNCTION
_krb5_principalname2krb5_principal (krb5_context context,
krb5_principal *principal,
const PrincipalName from,
const Realm realm)
{
if (from.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
if (from.name_string.len != 1) {
return KRB5_PARSE_MALFORMED;
}
return krb5_parse_name(context,
from.name_string.val[0],
principal);
} else {
krb5_principal p = malloc(sizeof(*p));
copy_PrincipalName(&from, &p->name);
p->realm = strdup(realm);
*principal = p;
}
return 0;
}
@@ -0,0 +1,517 @@
/*
* Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: auth_context.c,v 1.62 2005/01/05 02:34:08 lukeh Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_init(krb5_context context,
krb5_auth_context *auth_context)
{
krb5_auth_context p;
ALLOC(p, 1);
if(!p) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
memset(p, 0, sizeof(*p));
ALLOC(p->authenticator, 1);
if (!p->authenticator) {
krb5_set_error_string(context, "malloc: out of memory");
free(p);
return ENOMEM;
}
memset (p->authenticator, 0, sizeof(*p->authenticator));
p->flags = KRB5_AUTH_CONTEXT_DO_TIME;
p->local_address = NULL;
p->remote_address = NULL;
p->local_port = 0;
p->remote_port = 0;
p->keytype = KEYTYPE_NULL;
p->cksumtype = CKSUMTYPE_NONE;
*auth_context = p;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_free(krb5_context context,
krb5_auth_context auth_context)
{
if (auth_context != NULL) {
krb5_free_authenticator(context, &auth_context->authenticator);
if(auth_context->local_address){
free_HostAddress(auth_context->local_address);
free(auth_context->local_address);
}
if(auth_context->remote_address){
free_HostAddress(auth_context->remote_address);
free(auth_context->remote_address);
}
krb5_free_keyblock(context, auth_context->keyblock);
krb5_free_keyblock(context, auth_context->remote_subkey);
krb5_free_keyblock(context, auth_context->local_subkey);
free (auth_context);
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setflags(krb5_context context,
krb5_auth_context auth_context,
int32_t flags)
{
auth_context->flags = flags;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getflags(krb5_context context,
krb5_auth_context auth_context,
int32_t *flags)
{
*flags = auth_context->flags;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_addflags(krb5_context context,
krb5_auth_context auth_context,
int32_t addflags,
int32_t *flags)
{
if (flags)
*flags = auth_context->flags;
auth_context->flags |= addflags;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_removeflags(krb5_context context,
krb5_auth_context auth_context,
int32_t removeflags,
int32_t *flags)
{
if (flags)
*flags = auth_context->flags;
auth_context->flags &= ~removeflags;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setaddrs(krb5_context context,
krb5_auth_context auth_context,
krb5_address *local_addr,
krb5_address *remote_addr)
{
if (local_addr) {
if (auth_context->local_address)
krb5_free_address (context, auth_context->local_address);
else
auth_context->local_address = malloc(sizeof(krb5_address));
krb5_copy_address(context, local_addr, auth_context->local_address);
}
if (remote_addr) {
if (auth_context->remote_address)
krb5_free_address (context, auth_context->remote_address);
else
auth_context->remote_address = malloc(sizeof(krb5_address));
krb5_copy_address(context, remote_addr, auth_context->remote_address);
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_genaddrs(krb5_context context,
krb5_auth_context auth_context,
int fd, int flags)
{
krb5_error_code ret;
krb5_address local_k_address, remote_k_address;
krb5_address *lptr = NULL, *rptr = NULL;
struct sockaddr_storage ss_local, ss_remote;
struct sockaddr *local = (struct sockaddr *)&ss_local;
struct sockaddr *remote = (struct sockaddr *)&ss_remote;
socklen_t len;
if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) {
if (auth_context->local_address == NULL) {
len = sizeof(ss_local);
if(getsockname(fd, local, &len) < 0) {
ret = errno;
krb5_set_error_string (context, "getsockname: %s",
strerror(ret));
goto out;
}
ret = krb5_sockaddr2address (context, local, &local_k_address);
if(ret) goto out;
if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) {
krb5_sockaddr2port (context, local, &auth_context->local_port);
} else
auth_context->local_port = 0;
lptr = &local_k_address;
}
}
if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) {
len = sizeof(ss_remote);
if(getpeername(fd, remote, &len) < 0) {
ret = errno;
krb5_set_error_string (context, "getpeername: %s", strerror(ret));
goto out;
}
ret = krb5_sockaddr2address (context, remote, &remote_k_address);
if(ret) goto out;
if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) {
krb5_sockaddr2port (context, remote, &auth_context->remote_port);
} else
auth_context->remote_port = 0;
rptr = &remote_k_address;
}
ret = krb5_auth_con_setaddrs (context,
auth_context,
lptr,
rptr);
out:
if (lptr)
krb5_free_address (context, lptr);
if (rptr)
krb5_free_address (context, rptr);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setaddrs_from_fd (krb5_context context,
krb5_auth_context auth_context,
void *p_fd)
{
int fd = *(int*)p_fd;
int flags = 0;
if(auth_context->local_address == NULL)
flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR;
if(auth_context->remote_address == NULL)
flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR;
return krb5_auth_con_genaddrs(context, auth_context, fd, flags);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getaddrs(krb5_context context,
krb5_auth_context auth_context,
krb5_address **local_addr,
krb5_address **remote_addr)
{
if(*local_addr)
krb5_free_address (context, *local_addr);
*local_addr = malloc (sizeof(**local_addr));
if (*local_addr == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
krb5_copy_address(context,
auth_context->local_address,
*local_addr);
if(*remote_addr)
krb5_free_address (context, *remote_addr);
*remote_addr = malloc (sizeof(**remote_addr));
if (*remote_addr == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
krb5_free_address (context, *local_addr);
*local_addr = NULL;
return ENOMEM;
}
krb5_copy_address(context,
auth_context->remote_address,
*remote_addr);
return 0;
}
static krb5_error_code
copy_key(krb5_context context,
krb5_keyblock *in,
krb5_keyblock **out)
{
if(in)
return krb5_copy_keyblock(context, in, out);
*out = NULL; /* is this right? */
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getkey(krb5_context context,
krb5_auth_context auth_context,
krb5_keyblock **keyblock)
{
return copy_key(context, auth_context->keyblock, keyblock);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getlocalsubkey(krb5_context context,
krb5_auth_context auth_context,
krb5_keyblock **keyblock)
{
return copy_key(context, auth_context->local_subkey, keyblock);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getremotesubkey(krb5_context context,
krb5_auth_context auth_context,
krb5_keyblock **keyblock)
{
return copy_key(context, auth_context->remote_subkey, keyblock);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setkey(krb5_context context,
krb5_auth_context auth_context,
krb5_keyblock *keyblock)
{
if(auth_context->keyblock)
krb5_free_keyblock(context, auth_context->keyblock);
return copy_key(context, keyblock, &auth_context->keyblock);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setlocalsubkey(krb5_context context,
krb5_auth_context auth_context,
krb5_keyblock *keyblock)
{
if(auth_context->local_subkey)
krb5_free_keyblock(context, auth_context->local_subkey);
return copy_key(context, keyblock, &auth_context->local_subkey);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_generatelocalsubkey(krb5_context context,
krb5_auth_context auth_context,
krb5_keyblock *key)
{
krb5_error_code ret;
krb5_keyblock *subkey;
ret = krb5_generate_subkey_extended (context, key,
auth_context->keytype,
&subkey);
if(ret)
return ret;
if(auth_context->local_subkey)
krb5_free_keyblock(context, auth_context->local_subkey);
auth_context->local_subkey = subkey;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setremotesubkey(krb5_context context,
krb5_auth_context auth_context,
krb5_keyblock *keyblock)
{
if(auth_context->remote_subkey)
krb5_free_keyblock(context, auth_context->remote_subkey);
return copy_key(context, keyblock, &auth_context->remote_subkey);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setcksumtype(krb5_context context,
krb5_auth_context auth_context,
krb5_cksumtype cksumtype)
{
auth_context->cksumtype = cksumtype;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getcksumtype(krb5_context context,
krb5_auth_context auth_context,
krb5_cksumtype *cksumtype)
{
*cksumtype = auth_context->cksumtype;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setkeytype (krb5_context context,
krb5_auth_context auth_context,
krb5_keytype keytype)
{
auth_context->keytype = keytype;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getkeytype (krb5_context context,
krb5_auth_context auth_context,
krb5_keytype *keytype)
{
*keytype = auth_context->keytype;
return 0;
}
#if 0
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setenctype(krb5_context context,
krb5_auth_context auth_context,
krb5_enctype etype)
{
if(auth_context->keyblock)
krb5_free_keyblock(context, auth_context->keyblock);
ALLOC(auth_context->keyblock, 1);
if(auth_context->keyblock == NULL)
return ENOMEM;
auth_context->keyblock->keytype = etype;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getenctype(krb5_context context,
krb5_auth_context auth_context,
krb5_enctype *etype)
{
krb5_abortx(context, "unimplemented krb5_auth_getenctype called");
}
#endif
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getlocalseqnumber(krb5_context context,
krb5_auth_context auth_context,
int32_t *seqnumber)
{
*seqnumber = auth_context->local_seqnumber;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setlocalseqnumber (krb5_context context,
krb5_auth_context auth_context,
int32_t seqnumber)
{
auth_context->local_seqnumber = seqnumber;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_getremoteseqnumber(krb5_context context,
krb5_auth_context auth_context,
int32_t *seqnumber)
{
*seqnumber = auth_context->remote_seqnumber;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setremoteseqnumber (krb5_context context,
krb5_auth_context auth_context,
int32_t seqnumber)
{
auth_context->remote_seqnumber = seqnumber;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getauthenticator(krb5_context context,
krb5_auth_context auth_context,
krb5_authenticator *authenticator)
{
*authenticator = malloc(sizeof(**authenticator));
if (*authenticator == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
copy_Authenticator(auth_context->authenticator,
*authenticator);
return 0;
}
void KRB5_LIB_FUNCTION
krb5_free_authenticator(krb5_context context,
krb5_authenticator *authenticator)
{
free_Authenticator (*authenticator);
free (*authenticator);
*authenticator = NULL;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setuserkey(krb5_context context,
krb5_auth_context auth_context,
krb5_keyblock *keyblock)
{
if(auth_context->keyblock)
krb5_free_keyblock(context, auth_context->keyblock);
return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_getrcache(krb5_context context,
krb5_auth_context auth_context,
krb5_rcache *rcache)
{
*rcache = auth_context->rcache;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setrcache(krb5_context context,
krb5_auth_context auth_context,
krb5_rcache rcache)
{
auth_context->rcache = rcache;
return 0;
}
#if 0 /* not implemented */
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_initivector(krb5_context context,
krb5_auth_context auth_context)
{
krb5_abortx(context, "unimplemented krb5_auth_con_initivector called");
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_setivector(krb5_context context,
krb5_auth_context auth_context,
krb5_pointer ivector)
{
krb5_abortx(context, "unimplemented krb5_auth_con_setivector called");
}
#endif /* not implemented */
@@ -0,0 +1,76 @@
/*
* Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: build_ap_req.c,v 1.20 2004/05/25 21:18:17 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_ap_req (krb5_context context,
krb5_enctype enctype,
krb5_creds *cred,
krb5_flags ap_options,
krb5_data authenticator,
krb5_data *retdata)
{
krb5_error_code ret = 0;
AP_REQ ap;
Ticket t;
size_t len;
ap.pvno = 5;
ap.msg_type = krb_ap_req;
memset(&ap.ap_options, 0, sizeof(ap.ap_options));
ap.ap_options.use_session_key = (ap_options & AP_OPTS_USE_SESSION_KEY) > 0;
ap.ap_options.mutual_required = (ap_options & AP_OPTS_MUTUAL_REQUIRED) > 0;
ap.ticket.tkt_vno = 5;
copy_Realm(&cred->server->realm, &ap.ticket.realm);
copy_PrincipalName(&cred->server->name, &ap.ticket.sname);
decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
copy_EncryptedData(&t.enc_part, &ap.ticket.enc_part);
free_Ticket(&t);
ap.authenticator.etype = enctype;
ap.authenticator.kvno = NULL;
ap.authenticator.cipher = authenticator;
ASN1_MALLOC_ENCODE(AP_REQ, retdata->data, retdata->length,
&ap, &len, ret);
if(ret == 0 && retdata->length != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
free_AP_REQ(&ap);
return ret;
}
+202
View File
@@ -0,0 +1,202 @@
/*
* Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: build_auth.c,v 1.43 2006/04/10 08:53:21 lha Exp $");
static krb5_error_code
make_etypelist(krb5_context context,
krb5_authdata **auth_data)
{
EtypeList etypes;
krb5_error_code ret;
krb5_authdata ad;
u_char *buf;
size_t len;
size_t buf_size;
ret = krb5_init_etype(context, &etypes.len, &etypes.val, NULL);
if (ret)
return ret;
ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret);
if (ret) {
free_EtypeList(&etypes);
return ret;
}
if(buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
free_EtypeList(&etypes);
ALLOC_SEQ(&ad, 1);
if (ad.val == NULL) {
free(buf);
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
ad.val[0].ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION;
ad.val[0].ad_data.length = len;
ad.val[0].ad_data.data = buf;
ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret);
if (ret) {
free_AuthorizationData(&ad);
return ret;
}
if(buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
free_AuthorizationData(&ad);
ALLOC(*auth_data, 1);
if (*auth_data == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
ALLOC_SEQ(*auth_data, 1);
if ((*auth_data)->val == NULL) {
free(buf);
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
(*auth_data)->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
(*auth_data)->val[0].ad_data.length = len;
(*auth_data)->val[0].ad_data.data = buf;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_authenticator (krb5_context context,
krb5_auth_context auth_context,
krb5_enctype enctype,
krb5_creds *cred,
Checksum *cksum,
Authenticator **auth_result,
krb5_data *result,
krb5_key_usage usage)
{
Authenticator *auth;
u_char *buf = NULL;
size_t buf_size;
size_t len;
krb5_error_code ret;
krb5_crypto crypto;
auth = calloc(1, sizeof(*auth));
if (auth == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
auth->authenticator_vno = 5;
copy_Realm(&cred->client->realm, &auth->crealm);
copy_PrincipalName(&cred->client->name, &auth->cname);
krb5_us_timeofday (context, &auth->ctime, &auth->cusec);
ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey);
if(ret)
goto fail;
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
if(auth_context->local_seqnumber == 0)
krb5_generate_seq_number (context,
&cred->session,
&auth_context->local_seqnumber);
ALLOC(auth->seq_number, 1);
if(auth->seq_number == NULL) {
ret = ENOMEM;
goto fail;
}
*auth->seq_number = auth_context->local_seqnumber;
} else
auth->seq_number = NULL;
auth->authorization_data = NULL;
auth->cksum = cksum;
if (cksum != NULL && cksum->cksumtype == CKSUMTYPE_GSSAPI) {
/*
* This is not GSS-API specific, we only enable it for
* GSS for now
*/
ret = make_etypelist(context, &auth->authorization_data);
if (ret)
goto fail;
}
/* XXX - Copy more to auth_context? */
auth_context->authenticator->ctime = auth->ctime;
auth_context->authenticator->cusec = auth->cusec;
ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret);
if (ret)
goto fail;
if(buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
ret = krb5_crypto_init(context, &cred->session, enctype, &crypto);
if (ret)
goto fail;
ret = krb5_encrypt (context,
crypto,
usage /* KRB5_KU_AP_REQ_AUTH */,
buf + buf_size - len,
len,
result);
krb5_crypto_destroy(context, crypto);
if (ret)
goto fail;
free (buf);
if (auth_result)
*auth_result = auth;
else {
/* Don't free the `cksum', it's allocated by the caller */
auth->cksum = NULL;
free_Authenticator (auth);
free (auth);
}
return ret;
fail:
free_Authenticator (auth);
free (auth);
free (buf);
return ret;
}
+863
View File
@@ -0,0 +1,863 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: cache.c,v 1.82 2006/09/12 17:35:33 lha Exp $");
/*
* Add a new ccache type with operations `ops', overwriting any
* existing one if `override'.
* Return an error code or 0.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_register(krb5_context context,
const krb5_cc_ops *ops,
krb5_boolean override)
{
int i;
for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) {
if(strcmp(context->cc_ops[i].prefix, ops->prefix) == 0) {
if(!override) {
krb5_set_error_string(context,
"ccache type %s already exists",
ops->prefix);
return KRB5_CC_TYPE_EXISTS;
}
break;
}
}
if(i == context->num_cc_ops) {
krb5_cc_ops *o = realloc(context->cc_ops,
(context->num_cc_ops + 1) *
sizeof(*context->cc_ops));
if(o == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
context->num_cc_ops++;
context->cc_ops = o;
memset(context->cc_ops + i, 0,
(context->num_cc_ops - i) * sizeof(*context->cc_ops));
}
memcpy(&context->cc_ops[i], ops, sizeof(context->cc_ops[i]));
return 0;
}
/*
* Allocate the memory for a `id' and the that function table to
* `ops'. Returns 0 or and error code.
*/
krb5_error_code
_krb5_cc_allocate(krb5_context context,
const krb5_cc_ops *ops,
krb5_ccache *id)
{
krb5_ccache p;
p = malloc (sizeof(*p));
if(p == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
p->ops = ops;
*id = p;
return 0;
}
/*
* Allocate memory for a new ccache in `id' with operations `ops'
* and name `residual'.
* Return 0 or an error code.
*/
static krb5_error_code
allocate_ccache (krb5_context context,
const krb5_cc_ops *ops,
const char *residual,
krb5_ccache *id)
{
krb5_error_code ret;
ret = _krb5_cc_allocate(context, ops, id);
if (ret)
return ret;
ret = (*id)->ops->resolve(context, id, residual);
if(ret)
free(*id);
return ret;
}
/*
* Find and allocate a ccache in `id' from the specification in `residual'.
* If the ccache name doesn't contain any colon, interpret it as a file name.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_resolve(krb5_context context,
const char *name,
krb5_ccache *id)
{
int i;
for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) {
size_t prefix_len = strlen(context->cc_ops[i].prefix);
if(strncmp(context->cc_ops[i].prefix, name, prefix_len) == 0
&& name[prefix_len] == ':') {
return allocate_ccache (context, &context->cc_ops[i],
name + prefix_len + 1,
id);
}
}
if (strchr (name, ':') == NULL)
return allocate_ccache (context, &krb5_fcc_ops, name, id);
else {
krb5_set_error_string(context, "unknown ccache type %s", name);
return KRB5_CC_UNKNOWN_TYPE;
}
}
/*
* Generate a new ccache of type `ops' in `id'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_gen_new(krb5_context context,
const krb5_cc_ops *ops,
krb5_ccache *id)
{
krb5_error_code ret;
ret = _krb5_cc_allocate(context, ops, id);
if (ret)
return ret;
return (*id)->ops->gen_new(context, id);
}
/*
* Generates a new unique ccache of `type` in `id'. If `type' is NULL,
* the library chooses the default credential cache type. The supplied
* `hint' (that can be NULL) is a string that the credential cache
* type can use to base the name of the credential on, this is to make
* its easier for the user to differentiate the credentials.
*
* Returns 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_new_unique(krb5_context context, const char *type,
const char *hint, krb5_ccache *id)
{
const krb5_cc_ops *ops;
if (type == NULL)
type = KRB5_DEFAULT_CCNAME;
ops = krb5_cc_get_prefix_ops(context, type);
if (ops == NULL) {
krb5_set_error_string(context, "Credential cache type %s is unknown",
type);
return KRB5_CC_UNKNOWN_TYPE;
}
return krb5_cc_gen_new(context, ops, id);
}
/*
* Return the name of the ccache `id'
*/
const char* KRB5_LIB_FUNCTION
krb5_cc_get_name(krb5_context context,
krb5_ccache id)
{
return id->ops->get_name(context, id);
}
/*
* Return the type of the ccache `id'.
*/
const char* KRB5_LIB_FUNCTION
krb5_cc_get_type(krb5_context context,
krb5_ccache id)
{
return id->ops->prefix;
}
/*
* Return the complete resolvable name the ccache `id' in `str´.
* `str` should be freed with free(3).
* Returns 0 or an error (and then *str is set to NULL).
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_get_full_name(krb5_context context,
krb5_ccache id,
char **str)
{
const char *type, *name;
*str = NULL;
type = krb5_cc_get_type(context, id);
if (type == NULL) {
krb5_set_error_string(context, "cache have no name of type");
return KRB5_CC_UNKNOWN_TYPE;
}
name = krb5_cc_get_name(context, id);
if (name == NULL) {
krb5_set_error_string(context, "cache of type %s have no name", type);
return KRB5_CC_BADNAME;
}
if (asprintf(str, "%s:%s", type, name) == -1) {
krb5_set_error_string(context, "malloc - out of memory");
*str = NULL;
return ENOMEM;
}
return 0;
}
/*
* Return krb5_cc_ops of a the ccache `id'.
*/
const krb5_cc_ops *
krb5_cc_get_ops(krb5_context context, krb5_ccache id)
{
return id->ops;
}
/*
* Expand variables in `str' into `res'
*/
krb5_error_code
_krb5_expand_default_cc_name(krb5_context context, const char *str, char **res)
{
size_t tlen, len = 0;
char *tmp, *tmp2, *append;
*res = NULL;
while (str && *str) {
tmp = strstr(str, "%{");
if (tmp && tmp != str) {
append = malloc((tmp - str) + 1);
if (append) {
memcpy(append, str, tmp - str);
append[tmp - str] = '\0';
}
str = tmp;
} else if (tmp) {
tmp2 = strchr(tmp, '}');
if (tmp2 == NULL) {
free(*res);
*res = NULL;
krb5_set_error_string(context, "variable missing }");
return KRB5_CONFIG_BADFORMAT;
}
if (strncasecmp(tmp, "%{uid}", 6) == 0)
asprintf(&append, "%u", (unsigned)getuid());
else if (strncasecmp(tmp, "%{null}", 7) == 0)
append = strdup("");
else {
free(*res);
*res = NULL;
krb5_set_error_string(context,
"expand default cache unknown "
"variable \"%.*s\"",
(int)(tmp2 - tmp) - 2, tmp + 2);
return KRB5_CONFIG_BADFORMAT;
}
str = tmp2 + 1;
} else {
append = strdup(str);
str = NULL;
}
if (append == NULL) {
free(*res);
*res = NULL;
krb5_set_error_string(context, "malloc - out of memory");
return ENOMEM;
}
tlen = strlen(append);
tmp = realloc(*res, len + tlen + 1);
if (tmp == NULL) {
free(append);
free(*res);
*res = NULL;
krb5_set_error_string(context, "malloc - out of memory");
return ENOMEM;
}
*res = tmp;
memcpy(*res + len, append, tlen + 1);
len = len + tlen;
free(append);
}
return 0;
}
/*
* Set the default cc name for `context' to `name'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_set_default_name(krb5_context context, const char *name)
{
krb5_error_code ret = 0;
char *p;
if (name == NULL) {
const char *e = NULL;
if(!issuid()) {
e = getenv("KRB5CCNAME");
if (e)
p = strdup(e);
}
if (e == NULL) {
e = krb5_config_get_string(context, NULL, "libdefaults",
"default_cc_name", NULL);
if (e == NULL)
e = KRB5_DEFAULT_CCNAME;
ret = _krb5_expand_default_cc_name(context, e, &p);
if (ret)
return ret;
}
} else
p = strdup(name);
if (p == NULL) {
krb5_set_error_string(context, "malloc - out of memory");
return ENOMEM;
}
if (context->default_cc_name)
free(context->default_cc_name);
context->default_cc_name = p;
return ret;
}
/*
* Return a pointer to a context static string containing the default
* ccache name.
*/
const char* KRB5_LIB_FUNCTION
krb5_cc_default_name(krb5_context context)
{
if (context->default_cc_name == NULL)
krb5_cc_set_default_name(context, NULL);
return context->default_cc_name;
}
/*
* Open the default ccache in `id'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_default(krb5_context context,
krb5_ccache *id)
{
const char *p = krb5_cc_default_name(context);
if (p == NULL) {
krb5_set_error_string(context, "malloc - out of memory");
return ENOMEM;
}
return krb5_cc_resolve(context, p, id);
}
/*
* Create a new ccache in `id' for `primary_principal'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_initialize(krb5_context context,
krb5_ccache id,
krb5_principal primary_principal)
{
return (*id->ops->init)(context, id, primary_principal);
}
/*
* Remove the ccache `id'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_destroy(krb5_context context,
krb5_ccache id)
{
krb5_error_code ret;
ret = (*id->ops->destroy)(context, id);
krb5_cc_close (context, id);
return ret;
}
/*
* Stop using the ccache `id' and free the related resources.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_close(krb5_context context,
krb5_ccache id)
{
krb5_error_code ret;
ret = (*id->ops->close)(context, id);
free(id);
return ret;
}
/*
* Store `creds' in the ccache `id'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_store_cred(krb5_context context,
krb5_ccache id,
krb5_creds *creds)
{
return (*id->ops->store)(context, id, creds);
}
/*
* Retrieve the credential identified by `mcreds' (and `whichfields')
* from `id' in `creds'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_retrieve_cred(krb5_context context,
krb5_ccache id,
krb5_flags whichfields,
const krb5_creds *mcreds,
krb5_creds *creds)
{
krb5_error_code ret;
krb5_cc_cursor cursor;
if (id->ops->retrieve != NULL) {
return (*id->ops->retrieve)(context, id, whichfields,
mcreds, creds);
}
krb5_cc_start_seq_get(context, id, &cursor);
while((ret = krb5_cc_next_cred(context, id, &cursor, creds)) == 0){
if(krb5_compare_creds(context, whichfields, mcreds, creds)){
ret = 0;
break;
}
krb5_free_cred_contents (context, creds);
}
krb5_cc_end_seq_get(context, id, &cursor);
return ret;
}
/*
* Return the principal of `id' in `principal'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_get_principal(krb5_context context,
krb5_ccache id,
krb5_principal *principal)
{
return (*id->ops->get_princ)(context, id, principal);
}
/*
* Start iterating over `id', `cursor' is initialized to the
* beginning.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_start_seq_get (krb5_context context,
const krb5_ccache id,
krb5_cc_cursor *cursor)
{
return (*id->ops->get_first)(context, id, cursor);
}
/*
* Retrieve the next cred pointed to by (`id', `cursor') in `creds'
* and advance `cursor'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_next_cred (krb5_context context,
const krb5_ccache id,
krb5_cc_cursor *cursor,
krb5_creds *creds)
{
return (*id->ops->get_next)(context, id, cursor, creds);
}
/* like krb5_cc_next_cred, but allow for selective retrieval */
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_next_cred_match(krb5_context context,
const krb5_ccache id,
krb5_cc_cursor * cursor,
krb5_creds * creds,
krb5_flags whichfields,
const krb5_creds * mcreds)
{
krb5_error_code ret;
while (1) {
ret = krb5_cc_next_cred(context, id, cursor, creds);
if (ret)
return ret;
if (mcreds == NULL || krb5_compare_creds(context, whichfields, mcreds, creds))
return 0;
krb5_free_cred_contents(context, creds);
}
}
/*
* Destroy the cursor `cursor'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_end_seq_get (krb5_context context,
const krb5_ccache id,
krb5_cc_cursor *cursor)
{
return (*id->ops->end_get)(context, id, cursor);
}
/*
* Remove the credential identified by `cred', `which' from `id'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_remove_cred(krb5_context context,
krb5_ccache id,
krb5_flags which,
krb5_creds *cred)
{
if(id->ops->remove_cred == NULL) {
krb5_set_error_string(context,
"ccache %s does not support remove_cred",
id->ops->prefix);
return EACCES; /* XXX */
}
return (*id->ops->remove_cred)(context, id, which, cred);
}
/*
* Set the flags of `id' to `flags'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_set_flags(krb5_context context,
krb5_ccache id,
krb5_flags flags)
{
return (*id->ops->set_flags)(context, id, flags);
}
/*
* Copy the contents of `from' to `to'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_copy_cache_match(krb5_context context,
const krb5_ccache from,
krb5_ccache to,
krb5_flags whichfields,
const krb5_creds * mcreds,
unsigned int *matched)
{
krb5_error_code ret;
krb5_cc_cursor cursor;
krb5_creds cred;
krb5_principal princ;
ret = krb5_cc_get_principal(context, from, &princ);
if (ret)
return ret;
ret = krb5_cc_initialize(context, to, princ);
if (ret) {
krb5_free_principal(context, princ);
return ret;
}
ret = krb5_cc_start_seq_get(context, from, &cursor);
if (ret) {
krb5_free_principal(context, princ);
return ret;
}
if (matched)
*matched = 0;
while (ret == 0 &&
krb5_cc_next_cred_match(context, from, &cursor, &cred,
whichfields, mcreds) == 0) {
if (matched)
(*matched)++;
ret = krb5_cc_store_cred(context, to, &cred);
krb5_free_cred_contents(context, &cred);
}
krb5_cc_end_seq_get(context, from, &cursor);
krb5_free_principal(context, princ);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_copy_cache(krb5_context context,
const krb5_ccache from,
krb5_ccache to)
{
return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL);
}
/*
* Return the version of `id'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_get_version(krb5_context context,
const krb5_ccache id)
{
if(id->ops->get_version)
return (*id->ops->get_version)(context, id);
else
return 0;
}
/*
* Clear `mcreds' so it can be used with krb5_cc_retrieve_cred
*/
void KRB5_LIB_FUNCTION
krb5_cc_clear_mcred(krb5_creds *mcred)
{
memset(mcred, 0, sizeof(*mcred));
}
/*
* Get the cc ops that is registered in `context' to handle the
* `prefix'. `prefix' can be a complete credential cache name or a
* prefix, the function will only use part up to the first colon (:)
* if there is one. Returns NULL if ops not found.
*/
const krb5_cc_ops *
krb5_cc_get_prefix_ops(krb5_context context, const char *prefix)
{
char *p, *p1;
int i;
if (prefix[0] == '/')
return &krb5_fcc_ops;
p = strdup(prefix);
if (p == NULL) {
krb5_set_error_string(context, "malloc - out of memory");
return NULL;
}
p1 = strchr(p, ':');
if (p1)
*p1 = '\0';
for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) {
if(strcmp(context->cc_ops[i].prefix, p) == 0) {
free(p);
return &context->cc_ops[i];
}
}
free(p);
return NULL;
}
struct krb5_cc_cache_cursor_data {
const krb5_cc_ops *ops;
krb5_cc_cursor cursor;
};
/*
* Start iterating over all caches of `type'. If `type' is NULL, the
* default type is * used. `cursor' is initialized to the beginning.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_cache_get_first (krb5_context context,
const char *type,
krb5_cc_cache_cursor *cursor)
{
const krb5_cc_ops *ops;
krb5_error_code ret;
if (type == NULL)
type = krb5_cc_default_name(context);
ops = krb5_cc_get_prefix_ops(context, type);
if (ops == NULL) {
krb5_set_error_string(context, "Unknown type \"%s\" when iterating "
"trying to iterate the credential caches", type);
return KRB5_CC_UNKNOWN_TYPE;
}
if (ops->get_cache_first == NULL) {
krb5_set_error_string(context, "Credential cache type %s doesn't support "
"iterations over caches", ops->prefix);
return KRB5_CC_NOSUPP;
}
*cursor = calloc(1, sizeof(**cursor));
if (*cursor == NULL) {
krb5_set_error_string(context, "malloc - out of memory");
return ENOMEM;
}
(*cursor)->ops = ops;
ret = ops->get_cache_first(context, &(*cursor)->cursor);
if (ret) {
free(*cursor);
*cursor = NULL;
}
return ret;
}
/*
* Retrieve the next cache pointed to by (`cursor') in `id'
* and advance `cursor'.
* Return 0 or an error code.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_cache_next (krb5_context context,
krb5_cc_cache_cursor cursor,
krb5_ccache *id)
{
return cursor->ops->get_cache_next(context, cursor->cursor, id);
}
/*
* Destroy the cursor `cursor'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_cache_end_seq_get (krb5_context context,
krb5_cc_cache_cursor cursor)
{
krb5_error_code ret;
ret = cursor->ops->end_cache_get(context, cursor->cursor);
cursor->ops = NULL;
free(cursor);
return ret;
}
/*
* Search for a matching credential cache of type `type' that have the
* `principal' as the default principal. If NULL is used for `type',
* the default type is used. On success, `id' needs to be freed with
* krb5_cc_close or krb5_cc_destroy. On failure, error code is
* returned and `id' is set to NULL.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_cc_cache_match (krb5_context context,
krb5_principal client,
const char *type,
krb5_ccache *id)
{
krb5_cc_cache_cursor cursor;
krb5_error_code ret;
krb5_ccache cache = NULL;
*id = NULL;
ret = krb5_cc_cache_get_first (context, type, &cursor);
if (ret)
return ret;
while ((ret = krb5_cc_cache_next (context, cursor, &cache)) == 0) {
krb5_principal principal;
ret = krb5_cc_get_principal(context, cache, &principal);
if (ret == 0) {
krb5_boolean match;
match = krb5_principal_compare(context, principal, client);
krb5_free_principal(context, principal);
if (match)
break;
}
krb5_cc_close(context, cache);
cache = NULL;
}
krb5_cc_cache_end_seq_get(context, cursor);
if (cache == NULL) {
char *str;
krb5_unparse_name(context, client, &str);
krb5_set_error_string(context, "Principal %s not found in a "
"credential cache", str ? str : "<out of memory>");
if (str)
free(str);
return KRB5_CC_NOTFOUND;
}
*id = cache;
return 0;
}
+821
View File
@@ -0,0 +1,821 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: changepw.c,v 1.56 2006/05/05 09:26:47 lha Exp $");
static void
str2data (krb5_data *d,
const char *fmt,
...) __attribute__ ((format (printf, 2, 3)));
static void
str2data (krb5_data *d,
const char *fmt,
...)
{
va_list args;
va_start(args, fmt);
d->length = vasprintf ((char **)&d->data, fmt, args);
va_end(args);
}
/*
* Change password protocol defined by
* draft-ietf-cat-kerb-chg-password-02.txt
*
* Share the response part of the protocol with MS set password
* (RFC3244)
*/
static krb5_error_code
chgpw_send_request (krb5_context context,
krb5_auth_context *auth_context,
krb5_creds *creds,
krb5_principal targprinc,
int is_stream,
int sock,
const char *passwd,
const char *host)
{
krb5_error_code ret;
krb5_data ap_req_data;
krb5_data krb_priv_data;
krb5_data passwd_data;
size_t len;
u_char header[6];
u_char *p;
struct iovec iov[3];
struct msghdr msghdr;
if (is_stream)
return KRB5_KPASSWD_MALFORMED;
if (targprinc &&
krb5_principal_compare(context, creds->client, targprinc) != TRUE)
return KRB5_KPASSWD_MALFORMED;
krb5_data_zero (&ap_req_data);
ret = krb5_mk_req_extended (context,
auth_context,
AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
NULL, /* in_data */
creds,
&ap_req_data);
if (ret)
return ret;
passwd_data.data = rk_UNCONST(passwd);
passwd_data.length = strlen(passwd);
krb5_data_zero (&krb_priv_data);
ret = krb5_mk_priv (context,
*auth_context,
&passwd_data,
&krb_priv_data,
NULL);
if (ret)
goto out2;
len = 6 + ap_req_data.length + krb_priv_data.length;
p = header;
*p++ = (len >> 8) & 0xFF;
*p++ = (len >> 0) & 0xFF;
*p++ = 0;
*p++ = 1;
*p++ = (ap_req_data.length >> 8) & 0xFF;
*p++ = (ap_req_data.length >> 0) & 0xFF;
memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_name = NULL;
msghdr.msg_namelen = 0;
msghdr.msg_iov = iov;
msghdr.msg_iovlen = sizeof(iov)/sizeof(*iov);
#if 0
msghdr.msg_control = NULL;
msghdr.msg_controllen = 0;
#endif
iov[0].iov_base = (void*)header;
iov[0].iov_len = 6;
iov[1].iov_base = ap_req_data.data;
iov[1].iov_len = ap_req_data.length;
iov[2].iov_base = krb_priv_data.data;
iov[2].iov_len = krb_priv_data.length;
if (sendmsg (sock, &msghdr, 0) < 0) {
ret = errno;
krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret));
}
krb5_data_free (&krb_priv_data);
out2:
krb5_data_free (&ap_req_data);
return ret;
}
/*
* Set password protocol as defined by RFC3244 --
* Microsoft Windows 2000 Kerberos Change Password and Set Password Protocols
*/
static krb5_error_code
setpw_send_request (krb5_context context,
krb5_auth_context *auth_context,
krb5_creds *creds,
krb5_principal targprinc,
int is_stream,
int sock,
const char *passwd,
const char *host)
{
krb5_error_code ret;
krb5_data ap_req_data;
krb5_data krb_priv_data;
krb5_data pwd_data;
ChangePasswdDataMS chpw;
size_t len;
u_char header[4 + 6];
u_char *p;
struct iovec iov[3];
struct msghdr msghdr;
krb5_data_zero (&ap_req_data);
ret = krb5_mk_req_extended (context,
auth_context,
AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
NULL, /* in_data */
creds,
&ap_req_data);
if (ret)
return ret;
chpw.newpasswd.length = strlen(passwd);
chpw.newpasswd.data = rk_UNCONST(passwd);
if (targprinc) {
chpw.targname = &targprinc->name;
chpw.targrealm = &targprinc->realm;
} else {
chpw.targname = NULL;
chpw.targrealm = NULL;
}
ASN1_MALLOC_ENCODE(ChangePasswdDataMS, pwd_data.data, pwd_data.length,
&chpw, &len, ret);
if (ret) {
krb5_data_free (&ap_req_data);
return ret;
}
if(pwd_data.length != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
ret = krb5_mk_priv (context,
*auth_context,
&pwd_data,
&krb_priv_data,
NULL);
if (ret)
goto out2;
len = 6 + ap_req_data.length + krb_priv_data.length;
p = header;
if (is_stream) {
_krb5_put_int(p, len, 4);
p += 4;
}
*p++ = (len >> 8) & 0xFF;
*p++ = (len >> 0) & 0xFF;
*p++ = 0xff;
*p++ = 0x80;
*p++ = (ap_req_data.length >> 8) & 0xFF;
*p++ = (ap_req_data.length >> 0) & 0xFF;
memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_name = NULL;
msghdr.msg_namelen = 0;
msghdr.msg_iov = iov;
msghdr.msg_iovlen = sizeof(iov)/sizeof(*iov);
#if 0
msghdr.msg_control = NULL;
msghdr.msg_controllen = 0;
#endif
iov[0].iov_base = (void*)header;
if (is_stream)
iov[0].iov_len = 10;
else
iov[0].iov_len = 6;
iov[1].iov_base = ap_req_data.data;
iov[1].iov_len = ap_req_data.length;
iov[2].iov_base = krb_priv_data.data;
iov[2].iov_len = krb_priv_data.length;
if (sendmsg (sock, &msghdr, 0) < 0) {
ret = errno;
krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret));
}
krb5_data_free (&krb_priv_data);
out2:
krb5_data_free (&ap_req_data);
krb5_data_free (&pwd_data);
return ret;
}
static krb5_error_code
process_reply (krb5_context context,
krb5_auth_context auth_context,
int is_stream,
int sock,
int *result_code,
krb5_data *result_code_string,
krb5_data *result_string,
const char *host)
{
krb5_error_code ret;
u_char reply[1024 * 3];
ssize_t len;
uint16_t pkt_len, pkt_ver;
krb5_data ap_rep_data;
int save_errno;
len = 0;
if (is_stream) {
while (len < sizeof(reply)) {
unsigned long size;
ret = recvfrom (sock, reply + len, sizeof(reply) - len,
0, NULL, NULL);
if (ret < 0) {
save_errno = errno;
krb5_set_error_string(context, "recvfrom %s: %s",
host, strerror(save_errno));
return save_errno;
} else if (ret == 0) {
krb5_set_error_string(context, "recvfrom timeout %s", host);
return 1;
}
len += ret;
if (len < 4)
continue;
_krb5_get_int(reply, &size, 4);
if (size + 4 < len)
continue;
memmove(reply, reply + 4, size);
len = size;
break;
}
if (len == sizeof(reply)) {
krb5_set_error_string(context, "message too large from %s",
host);
return ENOMEM;
}
} else {
ret = recvfrom (sock, reply, sizeof(reply), 0, NULL, NULL);
if (ret < 0) {
save_errno = errno;
krb5_set_error_string(context, "recvfrom %s: %s",
host, strerror(save_errno));
return save_errno;
}
len = ret;
}
if (len < 6) {
str2data (result_string, "server %s sent to too short message "
"(%ld bytes)", host, (long)len);
*result_code = KRB5_KPASSWD_MALFORMED;
return 0;
}
pkt_len = (reply[0] << 8) | (reply[1]);
pkt_ver = (reply[2] << 8) | (reply[3]);
if ((pkt_len != len) || (reply[1] == 0x7e || reply[1] == 0x5e)) {
KRB_ERROR error;
size_t size;
u_char *p;
memset(&error, 0, sizeof(error));
ret = decode_KRB_ERROR(reply, len, &error, &size);
if (ret)
return ret;
if (error.e_data->length < 2) {
str2data(result_string, "server %s sent too short "
"e_data to print anything usable", host);
free_KRB_ERROR(&error);
*result_code = KRB5_KPASSWD_MALFORMED;
return 0;
}
p = error.e_data->data;
*result_code = (p[0] << 8) | p[1];
if (error.e_data->length == 2)
str2data(result_string, "server only sent error code");
else
krb5_data_copy (result_string,
p + 2,
error.e_data->length - 2);
free_KRB_ERROR(&error);
return 0;
}
if (pkt_len != len) {
str2data (result_string, "client: wrong len in reply");
*result_code = KRB5_KPASSWD_MALFORMED;
return 0;
}
if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW) {
str2data (result_string,
"client: wrong version number (%d)", pkt_ver);
*result_code = KRB5_KPASSWD_MALFORMED;
return 0;
}
ap_rep_data.data = reply + 6;
ap_rep_data.length = (reply[4] << 8) | (reply[5]);
if (reply + len < (u_char *)ap_rep_data.data + ap_rep_data.length) {
str2data (result_string, "client: wrong AP len in reply");
*result_code = KRB5_KPASSWD_MALFORMED;
return 0;
}
if (ap_rep_data.length) {
krb5_ap_rep_enc_part *ap_rep;
krb5_data priv_data;
u_char *p;
priv_data.data = (u_char*)ap_rep_data.data + ap_rep_data.length;
priv_data.length = len - ap_rep_data.length - 6;
ret = krb5_rd_rep (context,
auth_context,
&ap_rep_data,
&ap_rep);
if (ret)
return ret;
krb5_free_ap_rep_enc_part (context, ap_rep);
ret = krb5_rd_priv (context,
auth_context,
&priv_data,
result_code_string,
NULL);
if (ret) {
krb5_data_free (result_code_string);
return ret;
}
if (result_code_string->length < 2) {
*result_code = KRB5_KPASSWD_MALFORMED;
str2data (result_string,
"client: bad length in result");
return 0;
}
p = result_code_string->data;
*result_code = (p[0] << 8) | p[1];
krb5_data_copy (result_string,
(unsigned char*)result_code_string->data + 2,
result_code_string->length - 2);
return 0;
} else {
KRB_ERROR error;
size_t size;
u_char *p;
ret = decode_KRB_ERROR(reply + 6, len - 6, &error, &size);
if (ret) {
return ret;
}
if (error.e_data->length < 2) {
krb5_warnx (context, "too short e_data to print anything usable");
return 1; /* XXX */
}
p = error.e_data->data;
*result_code = (p[0] << 8) | p[1];
krb5_data_copy (result_string,
p + 2,
error.e_data->length - 2);
return 0;
}
}
/*
* change the password using the credentials in `creds' (for the
* principal indicated in them) to `newpw', storing the result of
* the operation in `result_*' and an error code or 0.
*/
typedef krb5_error_code (*kpwd_send_request) (krb5_context,
krb5_auth_context *,
krb5_creds *,
krb5_principal,
int,
int,
const char *,
const char *);
typedef krb5_error_code (*kpwd_process_reply) (krb5_context,
krb5_auth_context,
int,
int,
int *,
krb5_data *,
krb5_data *,
const char *);
static struct kpwd_proc {
const char *name;
int flags;
#define SUPPORT_TCP 1
#define SUPPORT_UDP 2
kpwd_send_request send_req;
kpwd_process_reply process_rep;
} procs[] = {
{
"MS set password",
SUPPORT_TCP|SUPPORT_UDP,
setpw_send_request,
process_reply
},
{
"change password",
SUPPORT_UDP,
chgpw_send_request,
process_reply
},
{ NULL }
};
static struct kpwd_proc *
find_chpw_proto(const char *name)
{
struct kpwd_proc *p;
for (p = procs; p->name != NULL; p++) {
if (strcmp(p->name, name) == 0)
return p;
}
return NULL;
}
/*
*
*/
static krb5_error_code
change_password_loop (krb5_context context,
krb5_creds *creds,
krb5_principal targprinc,
const char *newpw,
int *result_code,
krb5_data *result_code_string,
krb5_data *result_string,
struct kpwd_proc *proc)
{
krb5_error_code ret;
krb5_auth_context auth_context = NULL;
krb5_krbhst_handle handle = NULL;
krb5_krbhst_info *hi;
int sock;
int i;
int done = 0;
krb5_realm realm;
if (targprinc)
realm = targprinc->realm;
else
realm = creds->client->realm;
ret = krb5_auth_con_init (context, &auth_context);
if (ret)
return ret;
krb5_auth_con_setflags (context, auth_context,
KRB5_AUTH_CONTEXT_DO_SEQUENCE);
ret = krb5_krbhst_init (context, realm, KRB5_KRBHST_CHANGEPW, &handle);
if (ret)
goto out;
while (!done && (ret = krb5_krbhst_next(context, handle, &hi)) == 0) {
struct addrinfo *ai, *a;
int is_stream;
switch (hi->proto) {
case KRB5_KRBHST_UDP:
if ((proc->flags & SUPPORT_UDP) == 0)
continue;
is_stream = 0;
break;
case KRB5_KRBHST_TCP:
if ((proc->flags & SUPPORT_TCP) == 0)
continue;
is_stream = 1;
break;
default:
continue;
}
ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
if (ret)
continue;
for (a = ai; !done && a != NULL; a = a->ai_next) {
int replied = 0;
sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
if (sock < 0)
continue;
ret = connect(sock, a->ai_addr, a->ai_addrlen);
if (ret < 0) {
close (sock);
goto out;
}
ret = krb5_auth_con_genaddrs (context, auth_context, sock,
KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR);
if (ret) {
close (sock);
goto out;
}
for (i = 0; !done && i < 5; ++i) {
fd_set fdset;
struct timeval tv;
if (!replied) {
replied = 0;
ret = (*proc->send_req) (context,
&auth_context,
creds,
targprinc,
is_stream,
sock,
newpw,
hi->hostname);
if (ret) {
close(sock);
goto out;
}
}
if (sock >= FD_SETSIZE) {
krb5_set_error_string(context, "fd %d too large", sock);
ret = ERANGE;
close (sock);
goto out;
}
FD_ZERO(&fdset);
FD_SET(sock, &fdset);
tv.tv_usec = 0;
tv.tv_sec = 1 + (1 << i);
ret = select (sock + 1, &fdset, NULL, NULL, &tv);
if (ret < 0 && errno != EINTR) {
close(sock);
goto out;
}
if (ret == 1) {
ret = (*proc->process_rep) (context,
auth_context,
is_stream,
sock,
result_code,
result_code_string,
result_string,
hi->hostname);
if (ret == 0)
done = 1;
else if (i > 0 && ret == KRB5KRB_AP_ERR_MUT_FAIL)
replied = 1;
} else {
ret = KRB5_KDC_UNREACH;
}
}
close (sock);
}
}
out:
krb5_krbhst_free (context, handle);
krb5_auth_con_free (context, auth_context);
if (done)
return 0;
else {
if (ret == KRB5_KDC_UNREACH) {
krb5_set_error_string(context,
"unable to reach any changepw server "
" in realm %s", realm);
*result_code = KRB5_KPASSWD_HARDERROR;
}
return ret;
}
}
/*
* change the password using the credentials in `creds' (for the
* principal indicated in them) to `newpw', storing the result of
* the operation in `result_*' and an error code or 0.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_change_password (krb5_context context,
krb5_creds *creds,
const char *newpw,
int *result_code,
krb5_data *result_code_string,
krb5_data *result_string)
{
struct kpwd_proc *p = find_chpw_proto("change password");
*result_code = KRB5_KPASSWD_MALFORMED;
result_code_string->data = result_string->data = NULL;
result_code_string->length = result_string->length = 0;
if (p == NULL)
return KRB5_KPASSWD_MALFORMED;
return change_password_loop(context, creds, NULL, newpw,
result_code, result_code_string,
result_string, p);
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_password(krb5_context context,
krb5_creds *creds,
const char *newpw,
krb5_principal targprinc,
int *result_code,
krb5_data *result_code_string,
krb5_data *result_string)
{
krb5_principal principal = NULL;
krb5_error_code ret = 0;
int i;
*result_code = KRB5_KPASSWD_MALFORMED;
result_code_string->data = result_string->data = NULL;
result_code_string->length = result_string->length = 0;
if (targprinc == NULL) {
ret = krb5_get_default_principal(context, &principal);
if (ret)
return ret;
} else
principal = targprinc;
for (i = 0; procs[i].name != NULL; i++) {
*result_code = 0;
ret = change_password_loop(context, creds, principal, newpw,
result_code, result_code_string,
result_string,
&procs[i]);
if (ret == 0 && *result_code == 0)
break;
}
if (targprinc == NULL)
krb5_free_principal(context, principal);
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_password_using_ccache(krb5_context context,
krb5_ccache ccache,
const char *newpw,
krb5_principal targprinc,
int *result_code,
krb5_data *result_code_string,
krb5_data *result_string)
{
krb5_creds creds, *credsp;
krb5_error_code ret;
krb5_principal principal = NULL;
*result_code = KRB5_KPASSWD_MALFORMED;
result_code_string->data = result_string->data = NULL;
result_code_string->length = result_string->length = 0;
memset(&creds, 0, sizeof(creds));
if (targprinc == NULL) {
ret = krb5_cc_get_principal(context, ccache, &principal);
if (ret)
return ret;
} else
principal = targprinc;
ret = krb5_make_principal(context, &creds.server,
krb5_principal_get_realm(context, principal),
"kadmin", "changepw", NULL);
if (ret)
goto out;
ret = krb5_cc_get_principal(context, ccache, &creds.client);
if (ret) {
krb5_free_principal(context, creds.server);
goto out;
}
ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
krb5_free_principal(context, creds.server);
krb5_free_principal(context, creds.client);
if (ret)
goto out;
ret = krb5_set_password(context,
credsp,
newpw,
principal,
result_code,
result_code_string,
result_string);
krb5_free_creds(context, credsp);
return ret;
out:
if (targprinc == NULL)
krb5_free_principal(context, principal);
return ret;
}
/*
*
*/
const char* KRB5_LIB_FUNCTION
krb5_passwd_result_to_string (krb5_context context,
int result)
{
static const char *strings[] = {
"Success",
"Malformed",
"Hard error",
"Auth error",
"Soft error" ,
"Access denied",
"Bad version",
"Initial flag needed"
};
if (result < 0 || result > KRB5_KPASSWD_INITIAL_FLAG_NEEDED)
return "unknown result code";
else
return strings[result];
}
+196
View File
@@ -0,0 +1,196 @@
/*
* Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: codec.c,v 1.9 2004/05/25 21:19:37 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_EncTicketPart (krb5_context context,
const void *data,
size_t length,
EncTicketPart *t,
size_t *len)
{
return decode_EncTicketPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_encode_EncTicketPart (krb5_context context,
void *data,
size_t length,
EncTicketPart *t,
size_t *len)
{
return encode_EncTicketPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_EncASRepPart (krb5_context context,
const void *data,
size_t length,
EncASRepPart *t,
size_t *len)
{
return decode_EncASRepPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_encode_EncASRepPart (krb5_context context,
void *data,
size_t length,
EncASRepPart *t,
size_t *len)
{
return encode_EncASRepPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_EncTGSRepPart (krb5_context context,
const void *data,
size_t length,
EncTGSRepPart *t,
size_t *len)
{
return decode_EncTGSRepPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_encode_EncTGSRepPart (krb5_context context,
void *data,
size_t length,
EncTGSRepPart *t,
size_t *len)
{
return encode_EncTGSRepPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_EncAPRepPart (krb5_context context,
const void *data,
size_t length,
EncAPRepPart *t,
size_t *len)
{
return decode_EncAPRepPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_encode_EncAPRepPart (krb5_context context,
void *data,
size_t length,
EncAPRepPart *t,
size_t *len)
{
return encode_EncAPRepPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_Authenticator (krb5_context context,
const void *data,
size_t length,
Authenticator *t,
size_t *len)
{
return decode_Authenticator(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_encode_Authenticator (krb5_context context,
void *data,
size_t length,
Authenticator *t,
size_t *len)
{
return encode_Authenticator(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_EncKrbCredPart (krb5_context context,
const void *data,
size_t length,
EncKrbCredPart *t,
size_t *len)
{
return decode_EncKrbCredPart(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_encode_EncKrbCredPart (krb5_context context,
void *data,
size_t length,
EncKrbCredPart *t,
size_t *len)
{
return encode_EncKrbCredPart (data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_ETYPE_INFO (krb5_context context,
const void *data,
size_t length,
ETYPE_INFO *t,
size_t *len)
{
return decode_ETYPE_INFO(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_encode_ETYPE_INFO (krb5_context context,
void *data,
size_t length,
ETYPE_INFO *t,
size_t *len)
{
return encode_ETYPE_INFO (data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_ETYPE_INFO2 (krb5_context context,
const void *data,
size_t length,
ETYPE_INFO2 *t,
size_t *len)
{
return decode_ETYPE_INFO2(data, length, t, len);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_encode_ETYPE_INFO2 (krb5_context context,
void *data,
size_t length,
ETYPE_INFO2 *t,
size_t *len)
{
return encode_ETYPE_INFO2 (data, length, t, len);
}
+773
View File
@@ -0,0 +1,773 @@
/*
* Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: config_file.c,v 1.54 2006/04/02 00:59:19 lha Exp $");
#ifndef HAVE_NETINFO
/* Gaah! I want a portable funopen */
struct fileptr {
const char *s;
FILE *f;
};
static char *
config_fgets(char *str, size_t len, struct fileptr *ptr)
{
/* XXX this is not correct, in that they don't do the same if the
line is longer than len */
if(ptr->f != NULL)
return fgets(str, len, ptr->f);
else {
/* this is almost strsep_copy */
const char *p;
ssize_t l;
if(*ptr->s == '\0')
return NULL;
p = ptr->s + strcspn(ptr->s, "\n");
if(*p == '\n')
p++;
l = min(len, p - ptr->s);
if(len > 0) {
memcpy(str, ptr->s, l);
str[l] = '\0';
}
ptr->s = p;
return str;
}
}
static krb5_error_code parse_section(char *p, krb5_config_section **s,
krb5_config_section **res,
const char **error_message);
static krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p,
krb5_config_binding **b,
krb5_config_binding **parent,
const char **error_message);
static krb5_error_code parse_list(struct fileptr *f, unsigned *lineno,
krb5_config_binding **parent,
const char **error_message);
static krb5_config_section *
get_entry(krb5_config_section **parent, const char *name, int type)
{
krb5_config_section **q;
for(q = parent; *q != NULL; q = &(*q)->next)
if(type == krb5_config_list &&
type == (*q)->type &&
strcmp(name, (*q)->name) == 0)
return *q;
*q = calloc(1, sizeof(**q));
if(*q == NULL)
return NULL;
(*q)->name = strdup(name);
(*q)->type = type;
if((*q)->name == NULL) {
free(*q);
*q = NULL;
return NULL;
}
return *q;
}
/*
* Parse a section:
*
* [section]
* foo = bar
* b = {
* a
* }
* ...
*
* starting at the line in `p', storing the resulting structure in
* `s' and hooking it into `parent'.
* Store the error message in `error_message'.
*/
static krb5_error_code
parse_section(char *p, krb5_config_section **s, krb5_config_section **parent,
const char **error_message)
{
char *p1;
krb5_config_section *tmp;
p1 = strchr (p + 1, ']');
if (p1 == NULL) {
*error_message = "missing ]";
return KRB5_CONFIG_BADFORMAT;
}
*p1 = '\0';
tmp = get_entry(parent, p + 1, krb5_config_list);
if(tmp == NULL) {
*error_message = "out of memory";
return KRB5_CONFIG_BADFORMAT;
}
*s = tmp;
return 0;
}
/*
* Parse a brace-enclosed list from `f', hooking in the structure at
* `parent'.
* Store the error message in `error_message'.
*/
static krb5_error_code
parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent,
const char **error_message)
{
char buf[BUFSIZ];
krb5_error_code ret;
krb5_config_binding *b = NULL;
unsigned beg_lineno = *lineno;
while(config_fgets(buf, sizeof(buf), f) != NULL) {
char *p;
++*lineno;
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
p = buf;
while(isspace((unsigned char)*p))
++p;
if (*p == '#' || *p == ';' || *p == '\0')
continue;
while(isspace((unsigned char)*p))
++p;
if (*p == '}')
return 0;
if (*p == '\0')
continue;
ret = parse_binding (f, lineno, p, &b, parent, error_message);
if (ret)
return ret;
}
*lineno = beg_lineno;
*error_message = "unclosed {";
return KRB5_CONFIG_BADFORMAT;
}
/*
*
*/
static krb5_error_code
parse_binding(struct fileptr *f, unsigned *lineno, char *p,
krb5_config_binding **b, krb5_config_binding **parent,
const char **error_message)
{
krb5_config_binding *tmp;
char *p1, *p2;
krb5_error_code ret = 0;
p1 = p;
while (*p && *p != '=' && !isspace((unsigned char)*p))
++p;
if (*p == '\0') {
*error_message = "missing =";
return KRB5_CONFIG_BADFORMAT;
}
p2 = p;
while (isspace((unsigned char)*p))
++p;
if (*p != '=') {
*error_message = "missing =";
return KRB5_CONFIG_BADFORMAT;
}
++p;
while(isspace((unsigned char)*p))
++p;
*p2 = '\0';
if (*p == '{') {
tmp = get_entry(parent, p1, krb5_config_list);
if (tmp == NULL) {
*error_message = "out of memory";
return KRB5_CONFIG_BADFORMAT;
}
ret = parse_list (f, lineno, &tmp->u.list, error_message);
} else {
tmp = get_entry(parent, p1, krb5_config_string);
if (tmp == NULL) {
*error_message = "out of memory";
return KRB5_CONFIG_BADFORMAT;
}
p1 = p;
p = p1 + strlen(p1);
while(p > p1 && isspace((unsigned char)*(p-1)))
--p;
*p = '\0';
tmp->u.string = strdup(p1);
}
*b = tmp;
return ret;
}
/*
* Parse the config file `fname', generating the structures into `res'
* returning error messages in `error_message'
*/
static krb5_error_code
krb5_config_parse_debug (struct fileptr *f,
krb5_config_section **res,
unsigned *lineno,
const char **error_message)
{
krb5_config_section *s = NULL;
krb5_config_binding *b = NULL;
char buf[BUFSIZ];
krb5_error_code ret;
while (config_fgets(buf, sizeof(buf), f) != NULL) {
char *p;
++*lineno;
if(buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
p = buf;
while(isspace((unsigned char)*p))
++p;
if (*p == '#' || *p == ';')
continue;
if (*p == '[') {
ret = parse_section(p, &s, res, error_message);
if (ret)
return ret;
b = NULL;
} else if (*p == '}') {
*error_message = "unmatched }";
return EINVAL; /* XXX */
} else if(*p != '\0') {
if (s == NULL) {
*error_message = "binding before section";
return EINVAL;
}
ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message);
if (ret)
return ret;
}
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_config_parse_string_multi(krb5_context context,
const char *string,
krb5_config_section **res)
{
const char *str;
unsigned lineno = 0;
krb5_error_code ret;
struct fileptr f;
f.f = NULL;
f.s = string;
ret = krb5_config_parse_debug (&f, res, &lineno, &str);
if (ret) {
krb5_set_error_string (context, "%s:%u: %s", "<constant>", lineno, str);
return ret;
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_config_parse_file_multi (krb5_context context,
const char *fname,
krb5_config_section **res)
{
const char *str;
unsigned lineno = 0;
krb5_error_code ret;
struct fileptr f;
f.f = fopen(fname, "r");
f.s = NULL;
if(f.f == NULL) {
ret = errno;
krb5_set_error_string (context, "open %s: %s", fname, strerror(ret));
return ret;
}
ret = krb5_config_parse_debug (&f, res, &lineno, &str);
fclose(f.f);
if (ret) {
krb5_set_error_string (context, "%s:%u: %s", fname, lineno, str);
return ret;
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_config_parse_file (krb5_context context,
const char *fname,
krb5_config_section **res)
{
*res = NULL;
return krb5_config_parse_file_multi(context, fname, res);
}
#endif /* !HAVE_NETINFO */
static void
free_binding (krb5_context context, krb5_config_binding *b)
{
krb5_config_binding *next_b;
while (b) {
free (b->name);
if (b->type == krb5_config_string)
free (b->u.string);
else if (b->type == krb5_config_list)
free_binding (context, b->u.list);
else
krb5_abortx(context, "unknown binding type (%d) in free_binding",
b->type);
next_b = b->next;
free (b);
b = next_b;
}
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_config_file_free (krb5_context context, krb5_config_section *s)
{
free_binding (context, s);
return 0;
}
const void *
krb5_config_get_next (krb5_context context,
const krb5_config_section *c,
const krb5_config_binding **pointer,
int type,
...)
{
const char *ret;
va_list args;
va_start(args, type);
ret = krb5_config_vget_next (context, c, pointer, type, args);
va_end(args);
return ret;
}
static const void *
vget_next(krb5_context context,
const krb5_config_binding *b,
const krb5_config_binding **pointer,
int type,
const char *name,
va_list args)
{
const char *p = va_arg(args, const char *);
while(b != NULL) {
if(strcmp(b->name, name) == 0) {
if(b->type == type && p == NULL) {
*pointer = b;
return b->u.generic;
} else if(b->type == krb5_config_list && p != NULL) {
return vget_next(context, b->u.list, pointer, type, p, args);
}
}
b = b->next;
}
return NULL;
}
const void *
krb5_config_vget_next (krb5_context context,
const krb5_config_section *c,
const krb5_config_binding **pointer,
int type,
va_list args)
{
const krb5_config_binding *b;
const char *p;
if(c == NULL)
c = context->cf;
if (c == NULL)
return NULL;
if (*pointer == NULL) {
/* first time here, walk down the tree looking for the right
section */
p = va_arg(args, const char *);
if (p == NULL)
return NULL;
return vget_next(context, c, pointer, type, p, args);
}
/* we were called again, so just look for more entries with the
same name and type */
for (b = (*pointer)->next; b != NULL; b = b->next) {
if(strcmp(b->name, (*pointer)->name) == 0 && b->type == type) {
*pointer = b;
return b->u.generic;
}
}
return NULL;
}
const void *
krb5_config_get (krb5_context context,
const krb5_config_section *c,
int type,
...)
{
const void *ret;
va_list args;
va_start(args, type);
ret = krb5_config_vget (context, c, type, args);
va_end(args);
return ret;
}
const void *
krb5_config_vget (krb5_context context,
const krb5_config_section *c,
int type,
va_list args)
{
const krb5_config_binding *foo = NULL;
return krb5_config_vget_next (context, c, &foo, type, args);
}
const krb5_config_binding *
krb5_config_get_list (krb5_context context,
const krb5_config_section *c,
...)
{
const krb5_config_binding *ret;
va_list args;
va_start(args, c);
ret = krb5_config_vget_list (context, c, args);
va_end(args);
return ret;
}
const krb5_config_binding *
krb5_config_vget_list (krb5_context context,
const krb5_config_section *c,
va_list args)
{
return krb5_config_vget (context, c, krb5_config_list, args);
}
const char* KRB5_LIB_FUNCTION
krb5_config_get_string (krb5_context context,
const krb5_config_section *c,
...)
{
const char *ret;
va_list args;
va_start(args, c);
ret = krb5_config_vget_string (context, c, args);
va_end(args);
return ret;
}
const char* KRB5_LIB_FUNCTION
krb5_config_vget_string (krb5_context context,
const krb5_config_section *c,
va_list args)
{
return krb5_config_vget (context, c, krb5_config_string, args);
}
const char* KRB5_LIB_FUNCTION
krb5_config_vget_string_default (krb5_context context,
const krb5_config_section *c,
const char *def_value,
va_list args)
{
const char *ret;
ret = krb5_config_vget_string (context, c, args);
if (ret == NULL)
ret = def_value;
return ret;
}
const char* KRB5_LIB_FUNCTION
krb5_config_get_string_default (krb5_context context,
const krb5_config_section *c,
const char *def_value,
...)
{
const char *ret;
va_list args;
va_start(args, def_value);
ret = krb5_config_vget_string_default (context, c, def_value, args);
va_end(args);
return ret;
}
char ** KRB5_LIB_FUNCTION
krb5_config_vget_strings(krb5_context context,
const krb5_config_section *c,
va_list args)
{
char **strings = NULL;
int nstr = 0;
const krb5_config_binding *b = NULL;
const char *p;
while((p = krb5_config_vget_next(context, c, &b,
krb5_config_string, args))) {
char *tmp = strdup(p);
char *pos = NULL;
char *s;
if(tmp == NULL)
goto cleanup;
s = strtok_r(tmp, " \t", &pos);
while(s){
char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings));
if(tmp2 == NULL)
goto cleanup;
strings = tmp2;
strings[nstr] = strdup(s);
nstr++;
if(strings[nstr-1] == NULL)
goto cleanup;
s = strtok_r(NULL, " \t", &pos);
}
free(tmp);
}
if(nstr){
char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
if(tmp == NULL)
goto cleanup;
strings = tmp;
strings[nstr] = NULL;
}
return strings;
cleanup:
while(nstr--)
free(strings[nstr]);
free(strings);
return NULL;
}
char**
krb5_config_get_strings(krb5_context context,
const krb5_config_section *c,
...)
{
va_list ap;
char **ret;
va_start(ap, c);
ret = krb5_config_vget_strings(context, c, ap);
va_end(ap);
return ret;
}
void KRB5_LIB_FUNCTION
krb5_config_free_strings(char **strings)
{
char **s = strings;
while(s && *s){
free(*s);
s++;
}
free(strings);
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_config_vget_bool_default (krb5_context context,
const krb5_config_section *c,
krb5_boolean def_value,
va_list args)
{
const char *str;
str = krb5_config_vget_string (context, c, args);
if(str == NULL)
return def_value;
if(strcasecmp(str, "yes") == 0 ||
strcasecmp(str, "true") == 0 ||
atoi(str)) return TRUE;
return FALSE;
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_config_vget_bool (krb5_context context,
const krb5_config_section *c,
va_list args)
{
return krb5_config_vget_bool_default (context, c, FALSE, args);
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_config_get_bool_default (krb5_context context,
const krb5_config_section *c,
krb5_boolean def_value,
...)
{
va_list ap;
krb5_boolean ret;
va_start(ap, def_value);
ret = krb5_config_vget_bool_default(context, c, def_value, ap);
va_end(ap);
return ret;
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_config_get_bool (krb5_context context,
const krb5_config_section *c,
...)
{
va_list ap;
krb5_boolean ret;
va_start(ap, c);
ret = krb5_config_vget_bool (context, c, ap);
va_end(ap);
return ret;
}
int KRB5_LIB_FUNCTION
krb5_config_vget_time_default (krb5_context context,
const krb5_config_section *c,
int def_value,
va_list args)
{
const char *str;
krb5_deltat t;
str = krb5_config_vget_string (context, c, args);
if(str == NULL)
return def_value;
if (krb5_string_to_deltat(str, &t))
return def_value;
return t;
}
int KRB5_LIB_FUNCTION
krb5_config_vget_time (krb5_context context,
const krb5_config_section *c,
va_list args)
{
return krb5_config_vget_time_default (context, c, -1, args);
}
int KRB5_LIB_FUNCTION
krb5_config_get_time_default (krb5_context context,
const krb5_config_section *c,
int def_value,
...)
{
va_list ap;
int ret;
va_start(ap, def_value);
ret = krb5_config_vget_time_default(context, c, def_value, ap);
va_end(ap);
return ret;
}
int KRB5_LIB_FUNCTION
krb5_config_get_time (krb5_context context,
const krb5_config_section *c,
...)
{
va_list ap;
int ret;
va_start(ap, c);
ret = krb5_config_vget_time (context, c, ap);
va_end(ap);
return ret;
}
int KRB5_LIB_FUNCTION
krb5_config_vget_int_default (krb5_context context,
const krb5_config_section *c,
int def_value,
va_list args)
{
const char *str;
str = krb5_config_vget_string (context, c, args);
if(str == NULL)
return def_value;
else {
char *endptr;
long l;
l = strtol(str, &endptr, 0);
if (endptr == str)
return def_value;
else
return l;
}
}
int KRB5_LIB_FUNCTION
krb5_config_vget_int (krb5_context context,
const krb5_config_section *c,
va_list args)
{
return krb5_config_vget_int_default (context, c, -1, args);
}
int KRB5_LIB_FUNCTION
krb5_config_get_int_default (krb5_context context,
const krb5_config_section *c,
int def_value,
...)
{
va_list ap;
int ret;
va_start(ap, def_value);
ret = krb5_config_vget_int_default(context, c, def_value, ap);
va_end(ap);
return ret;
}
int KRB5_LIB_FUNCTION
krb5_config_get_int (krb5_context context,
const krb5_config_section *c,
...)
{
va_list ap;
int ret;
va_start(ap, c);
ret = krb5_config_vget_int (context, c, ap);
va_end(ap);
return ret;
}
@@ -0,0 +1,180 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: config_file_netinfo.c,v 1.4 2004/05/25 21:20:18 lha Exp $");
/*
* Netinfo implementation from Luke Howard <lukeh@xedoc.com.au>
*/
#ifdef HAVE_NETINFO
#include <netinfo/ni.h>
static ni_status
ni_proplist2binding(ni_proplist *pl, krb5_config_section **ret)
{
int i, j;
krb5_config_section **next = NULL;
for (i = 0; i < pl->ni_proplist_len; i++) {
if (!strcmp(pl->nipl_val[i].nip_name, "name"))
continue;
for (j = 0; j < pl->nipl_val[i].nip_val.ni_namelist_len; j++) {
krb5_config_binding *b;
b = malloc(sizeof(*b));
if (b == NULL)
return NI_FAILED;
b->next = NULL;
b->type = krb5_config_string;
b->name = ni_name_dup(pl->nipl_val[i].nip_name);
b->u.string = ni_name_dup(pl->nipl_val[i].nip_val.ninl_val[j]);
if (next == NULL) {
*ret = b;
} else {
*next = b;
}
next = &b->next;
}
}
return NI_OK;
}
static ni_status
ni_idlist2binding(void *ni, ni_idlist *idlist, krb5_config_section **ret)
{
int i;
ni_status nis;
krb5_config_section **next;
for (i = 0; i < idlist->ni_idlist_len; i++) {
ni_proplist pl;
ni_id nid;
ni_idlist children;
krb5_config_binding *b;
ni_index index;
nid.nii_instance = 0;
nid.nii_object = idlist->ni_idlist_val[i];
nis = ni_read(ni, &nid, &pl);
if (nis != NI_OK) {
return nis;
}
index = ni_proplist_match(pl, "name", NULL);
b = malloc(sizeof(*b));
if (b == NULL) return NI_FAILED;
if (i == 0) {
*ret = b;
} else {
*next = b;
}
b->type = krb5_config_list;
b->name = ni_name_dup(pl.nipl_val[index].nip_val.ninl_val[0]);
b->next = NULL;
b->u.list = NULL;
/* get the child directories */
nis = ni_children(ni, &nid, &children);
if (nis == NI_OK) {
nis = ni_idlist2binding(ni, &children, &b->u.list);
if (nis != NI_OK) {
return nis;
}
}
nis = ni_proplist2binding(&pl, b->u.list == NULL ? &b->u.list : &b->u.list->next);
ni_proplist_free(&pl);
if (nis != NI_OK) {
return nis;
}
next = &b->next;
}
ni_idlist_free(idlist);
return NI_OK;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_config_parse_file (krb5_context context,
const char *fname,
krb5_config_section **res)
{
void *ni = NULL, *lastni = NULL;
int i;
ni_status nis;
ni_id nid;
ni_idlist children;
krb5_config_section *s;
int ret;
s = NULL;
for (i = 0; i < 256; i++) {
if (i == 0) {
nis = ni_open(NULL, ".", &ni);
} else {
if (lastni != NULL) ni_free(lastni);
lastni = ni;
nis = ni_open(lastni, "..", &ni);
}
if (nis != NI_OK)
break;
nis = ni_pathsearch(ni, &nid, "/locations/kerberos");
if (nis == NI_OK) {
nis = ni_children(ni, &nid, &children);
if (nis != NI_OK)
break;
nis = ni_idlist2binding(ni, &children, &s);
break;
}
}
if (ni != NULL) ni_free(ni);
if (ni != lastni && lastni != NULL) ni_free(lastni);
ret = (nis == NI_OK) ? 0 : -1;
if (ret == 0) {
*res = s;
} else {
*res = NULL;
}
return ret;
}
#endif /* HAVE_NETINFO */
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: constants.c,v 1.8 2004/09/23 07:57:37 joda Exp $");
const char *krb5_config_file =
#ifdef __APPLE__
"/Library/Preferences/edu.mit.Kerberos:"
#endif
SYSCONFDIR "/krb5.conf:/etc/krb5.conf";
const char *krb5_defkeyname = KEYTAB_DEFAULT;
+719
View File
@@ -0,0 +1,719 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include <com_err.h>
RCSID("$Id: context.c,v 1.111 2006/11/08 02:55:46 lha Exp $");
#define INIT_FIELD(C, T, E, D, F) \
(C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \
"libdefaults", F, NULL)
/*
* Set the list of etypes `ret_etypes' from the configuration variable
* `name'
*/
static krb5_error_code
set_etypes (krb5_context context,
const char *name,
krb5_enctype **ret_enctypes)
{
char **etypes_str;
krb5_enctype *etypes = NULL;
etypes_str = krb5_config_get_strings(context, NULL, "libdefaults",
name, NULL);
if(etypes_str){
int i, j, k;
for(i = 0; etypes_str[i]; i++);
etypes = malloc((i+1) * sizeof(*etypes));
if (etypes == NULL) {
krb5_config_free_strings (etypes_str);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
for(j = 0, k = 0; j < i; j++) {
krb5_enctype e;
if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0)
continue;
if (krb5_enctype_valid(context, e) != 0)
continue;
etypes[k++] = e;
}
etypes[k] = ETYPE_NULL;
krb5_config_free_strings(etypes_str);
}
*ret_enctypes = etypes;
return 0;
}
/*
* read variables from the configuration file and set in `context'
*/
static krb5_error_code
init_context_from_config_file(krb5_context context)
{
krb5_error_code ret;
const char * tmp;
krb5_enctype *tmptypes;
INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout");
INIT_FIELD(context, int, max_retries, 3, "max_retries");
INIT_FIELD(context, string, http_proxy, NULL, "http_proxy");
ret = set_etypes (context, "default_etypes", &tmptypes);
if(ret)
return ret;
free(context->etypes);
context->etypes = tmptypes;
ret = set_etypes (context, "default_etypes_des", &tmptypes);
if(ret)
return ret;
free(context->etypes_des);
context->etypes_des = tmptypes;
/* default keytab name */
tmp = NULL;
if(!issuid())
tmp = getenv("KRB5_KTNAME");
if(tmp != NULL)
context->default_keytab = tmp;
else
INIT_FIELD(context, string, default_keytab,
KEYTAB_DEFAULT, "default_keytab_name");
INIT_FIELD(context, string, default_keytab_modify,
NULL, "default_keytab_modify_name");
INIT_FIELD(context, string, time_fmt,
"%Y-%m-%dT%H:%M:%S", "time_format");
INIT_FIELD(context, string, date_fmt,
"%Y-%m-%d", "date_format");
INIT_FIELD(context, bool, log_utc,
FALSE, "log_utc");
/* init dns-proxy slime */
tmp = krb5_config_get_string(context, NULL, "libdefaults",
"dns_proxy", NULL);
if(tmp)
roken_gethostby_setup(context->http_proxy, tmp);
krb5_free_host_realm (context, context->default_realms);
context->default_realms = NULL;
{
krb5_addresses addresses;
char **adr, **a;
krb5_set_extra_addresses(context, NULL);
adr = krb5_config_get_strings(context, NULL,
"libdefaults",
"extra_addresses",
NULL);
memset(&addresses, 0, sizeof(addresses));
for(a = adr; a && *a; a++) {
ret = krb5_parse_address(context, *a, &addresses);
if (ret == 0) {
krb5_add_extra_addresses(context, &addresses);
krb5_free_addresses(context, &addresses);
}
}
krb5_config_free_strings(adr);
krb5_set_ignore_addresses(context, NULL);
adr = krb5_config_get_strings(context, NULL,
"libdefaults",
"ignore_addresses",
NULL);
memset(&addresses, 0, sizeof(addresses));
for(a = adr; a && *a; a++) {
ret = krb5_parse_address(context, *a, &addresses);
if (ret == 0) {
krb5_add_ignore_addresses(context, &addresses);
krb5_free_addresses(context, &addresses);
}
}
krb5_config_free_strings(adr);
}
INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces");
INIT_FIELD(context, int, fcache_vno, 0, "fcache_version");
/* prefer dns_lookup_kdc over srv_lookup. */
INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc");
INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size");
INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonicalize_hostname");
context->default_cc_name = NULL;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_init_context(krb5_context *context)
{
krb5_context p;
krb5_error_code ret;
char **files;
*context = NULL;
p = calloc(1, sizeof(*p));
if(!p)
return ENOMEM;
p->mutex = malloc(sizeof(HEIMDAL_MUTEX));
if (p->mutex == NULL) {
free(p);
return ENOMEM;
}
HEIMDAL_MUTEX_init(p->mutex);
ret = krb5_get_default_config_files(&files);
if(ret)
goto out;
ret = krb5_set_config_files(p, files);
krb5_free_config_files(files);
if(ret)
goto out;
/* init error tables */
krb5_init_ets(p);
p->cc_ops = NULL;
p->num_cc_ops = 0;
krb5_cc_register(p, &krb5_acc_ops, TRUE);
krb5_cc_register(p, &krb5_fcc_ops, TRUE);
krb5_cc_register(p, &krb5_mcc_ops, TRUE);
#ifdef HAVE_KCM
krb5_cc_register(p, &krb5_kcm_ops, TRUE);
#endif
p->num_kt_types = 0;
p->kt_types = NULL;
krb5_kt_register (p, &krb5_fkt_ops);
krb5_kt_register (p, &krb5_wrfkt_ops);
krb5_kt_register (p, &krb5_javakt_ops);
krb5_kt_register (p, &krb5_mkt_ops);
krb5_kt_register (p, &krb5_akf_ops);
krb5_kt_register (p, &krb4_fkt_ops);
krb5_kt_register (p, &krb5_srvtab_fkt_ops);
krb5_kt_register (p, &krb5_any_ops);
out:
if(ret) {
krb5_free_context(p);
p = NULL;
}
*context = p;
return ret;
}
void KRB5_LIB_FUNCTION
krb5_free_context(krb5_context context)
{
if (context->default_cc_name)
free(context->default_cc_name);
free(context->etypes);
free(context->etypes_des);
krb5_free_host_realm (context, context->default_realms);
krb5_config_file_free (context, context->cf);
free_error_table (context->et_list);
free(context->cc_ops);
free(context->kt_types);
krb5_clear_error_string(context);
if(context->warn_dest != NULL)
krb5_closelog(context, context->warn_dest);
krb5_set_extra_addresses(context, NULL);
krb5_set_ignore_addresses(context, NULL);
krb5_set_send_to_kdc_func(context, NULL, NULL);
if (context->mutex != NULL) {
HEIMDAL_MUTEX_destroy(context->mutex);
free(context->mutex);
}
memset(context, 0, sizeof(*context));
free(context);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_config_files(krb5_context context, char **filenames)
{
krb5_error_code ret;
krb5_config_binding *tmp = NULL;
while(filenames != NULL && *filenames != NULL && **filenames != '\0') {
ret = krb5_config_parse_file_multi(context, *filenames, &tmp);
if(ret != 0 && ret != ENOENT && ret != EACCES) {
krb5_config_file_free(context, tmp);
return ret;
}
filenames++;
}
#if 0
/* with this enabled and if there are no config files, Kerberos is
considererd disabled */
if(tmp == NULL)
return ENXIO;
#endif
krb5_config_file_free(context, context->cf);
context->cf = tmp;
ret = init_context_from_config_file(context);
return ret;
}
static krb5_error_code
add_file(char ***pfilenames, int *len, char *file)
{
char **pp = *pfilenames;
int i;
for(i = 0; i < *len; i++) {
if(strcmp(pp[i], file) == 0) {
free(file);
return 0;
}
}
pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp));
if (pp == NULL) {
free(file);
return ENOMEM;
}
pp[*len] = file;
pp[*len + 1] = NULL;
*pfilenames = pp;
*len += 1;
return 0;
}
/*
* `pq' isn't free, its up the the caller
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp)
{
krb5_error_code ret;
const char *p, *q;
char **pp;
int len;
char *fn;
pp = NULL;
len = 0;
p = filelist;
while(1) {
ssize_t l;
q = p;
l = strsep_copy(&q, ":", NULL, 0);
if(l == -1)
break;
fn = malloc(l + 1);
if(fn == NULL) {
krb5_free_config_files(pp);
return ENOMEM;
}
l = strsep_copy(&p, ":", fn, l + 1);
ret = add_file(&pp, &len, fn);
if (ret) {
krb5_free_config_files(pp);
return ret;
}
}
if (pq != NULL) {
int i;
for (i = 0; pq[i] != NULL; i++) {
fn = strdup(pq[i]);
if (fn == NULL) {
krb5_free_config_files(pp);
return ENOMEM;
}
ret = add_file(&pp, &len, fn);
if (ret) {
krb5_free_config_files(pp);
return ret;
}
}
}
*ret_pp = pp;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_prepend_config_files_default(const char *filelist, char ***pfilenames)
{
krb5_error_code ret;
char **defpp, **pp = NULL;
ret = krb5_get_default_config_files(&defpp);
if (ret)
return ret;
ret = krb5_prepend_config_files(filelist, defpp, &pp);
krb5_free_config_files(defpp);
if (ret) {
return ret;
}
*pfilenames = pp;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_default_config_files(char ***pfilenames)
{
const char *files = NULL;
if (pfilenames == NULL)
return EINVAL;
if(!issuid())
files = getenv("KRB5_CONFIG");
if (files == NULL)
files = krb5_config_file;
return krb5_prepend_config_files(files, NULL, pfilenames);
}
void KRB5_LIB_FUNCTION
krb5_free_config_files(char **filenames)
{
char **p;
for(p = filenames; *p != NULL; p++)
free(*p);
free(filenames);
}
/*
* Returns the list of Kerberos encryption types sorted in order of
* most preferred to least preferred encryption type. The array ends
* with ETYPE_NULL. Note that some encryption types might be
* disabled, so you need to check with krb5_enctype_valid() before
* using the encryption type.
*/
const krb5_enctype * KRB5_LIB_FUNCTION
krb5_kerberos_enctypes(krb5_context context)
{
static const krb5_enctype p[] = {
ETYPE_AES256_CTS_HMAC_SHA1_96,
ETYPE_AES128_CTS_HMAC_SHA1_96,
ETYPE_DES3_CBC_SHA1,
ETYPE_DES3_CBC_MD5,
ETYPE_ARCFOUR_HMAC_MD5,
ETYPE_DES_CBC_MD5,
ETYPE_DES_CBC_MD4,
ETYPE_DES_CBC_CRC,
ETYPE_NULL
};
return p;
}
/*
* set `etype' to a malloced list of the default enctypes
*/
static krb5_error_code
default_etypes(krb5_context context, krb5_enctype **etype)
{
const krb5_enctype *p;
krb5_enctype *e = NULL, *ep;
int i, n = 0;
p = krb5_kerberos_enctypes(context);
for (i = 0; p[i] != ETYPE_NULL; i++) {
if (krb5_enctype_valid(context, p[i]) != 0)
continue;
ep = realloc(e, (n + 2) * sizeof(*e));
if (ep == NULL) {
free(e);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
e = ep;
e[n] = p[i];
e[n + 1] = ETYPE_NULL;
n++;
}
*etype = e;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_default_in_tkt_etypes(krb5_context context,
const krb5_enctype *etypes)
{
krb5_enctype *p = NULL;
int i;
if(etypes) {
for (i = 0; etypes[i]; ++i) {
krb5_error_code ret;
ret = krb5_enctype_valid(context, etypes[i]);
if (ret)
return ret;
}
++i;
ALLOC(p, i);
if(!p) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
memmove(p, etypes, i * sizeof(krb5_enctype));
}
if(context->etypes)
free(context->etypes);
context->etypes = p;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_default_in_tkt_etypes(krb5_context context,
krb5_enctype **etypes)
{
krb5_enctype *p;
int i;
krb5_error_code ret;
if(context->etypes) {
for(i = 0; context->etypes[i]; i++);
++i;
ALLOC(p, i);
if(!p) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
memmove(p, context->etypes, i * sizeof(krb5_enctype));
} else {
ret = default_etypes(context, &p);
if (ret)
return ret;
}
*etypes = p;
return 0;
}
const char* KRB5_LIB_FUNCTION
krb5_get_err_text(krb5_context context, krb5_error_code code)
{
const char *p = NULL;
if(context != NULL)
p = com_right(context->et_list, code);
if(p == NULL)
p = strerror(code);
if (p == NULL)
p = "Unknown error";
return p;
}
void KRB5_LIB_FUNCTION
krb5_init_ets(krb5_context context)
{
if(context->et_list == NULL){
krb5_add_et_list(context, initialize_krb5_error_table_r);
krb5_add_et_list(context, initialize_asn1_error_table_r);
krb5_add_et_list(context, initialize_heim_error_table_r);
krb5_add_et_list(context, initialize_k524_error_table_r);
#ifdef PKINIT
krb5_add_et_list(context, initialize_hx_error_table_r);
#endif
}
}
void KRB5_LIB_FUNCTION
krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag)
{
context->use_admin_kdc = flag;
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_get_use_admin_kdc (krb5_context context)
{
return context->use_admin_kdc;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses)
{
if(context->extra_addresses)
return krb5_append_addresses(context,
context->extra_addresses, addresses);
else
return krb5_set_extra_addresses(context, addresses);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses)
{
if(context->extra_addresses)
krb5_free_addresses(context, context->extra_addresses);
if(addresses == NULL) {
if(context->extra_addresses != NULL) {
free(context->extra_addresses);
context->extra_addresses = NULL;
}
return 0;
}
if(context->extra_addresses == NULL) {
context->extra_addresses = malloc(sizeof(*context->extra_addresses));
if(context->extra_addresses == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
}
return krb5_copy_addresses(context, addresses, context->extra_addresses);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses)
{
if(context->extra_addresses == NULL) {
memset(addresses, 0, sizeof(*addresses));
return 0;
}
return krb5_copy_addresses(context,context->extra_addresses, addresses);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses)
{
if(context->ignore_addresses)
return krb5_append_addresses(context,
context->ignore_addresses, addresses);
else
return krb5_set_ignore_addresses(context, addresses);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses)
{
if(context->ignore_addresses)
krb5_free_addresses(context, context->ignore_addresses);
if(addresses == NULL) {
if(context->ignore_addresses != NULL) {
free(context->ignore_addresses);
context->ignore_addresses = NULL;
}
return 0;
}
if(context->ignore_addresses == NULL) {
context->ignore_addresses = malloc(sizeof(*context->ignore_addresses));
if(context->ignore_addresses == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
}
return krb5_copy_addresses(context, addresses, context->ignore_addresses);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses)
{
if(context->ignore_addresses == NULL) {
memset(addresses, 0, sizeof(*addresses));
return 0;
}
return krb5_copy_addresses(context, context->ignore_addresses, addresses);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_fcache_version(krb5_context context, int version)
{
context->fcache_vno = version;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_fcache_version(krb5_context context, int *version)
{
*version = context->fcache_vno;
return 0;
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_is_thread_safe(void)
{
#ifdef ENABLE_PTHREAD_SUPPORT
return TRUE;
#else
return FALSE;
#endif
}
void KRB5_LIB_FUNCTION
krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag)
{
context->dns_canonicalize_hostname = flag;
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_get_dns_canonicalize_hostname (krb5_context context)
{
return context->dns_canonicalize_hostname;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec)
{
if (sec)
*sec = context->kdc_sec_offset;
if (usec)
*usec = context->kdc_usec_offset;
return 0;
}
time_t KRB5_LIB_FUNCTION
krb5_get_max_time_skew (krb5_context context)
{
return context->max_skew;
}
void KRB5_LIB_FUNCTION
krb5_set_max_time_skew (krb5_context context, time_t t)
{
context->max_skew = t;
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: copy_host_realm.c,v 1.5 2004/05/25 21:21:17 lha Exp $");
/*
* Copy the list of realms from `from' to `to'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_host_realm(krb5_context context,
const krb5_realm *from,
krb5_realm **to)
{
int n, i;
const krb5_realm *p;
for (n = 0, p = from; *p != NULL; ++p)
++n;
++n;
*to = malloc (n * sizeof(**to));
if (*to == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
for (i = 0; i < n; ++i)
(*to)[i] = NULL;
for (i = 0, p = from; *p != NULL; ++p, ++i) {
(*to)[i] = strdup(*p);
if ((*to)[i] == NULL) {
krb5_free_host_realm (context, *to);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
}
return 0;
}
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: crc.c,v 1.10 2006/05/05 09:27:09 lha Exp $");
static u_long table[256];
#define CRC_GEN 0xEDB88320L
void
_krb5_crc_init_table(void)
{
static int flag = 0;
unsigned long crc, poly;
int i, j;
if(flag) return;
poly = CRC_GEN;
for (i = 0; i < 256; i++) {
crc = i;
for (j = 8; j > 0; j--) {
if (crc & 1) {
crc = (crc >> 1) ^ poly;
} else {
crc >>= 1;
}
}
table[i] = crc;
}
flag = 1;
}
uint32_t
_krb5_crc_update (const char *p, size_t len, uint32_t res)
{
while (len--)
res = table[(res ^ *p++) & 0xFF] ^ (res >> 8);
return res & 0xFFFFFFFF;
}
+215
View File
@@ -0,0 +1,215 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: creds.c,v 1.20 2005/05/18 04:21:04 lha Exp $");
/* keep this for compatibility with older code */
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_creds_contents (krb5_context context, krb5_creds *c)
{
return krb5_free_cred_contents (context, c);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_cred_contents (krb5_context context, krb5_creds *c)
{
krb5_free_principal (context, c->client);
c->client = NULL;
krb5_free_principal (context, c->server);
c->server = NULL;
krb5_free_keyblock_contents (context, &c->session);
krb5_data_free (&c->ticket);
krb5_data_free (&c->second_ticket);
free_AuthorizationData (&c->authdata);
krb5_free_addresses (context, &c->addresses);
memset(c, 0, sizeof(*c));
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_creds_contents (krb5_context context,
const krb5_creds *incred,
krb5_creds *c)
{
krb5_error_code ret;
memset(c, 0, sizeof(*c));
ret = krb5_copy_principal (context, incred->client, &c->client);
if (ret)
goto fail;
ret = krb5_copy_principal (context, incred->server, &c->server);
if (ret)
goto fail;
ret = krb5_copy_keyblock_contents (context, &incred->session, &c->session);
if (ret)
goto fail;
c->times = incred->times;
ret = krb5_data_copy (&c->ticket,
incred->ticket.data,
incred->ticket.length);
if (ret)
goto fail;
ret = krb5_data_copy (&c->second_ticket,
incred->second_ticket.data,
incred->second_ticket.length);
if (ret)
goto fail;
ret = copy_AuthorizationData(&incred->authdata, &c->authdata);
if (ret)
goto fail;
ret = krb5_copy_addresses (context,
&incred->addresses,
&c->addresses);
if (ret)
goto fail;
c->flags = incred->flags;
return 0;
fail:
krb5_free_cred_contents (context, c);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_creds (krb5_context context,
const krb5_creds *incred,
krb5_creds **outcred)
{
krb5_creds *c;
c = malloc (sizeof (*c));
if (c == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
memset (c, 0, sizeof(*c));
*outcred = c;
return krb5_copy_creds_contents (context, incred, c);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_creds (krb5_context context, krb5_creds *c)
{
krb5_free_cred_contents (context, c);
free (c);
return 0;
}
/* XXX these do not belong here */
static krb5_boolean
krb5_data_equal(const krb5_data *a, const krb5_data *b)
{
if(a->length != b->length)
return FALSE;
return memcmp(a->data, b->data, a->length) == 0;
}
static krb5_boolean
krb5_times_equal(const krb5_times *a, const krb5_times *b)
{
return a->starttime == b->starttime &&
a->authtime == b->authtime &&
a->endtime == b->endtime &&
a->renew_till == b->renew_till;
}
/*
* Return TRUE if `mcreds' and `creds' are equal (`whichfields'
* determines what equal means).
*/
krb5_boolean KRB5_LIB_FUNCTION
krb5_compare_creds(krb5_context context, krb5_flags whichfields,
const krb5_creds * mcreds, const krb5_creds * creds)
{
krb5_boolean match = TRUE;
if (match && mcreds->server) {
if (whichfields & (KRB5_TC_DONT_MATCH_REALM | KRB5_TC_MATCH_SRV_NAMEONLY))
match = krb5_principal_compare_any_realm (context, mcreds->server,
creds->server);
else
match = krb5_principal_compare (context, mcreds->server,
creds->server);
}
if (match && mcreds->client) {
if(whichfields & KRB5_TC_DONT_MATCH_REALM)
match = krb5_principal_compare_any_realm (context, mcreds->client,
creds->client);
else
match = krb5_principal_compare (context, mcreds->client,
creds->client);
}
if (match && (whichfields & KRB5_TC_MATCH_KEYTYPE))
match = krb5_enctypes_compatible_keys(context,
mcreds->session.keytype,
creds->session.keytype);
if (match && (whichfields & KRB5_TC_MATCH_FLAGS_EXACT))
match = mcreds->flags.i == creds->flags.i;
if (match && (whichfields & KRB5_TC_MATCH_FLAGS))
match = (creds->flags.i & mcreds->flags.i) == mcreds->flags.i;
if (match && (whichfields & KRB5_TC_MATCH_TIMES_EXACT))
match = krb5_times_equal(&mcreds->times, &creds->times);
if (match && (whichfields & KRB5_TC_MATCH_TIMES))
/* compare only expiration times */
match = (mcreds->times.renew_till <= creds->times.renew_till) &&
(mcreds->times.endtime <= creds->times.endtime);
if (match && (whichfields & KRB5_TC_MATCH_AUTHDATA)) {
unsigned int i;
if(mcreds->authdata.len != creds->authdata.len)
match = FALSE;
else
for(i = 0; match && i < mcreds->authdata.len; i++)
match = (mcreds->authdata.val[i].ad_type ==
creds->authdata.val[i].ad_type) &&
krb5_data_equal(&mcreds->authdata.val[i].ad_data,
&creds->authdata.val[i].ad_data);
}
if (match && (whichfields & KRB5_TC_MATCH_2ND_TKT))
match = krb5_data_equal(&mcreds->second_ticket, &creds->second_ticket);
if (match && (whichfields & KRB5_TC_MATCH_IS_SKEY))
match = ((mcreds->second_ticket.length == 0) ==
(creds->second_ticket.length == 0));
return match;
}
File diff suppressed because it is too large Load Diff
+120
View File
@@ -0,0 +1,120 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: data.c,v 1.21 2006/10/14 09:45:41 lha Exp $");
void KRB5_LIB_FUNCTION
krb5_data_zero(krb5_data *p)
{
p->length = 0;
p->data = NULL;
}
void KRB5_LIB_FUNCTION
krb5_data_free(krb5_data *p)
{
if(p->data != NULL)
free(p->data);
krb5_data_zero(p);
}
void KRB5_LIB_FUNCTION
krb5_free_data_contents(krb5_context context, krb5_data *data)
{
krb5_data_free(data);
}
void KRB5_LIB_FUNCTION
krb5_free_data(krb5_context context,
krb5_data *p)
{
krb5_data_free(p);
free(p);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_data_alloc(krb5_data *p, int len)
{
p->data = malloc(len);
if(len && p->data == NULL)
return ENOMEM;
p->length = len;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_data_realloc(krb5_data *p, int len)
{
void *tmp;
tmp = realloc(p->data, len);
if(len && !tmp)
return ENOMEM;
p->data = tmp;
p->length = len;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_data_copy(krb5_data *p, const void *data, size_t len)
{
if (len) {
if(krb5_data_alloc(p, len))
return ENOMEM;
memmove(p->data, data, len);
} else
p->data = NULL;
p->length = len;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_data(krb5_context context,
const krb5_data *indata,
krb5_data **outdata)
{
krb5_error_code ret;
ALLOC(*outdata, 1);
if(*outdata == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
ret = der_copy_octet_string(indata, *outdata);
if(ret) {
krb5_clear_error_string (context);
free(*outdata);
*outdata = NULL;
}
return ret;
}
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: eai_to_heim_errno.c,v 1.5 2004/05/25 21:23:35 lha Exp $");
/*
* convert the getaddrinfo error code in `eai_errno' into a
* krb5_error_code. `system_error' should have the value of the errno
* after the failed call.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_eai_to_heim_errno(int eai_errno, int system_error)
{
switch(eai_errno) {
case EAI_NOERROR:
return 0;
#ifdef EAI_ADDRFAMILY
case EAI_ADDRFAMILY:
return HEIM_EAI_ADDRFAMILY;
#endif
case EAI_AGAIN:
return HEIM_EAI_AGAIN;
case EAI_BADFLAGS:
return HEIM_EAI_BADFLAGS;
case EAI_FAIL:
return HEIM_EAI_FAIL;
case EAI_FAMILY:
return HEIM_EAI_FAMILY;
case EAI_MEMORY:
return HEIM_EAI_MEMORY;
#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
case EAI_NODATA:
return HEIM_EAI_NODATA;
#endif
case EAI_NONAME:
return HEIM_EAI_NONAME;
case EAI_SERVICE:
return HEIM_EAI_SERVICE;
case EAI_SOCKTYPE:
return HEIM_EAI_SOCKTYPE;
case EAI_SYSTEM:
return system_error;
default:
return HEIM_EAI_UNKNOWN; /* XXX */
}
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_h_errno_to_heim_errno(int eai_errno)
{
switch(eai_errno) {
case 0:
return 0;
case HOST_NOT_FOUND:
return HEIM_EAI_NONAME;
case TRY_AGAIN:
return HEIM_EAI_AGAIN;
case NO_RECOVERY:
return HEIM_EAI_FAIL;
case NO_DATA:
return HEIM_EAI_NONAME;
default:
return HEIM_EAI_UNKNOWN; /* XXX */
}
}
@@ -0,0 +1,130 @@
/*
* Copyright (c) 2001, 2003, 2005 - 2006 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: error_string.c,v 1.7 2006/02/16 07:49:23 lha Exp $");
#undef __attribute__
#define __attribute__(X)
void KRB5_LIB_FUNCTION
krb5_free_error_string(krb5_context context, char *str)
{
HEIMDAL_MUTEX_lock(context->mutex);
if (str != context->error_buf)
free(str);
HEIMDAL_MUTEX_unlock(context->mutex);
}
void KRB5_LIB_FUNCTION
krb5_clear_error_string(krb5_context context)
{
HEIMDAL_MUTEX_lock(context->mutex);
if (context->error_string != NULL
&& context->error_string != context->error_buf)
free(context->error_string);
context->error_string = NULL;
HEIMDAL_MUTEX_unlock(context->mutex);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_error_string(krb5_context context, const char *fmt, ...)
__attribute__((format (printf, 2, 3)))
{
krb5_error_code ret;
va_list ap;
va_start(ap, fmt);
ret = krb5_vset_error_string (context, fmt, ap);
va_end(ap);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_vset_error_string(krb5_context context, const char *fmt, va_list args)
__attribute__ ((format (printf, 2, 0)))
{
krb5_clear_error_string(context);
HEIMDAL_MUTEX_lock(context->mutex);
vasprintf(&context->error_string, fmt, args);
if(context->error_string == NULL) {
vsnprintf (context->error_buf, sizeof(context->error_buf), fmt, args);
context->error_string = context->error_buf;
}
HEIMDAL_MUTEX_unlock(context->mutex);
return 0;
}
char * KRB5_LIB_FUNCTION
krb5_get_error_string(krb5_context context)
{
char *ret;
HEIMDAL_MUTEX_lock(context->mutex);
ret = context->error_string;
context->error_string = NULL;
HEIMDAL_MUTEX_unlock(context->mutex);
return ret;
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_have_error_string(krb5_context context)
{
char *str;
HEIMDAL_MUTEX_lock(context->mutex);
str = context->error_string;
HEIMDAL_MUTEX_unlock(context->mutex);
return str != NULL;
}
char * KRB5_LIB_FUNCTION
krb5_get_error_message(krb5_context context, krb5_error_code code)
{
const char *cstr;
char *str;
str = krb5_get_error_string(context);
if (str)
return str;
cstr = krb5_get_err_text(context, code);
if (cstr)
return strdup(cstr);
if (asprintf(&str, "<unknown error: %d>", code) == -1)
return NULL;
return str;
}
@@ -0,0 +1,160 @@
/*
* Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: expand_hostname.c,v 1.14 2006/11/04 03:34:57 lha Exp $");
static krb5_error_code
copy_hostname(krb5_context context,
const char *orig_hostname,
char **new_hostname)
{
*new_hostname = strdup (orig_hostname);
if (*new_hostname == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
strlwr (*new_hostname);
return 0;
}
/*
* Try to make `orig_hostname' into a more canonical one in the newly
* allocated space returned in `new_hostname'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_expand_hostname (krb5_context context,
const char *orig_hostname,
char **new_hostname)
{
struct addrinfo *ai, *a, hints;
int error;
if (!context->dns_canonicalize_hostname)
return copy_hostname (context, orig_hostname, new_hostname);
memset (&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
if (error)
return copy_hostname (context, orig_hostname, new_hostname);
for (a = ai; a != NULL; a = a->ai_next) {
if (a->ai_canonname != NULL) {
*new_hostname = strdup (a->ai_canonname);
freeaddrinfo (ai);
if (*new_hostname == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
} else {
return 0;
}
}
}
freeaddrinfo (ai);
return copy_hostname (context, orig_hostname, new_hostname);
}
/*
* handle the case of the hostname being unresolvable and thus identical
*/
static krb5_error_code
vanilla_hostname (krb5_context context,
const char *orig_hostname,
char **new_hostname,
char ***realms)
{
krb5_error_code ret;
ret = copy_hostname (context, orig_hostname, new_hostname);
if (ret)
return ret;
strlwr (*new_hostname);
ret = krb5_get_host_realm (context, *new_hostname, realms);
if (ret) {
free (*new_hostname);
return ret;
}
return 0;
}
/*
* expand `hostname' to a name we believe to be a hostname in newly
* allocated space in `host' and return realms in `realms'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_expand_hostname_realms (krb5_context context,
const char *orig_hostname,
char **new_hostname,
char ***realms)
{
struct addrinfo *ai, *a, hints;
int error;
krb5_error_code ret = 0;
if (!context->dns_canonicalize_hostname)
return vanilla_hostname (context, orig_hostname, new_hostname,
realms);
memset (&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
if (error)
return vanilla_hostname (context, orig_hostname, new_hostname,
realms);
for (a = ai; a != NULL; a = a->ai_next) {
if (a->ai_canonname != NULL) {
ret = copy_hostname (context, a->ai_canonname, new_hostname);
if (ret) {
freeaddrinfo (ai);
return ret;
}
strlwr (*new_hostname);
ret = krb5_get_host_realm (context, *new_hostname, realms);
if (ret == 0) {
freeaddrinfo (ai);
return 0;
}
free (*new_hostname);
}
}
freeaddrinfo(ai);
return vanilla_hostname (context, orig_hostname, new_hostname, realms);
}
+719
View File
@@ -0,0 +1,719 @@
/*
* Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: fcache.c,v 1.52 2006/04/02 01:04:37 lha Exp $");
typedef struct krb5_fcache{
char *filename;
int version;
}krb5_fcache;
struct fcc_cursor {
int fd;
krb5_storage *sp;
};
#define KRB5_FCC_FVNO_1 1
#define KRB5_FCC_FVNO_2 2
#define KRB5_FCC_FVNO_3 3
#define KRB5_FCC_FVNO_4 4
#define FCC_TAG_DELTATIME 1
#define FCACHE(X) ((krb5_fcache*)(X)->data.data)
#define FILENAME(X) (FCACHE(X)->filename)
#define FCC_CURSOR(C) ((struct fcc_cursor*)(C))
static const char*
fcc_get_name(krb5_context context,
krb5_ccache id)
{
return FILENAME(id);
}
int
_krb5_xlock(krb5_context context, int fd, krb5_boolean exclusive,
const char *filename)
{
int ret;
#ifdef HAVE_FCNTL
struct flock l;
l.l_start = 0;
l.l_len = 0;
l.l_type = exclusive ? F_WRLCK : F_RDLCK;
l.l_whence = SEEK_SET;
ret = fcntl(fd, F_SETLKW, &l);
#else
ret = flock(fd, exclusive ? LOCK_EX : LOCK_SH);
#endif
if(ret < 0)
ret = errno;
if(ret == EACCES) /* fcntl can return EACCES instead of EAGAIN */
ret = EAGAIN;
switch (ret) {
case 0:
break;
case EINVAL: /* filesystem doesn't support locking, let the user have it */
ret = 0;
break;
case EAGAIN:
krb5_set_error_string(context, "timed out locking cache file %s",
filename);
break;
default:
krb5_set_error_string(context, "error locking cache file %s: %s",
filename, strerror(ret));
break;
}
return ret;
}
int
_krb5_xunlock(krb5_context context, int fd)
{
int ret;
#ifdef HAVE_FCNTL_LOCK
struct flock l;
l.l_start = 0;
l.l_len = 0;
l.l_type = F_UNLCK;
l.l_whence = SEEK_SET;
ret = fcntl(fd, F_SETLKW, &l);
#else
ret = flock(fd, LOCK_UN);
#endif
if (ret < 0)
ret = errno;
switch (ret) {
case 0:
break;
case EINVAL: /* filesystem doesn't support locking, let the user have it */
ret = 0;
break;
default:
krb5_set_error_string(context,
"Failed to unlock file: %s", strerror(ret));
break;
}
return ret;
}
static krb5_error_code
fcc_lock(krb5_context context, krb5_ccache id,
int fd, krb5_boolean exclusive)
{
return _krb5_xlock(context, fd, exclusive, fcc_get_name(context, id));
}
static krb5_error_code
fcc_unlock(krb5_context context, int fd)
{
return _krb5_xunlock(context, fd);
}
static krb5_error_code
fcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
{
krb5_fcache *f;
f = malloc(sizeof(*f));
if(f == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
f->filename = strdup(res);
if(f->filename == NULL){
free(f);
krb5_set_error_string(context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
f->version = 0;
(*id)->data.data = f;
(*id)->data.length = sizeof(*f);
return 0;
}
/*
* Try to scrub the contents of `filename' safely.
*/
static int
scrub_file (int fd)
{
off_t pos;
char buf[128];
pos = lseek(fd, 0, SEEK_END);
if (pos < 0)
return errno;
if (lseek(fd, 0, SEEK_SET) < 0)
return errno;
memset(buf, 0, sizeof(buf));
while(pos > 0) {
ssize_t tmp = write(fd, buf, min(sizeof(buf), pos));
if (tmp < 0)
return errno;
pos -= tmp;
}
fsync (fd);
return 0;
}
/*
* Erase `filename' if it exists, trying to remove the contents if
* it's `safe'. We always try to remove the file, it it exists. It's
* only overwritten if it's a regular file (not a symlink and not a
* hardlink)
*/
static krb5_error_code
erase_file(const char *filename)
{
int fd;
struct stat sb1, sb2;
int ret;
ret = lstat (filename, &sb1);
if (ret < 0)
return errno;
fd = open(filename, O_RDWR | O_BINARY);
if(fd < 0) {
if(errno == ENOENT)
return 0;
else
return errno;
}
if (unlink(filename) < 0) {
close (fd);
return errno;
}
ret = fstat (fd, &sb2);
if (ret < 0) {
close (fd);
return errno;
}
/* check if someone was playing with symlinks */
if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) {
close (fd);
return EPERM;
}
/* there are still hard links to this file */
if (sb2.st_nlink != 0) {
close (fd);
return 0;
}
ret = scrub_file (fd);
close (fd);
return ret;
}
static krb5_error_code
fcc_gen_new(krb5_context context, krb5_ccache *id)
{
krb5_fcache *f;
int fd;
char *file;
f = malloc(sizeof(*f));
if(f == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
asprintf (&file, "%sXXXXXX", KRB5_DEFAULT_CCFILE_ROOT);
if(file == NULL) {
free(f);
krb5_set_error_string(context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
fd = mkstemp(file);
if(fd < 0) {
int ret = errno;
krb5_set_error_string(context, "mkstemp %s", file);
free(f);
free(file);
return ret;
}
close(fd);
f->filename = file;
f->version = 0;
(*id)->data.data = f;
(*id)->data.length = sizeof(*f);
return 0;
}
static void
storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
{
int flags = 0;
switch(vno) {
case KRB5_FCC_FVNO_1:
flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS;
flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE;
flags |= KRB5_STORAGE_HOST_BYTEORDER;
break;
case KRB5_FCC_FVNO_2:
flags |= KRB5_STORAGE_HOST_BYTEORDER;
break;
case KRB5_FCC_FVNO_3:
flags |= KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE;
break;
case KRB5_FCC_FVNO_4:
break;
default:
krb5_abortx(context,
"storage_set_flags called with bad vno (%x)", vno);
}
krb5_storage_set_flags(sp, flags);
}
static krb5_error_code
fcc_open(krb5_context context,
krb5_ccache id,
int *fd_ret,
int flags,
mode_t mode)
{
krb5_boolean exclusive = ((flags | O_WRONLY) == flags ||
(flags | O_RDWR) == flags);
krb5_error_code ret;
const char *filename = FILENAME(id);
int fd;
fd = open(filename, flags, mode);
if(fd < 0) {
ret = errno;
krb5_set_error_string(context, "open(%s): %s", filename,
strerror(ret));
return ret;
}
if((ret = fcc_lock(context, id, fd, exclusive)) != 0) {
close(fd);
return ret;
}
*fd_ret = fd;
return 0;
}
static krb5_error_code
fcc_initialize(krb5_context context,
krb5_ccache id,
krb5_principal primary_principal)
{
krb5_fcache *f = FCACHE(id);
int ret = 0;
int fd;
char *filename = f->filename;
unlink (filename);
ret = fcc_open(context, id, &fd, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
if(ret)
return ret;
{
krb5_storage *sp;
sp = krb5_storage_from_fd(fd);
krb5_storage_set_eof_code(sp, KRB5_CC_END);
if(context->fcache_vno != 0)
f->version = context->fcache_vno;
else
f->version = KRB5_FCC_FVNO_4;
ret |= krb5_store_int8(sp, 5);
ret |= krb5_store_int8(sp, f->version);
storage_set_flags(context, sp, f->version);
if(f->version == KRB5_FCC_FVNO_4 && ret == 0) {
/* V4 stuff */
if (context->kdc_sec_offset) {
ret |= krb5_store_int16 (sp, 12); /* length */
ret |= krb5_store_int16 (sp, FCC_TAG_DELTATIME); /* Tag */
ret |= krb5_store_int16 (sp, 8); /* length of data */
ret |= krb5_store_int32 (sp, context->kdc_sec_offset);
ret |= krb5_store_int32 (sp, context->kdc_usec_offset);
} else {
ret |= krb5_store_int16 (sp, 0);
}
}
ret |= krb5_store_principal(sp, primary_principal);
krb5_storage_free(sp);
}
fcc_unlock(context, fd);
if (close(fd) < 0)
if (ret == 0) {
ret = errno;
krb5_set_error_string (context, "close %s: %s",
FILENAME(id), strerror(ret));
}
return ret;
}
static krb5_error_code
fcc_close(krb5_context context,
krb5_ccache id)
{
free (FILENAME(id));
krb5_data_free(&id->data);
return 0;
}
static krb5_error_code
fcc_destroy(krb5_context context,
krb5_ccache id)
{
erase_file(FILENAME(id));
return 0;
}
static krb5_error_code
fcc_store_cred(krb5_context context,
krb5_ccache id,
krb5_creds *creds)
{
int ret;
int fd;
ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY, 0);
if(ret)
return ret;
{
krb5_storage *sp;
sp = krb5_storage_from_fd(fd);
krb5_storage_set_eof_code(sp, KRB5_CC_END);
storage_set_flags(context, sp, FCACHE(id)->version);
if (!krb5_config_get_bool_default(context, NULL, TRUE,
"libdefaults",
"fcc-mit-ticketflags",
NULL))
krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER);
ret = krb5_store_creds(sp, creds);
krb5_storage_free(sp);
}
fcc_unlock(context, fd);
if (close(fd) < 0)
if (ret == 0) {
ret = errno;
krb5_set_error_string (context, "close %s: %s",
FILENAME(id), strerror(ret));
}
return ret;
}
static krb5_error_code
init_fcc (krb5_context context,
krb5_ccache id,
krb5_storage **ret_sp,
int *ret_fd)
{
int fd;
int8_t pvno, tag;
krb5_storage *sp;
krb5_error_code ret;
ret = fcc_open(context, id, &fd, O_RDONLY | O_BINARY, 0);
if(ret)
return ret;
sp = krb5_storage_from_fd(fd);
if(sp == NULL) {
krb5_clear_error_string(context);
ret = ENOMEM;
goto out;
}
krb5_storage_set_eof_code(sp, KRB5_CC_END);
ret = krb5_ret_int8(sp, &pvno);
if(ret != 0) {
if(ret == KRB5_CC_END)
ret = ENOENT; /* empty file */
krb5_clear_error_string(context);
goto out;
}
if(pvno != 5) {
krb5_set_error_string(context, "Bad version number in credential "
"cache file: %s", FILENAME(id));
ret = KRB5_CCACHE_BADVNO;
goto out;
}
ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */
if(ret != 0) {
krb5_clear_error_string(context);
ret = KRB5_CC_FORMAT;
goto out;
}
FCACHE(id)->version = tag;
storage_set_flags(context, sp, FCACHE(id)->version);
switch (tag) {
case KRB5_FCC_FVNO_4: {
int16_t length;
ret = krb5_ret_int16 (sp, &length);
if(ret) {
ret = KRB5_CC_FORMAT;
krb5_clear_error_string(context);
goto out;
}
while(length > 0) {
int16_t dtag, data_len;
int i;
int8_t dummy;
ret = krb5_ret_int16 (sp, &dtag);
if(ret) {
krb5_clear_error_string(context);
ret = KRB5_CC_FORMAT;
goto out;
}
ret = krb5_ret_int16 (sp, &data_len);
if(ret) {
krb5_clear_error_string(context);
ret = KRB5_CC_FORMAT;
goto out;
}
switch (dtag) {
case FCC_TAG_DELTATIME :
ret = krb5_ret_int32 (sp, &context->kdc_sec_offset);
if(ret) {
krb5_clear_error_string(context);
ret = KRB5_CC_FORMAT;
goto out;
}
ret = krb5_ret_int32 (sp, &context->kdc_usec_offset);
if(ret) {
krb5_clear_error_string(context);
ret = KRB5_CC_FORMAT;
goto out;
}
break;
default :
for (i = 0; i < data_len; ++i) {
ret = krb5_ret_int8 (sp, &dummy);
if(ret) {
krb5_clear_error_string(context);
ret = KRB5_CC_FORMAT;
goto out;
}
}
break;
}
length -= 4 + data_len;
}
break;
}
case KRB5_FCC_FVNO_3:
case KRB5_FCC_FVNO_2:
case KRB5_FCC_FVNO_1:
break;
default :
ret = KRB5_CCACHE_BADVNO;
krb5_set_error_string(context, "Unknown version number (%d) in "
"credential cache file: %s",
(int)tag, FILENAME(id));
goto out;
}
*ret_sp = sp;
*ret_fd = fd;
return 0;
out:
if(sp != NULL)
krb5_storage_free(sp);
fcc_unlock(context, fd);
close(fd);
return ret;
}
static krb5_error_code
fcc_get_principal(krb5_context context,
krb5_ccache id,
krb5_principal *principal)
{
krb5_error_code ret;
int fd;
krb5_storage *sp;
ret = init_fcc (context, id, &sp, &fd);
if (ret)
return ret;
ret = krb5_ret_principal(sp, principal);
if (ret)
krb5_clear_error_string(context);
krb5_storage_free(sp);
fcc_unlock(context, fd);
close(fd);
return ret;
}
static krb5_error_code
fcc_end_get (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor);
static krb5_error_code
fcc_get_first (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor)
{
krb5_error_code ret;
krb5_principal principal;
*cursor = malloc(sizeof(struct fcc_cursor));
if (*cursor == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
memset(*cursor, 0, sizeof(struct fcc_cursor));
ret = init_fcc (context, id, &FCC_CURSOR(*cursor)->sp,
&FCC_CURSOR(*cursor)->fd);
if (ret) {
free(*cursor);
*cursor = NULL;
return ret;
}
ret = krb5_ret_principal (FCC_CURSOR(*cursor)->sp, &principal);
if(ret) {
krb5_clear_error_string(context);
fcc_end_get(context, id, cursor);
return ret;
}
krb5_free_principal (context, principal);
fcc_unlock(context, FCC_CURSOR(*cursor)->fd);
return 0;
}
static krb5_error_code
fcc_get_next (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor,
krb5_creds *creds)
{
krb5_error_code ret;
if((ret = fcc_lock(context, id, FCC_CURSOR(*cursor)->fd, FALSE)) != 0)
return ret;
ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds);
if (ret)
krb5_clear_error_string(context);
fcc_unlock(context, FCC_CURSOR(*cursor)->fd);
return ret;
}
static krb5_error_code
fcc_end_get (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor)
{
krb5_storage_free(FCC_CURSOR(*cursor)->sp);
close (FCC_CURSOR(*cursor)->fd);
free(*cursor);
*cursor = NULL;
return 0;
}
static krb5_error_code
fcc_remove_cred(krb5_context context,
krb5_ccache id,
krb5_flags which,
krb5_creds *cred)
{
krb5_error_code ret;
krb5_ccache copy;
ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &copy);
if (ret)
return ret;
ret = krb5_cc_copy_cache(context, id, copy);
if (ret) {
krb5_cc_destroy(context, copy);
return ret;
}
ret = krb5_cc_remove_cred(context, copy, which, cred);
if (ret) {
krb5_cc_destroy(context, copy);
return ret;
}
fcc_destroy(context, id);
ret = krb5_cc_copy_cache(context, copy, id);
krb5_cc_destroy(context, copy);
return ret;
}
static krb5_error_code
fcc_set_flags(krb5_context context,
krb5_ccache id,
krb5_flags flags)
{
return 0; /* XXX */
}
static krb5_error_code
fcc_get_version(krb5_context context,
krb5_ccache id)
{
return FCACHE(id)->version;
}
const krb5_cc_ops krb5_fcc_ops = {
"FILE",
fcc_get_name,
fcc_resolve,
fcc_gen_new,
fcc_initialize,
fcc_destroy,
fcc_close,
fcc_store_cred,
NULL, /* fcc_retrieve */
fcc_get_principal,
fcc_get_first,
fcc_get_next,
fcc_end_get,
fcc_remove_cred,
fcc_set_flags,
fcc_get_version
};
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright (c) 1997 - 1999, 2004 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: free.c,v 1.8 2005/05/18 10:06:16 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *rep)
{
free_KDC_REP(&rep->kdc_rep);
free_EncTGSRepPart(&rep->enc_part);
free_KRB_ERROR(&rep->error);
memset(rep, 0, sizeof(*rep));
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_xfree (void *ptr)
{
free (ptr);
return 0;
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997, 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: free_host_realm.c,v 1.5 2004/05/25 21:25:02 lha Exp $");
/*
* Free all memory allocated by `realmlist'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_host_realm(krb5_context context,
krb5_realm *realmlist)
{
krb5_realm *p;
if(realmlist == NULL)
return 0;
for (p = realmlist; *p; ++p)
free (*p);
free (realmlist);
return 0;
}
@@ -0,0 +1,62 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: generate_seq_number.c,v 1.10 2006/05/05 09:28:06 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_seq_number(krb5_context context,
const krb5_keyblock *key,
uint32_t *seqno)
{
krb5_error_code ret;
krb5_keyblock *subkey;
uint32_t q;
u_char *p;
int i;
ret = krb5_generate_subkey (context, key, &subkey);
if (ret)
return ret;
q = 0;
for (p = (u_char *)subkey->keyvalue.data, i = 0;
i < subkey->keyvalue.length;
++i, ++p)
q = (q << 8) | *p;
q &= 0xffffffff;
*seqno = q;
krb5_free_keyblock (context, subkey);
return 0;
}
@@ -0,0 +1,72 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: generate_subkey.c,v 1.11 2005/01/05 02:39:21 lukeh Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_subkey(krb5_context context,
const krb5_keyblock *key,
krb5_keyblock **subkey)
{
return krb5_generate_subkey_extended(context, key, key->keytype, subkey);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_subkey_extended(krb5_context context,
const krb5_keyblock *key,
krb5_enctype etype,
krb5_keyblock **subkey)
{
krb5_error_code ret;
ALLOC(*subkey, 1);
if (*subkey == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
if (etype == ETYPE_NULL)
etype = key->keytype; /* use session key etype */
/* XXX should we use the session key as input to the RF? */
ret = krb5_generate_random_keyblock(context, etype, *subkey);
if (ret != 0) {
free(*subkey);
*subkey = NULL;
}
return ret;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,115 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: get_default_principal.c,v 1.10 2005/04/20 20:53:29 lha Exp $");
/*
* Try to find out what's a reasonable default principal.
*/
static const char*
get_env_user(void)
{
const char *user = getenv("USER");
if(user == NULL)
user = getenv("LOGNAME");
if(user == NULL)
user = getenv("USERNAME");
return user;
}
/*
* Will only use operating-system dependant operation to get the
* default principal, for use of functions that in ccache layer to
* avoid recursive calls.
*/
krb5_error_code
_krb5_get_default_principal_local (krb5_context context,
krb5_principal *princ)
{
krb5_error_code ret;
const char *user;
uid_t uid;
*princ = NULL;
uid = getuid();
if(uid == 0) {
user = getlogin();
if(user == NULL)
user = get_env_user();
if(user != NULL && strcmp(user, "root") != 0)
ret = krb5_make_principal(context, princ, NULL, user, "root", NULL);
else
ret = krb5_make_principal(context, princ, NULL, "root", NULL);
} else {
struct passwd *pw = getpwuid(uid);
if(pw != NULL)
user = pw->pw_name;
else {
user = get_env_user();
if(user == NULL)
user = getlogin();
}
if(user == NULL) {
krb5_set_error_string(context,
"unable to figure out current principal");
return ENOTTY; /* XXX */
}
ret = krb5_make_principal(context, princ, NULL, user, NULL);
}
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_default_principal (krb5_context context,
krb5_principal *princ)
{
krb5_error_code ret;
krb5_ccache id;
*princ = NULL;
ret = krb5_cc_default (context, &id);
if (ret == 0) {
ret = krb5_cc_get_principal (context, id, princ);
krb5_cc_close (context, id);
if (ret == 0)
return 0;
}
return _krb5_get_default_principal_local(context, princ);
}
@@ -0,0 +1,84 @@
/*
* Copyright (c) 1997 - 2001, 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: get_default_realm.c,v 1.13 2004/05/25 21:27:17 lha Exp $");
/*
* Return a NULL-terminated list of default realms in `realms'.
* Free this memory with krb5_free_host_realm.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_default_realms (krb5_context context,
krb5_realm **realms)
{
if (context->default_realms == NULL) {
krb5_error_code ret = krb5_set_default_realm (context, NULL);
if (ret)
return KRB5_CONFIG_NODEFREALM;
}
return krb5_copy_host_realm (context,
context->default_realms,
realms);
}
/*
* Return the first default realm. For compatibility.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_default_realm(krb5_context context,
krb5_realm *realm)
{
krb5_error_code ret;
char *res;
if (context->default_realms == NULL
|| context->default_realms[0] == NULL) {
krb5_clear_error_string(context);
ret = krb5_set_default_realm (context, NULL);
if (ret)
return ret;
}
res = strdup (context->default_realms[0]);
if (res == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
*realm = res;
return 0;
}
@@ -0,0 +1,426 @@
/*
* Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: get_for_creds.c,v 1.49 2006/04/10 09:28:15 lha Exp $");
static krb5_error_code
add_addrs(krb5_context context,
krb5_addresses *addr,
struct addrinfo *ai)
{
krb5_error_code ret;
unsigned n, i;
void *tmp;
struct addrinfo *a;
n = 0;
for (a = ai; a != NULL; a = a->ai_next)
++n;
tmp = realloc(addr->val, (addr->len + n) * sizeof(*addr->val));
if (tmp == NULL && (addr->len + n) != 0) {
krb5_set_error_string(context, "malloc: out of memory");
ret = ENOMEM;
goto fail;
}
addr->val = tmp;
for (i = addr->len; i < (addr->len + n); ++i) {
addr->val[i].addr_type = 0;
krb5_data_zero(&addr->val[i].address);
}
i = addr->len;
for (a = ai; a != NULL; a = a->ai_next) {
krb5_address ad;
ret = krb5_sockaddr2address (context, a->ai_addr, &ad);
if (ret == 0) {
if (krb5_address_search(context, &ad, addr))
krb5_free_address(context, &ad);
else
addr->val[i++] = ad;
}
else if (ret == KRB5_PROG_ATYPE_NOSUPP)
krb5_clear_error_string (context);
else
goto fail;
addr->len = i;
}
return 0;
fail:
krb5_free_addresses (context, addr);
return ret;
}
/*
* Forward credentials for `client' to host `hostname`,
* making them forwardable if `forwardable', and returning the
* blob of data to sent in `out_data'.
* If hostname == NULL, pick it from `server'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_fwd_tgt_creds (krb5_context context,
krb5_auth_context auth_context,
const char *hostname,
krb5_principal client,
krb5_principal server,
krb5_ccache ccache,
int forwardable,
krb5_data *out_data)
{
krb5_flags flags = 0;
krb5_creds creds;
krb5_error_code ret;
krb5_const_realm client_realm;
flags |= KDC_OPT_FORWARDED;
if (forwardable)
flags |= KDC_OPT_FORWARDABLE;
if (hostname == NULL &&
krb5_principal_get_type(context, server) == KRB5_NT_SRV_HST) {
const char *inst = krb5_principal_get_comp_string(context, server, 0);
const char *host = krb5_principal_get_comp_string(context, server, 1);
if (inst != NULL &&
strcmp(inst, "host") == 0 &&
host != NULL &&
krb5_principal_get_comp_string(context, server, 2) == NULL)
hostname = host;
}
client_realm = krb5_principal_get_realm(context, client);
memset (&creds, 0, sizeof(creds));
creds.client = client;
ret = krb5_build_principal(context,
&creds.server,
strlen(client_realm),
client_realm,
KRB5_TGS_NAME,
client_realm,
NULL);
if (ret)
return ret;
ret = krb5_get_forwarded_creds (context,
auth_context,
ccache,
flags,
hostname,
&creds,
out_data);
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_forwarded_creds (krb5_context context,
krb5_auth_context auth_context,
krb5_ccache ccache,
krb5_flags flags,
const char *hostname,
krb5_creds *in_creds,
krb5_data *out_data)
{
krb5_error_code ret;
krb5_creds *out_creds;
krb5_addresses addrs, *paddrs;
KRB_CRED cred;
KrbCredInfo *krb_cred_info;
EncKrbCredPart enc_krb_cred_part;
size_t len;
unsigned char *buf;
size_t buf_size;
krb5_kdc_flags kdc_flags;
krb5_crypto crypto;
struct addrinfo *ai;
int save_errno;
krb5_creds *ticket;
char *realm;
realm = in_creds->client->realm;
addrs.len = 0;
addrs.val = NULL;
paddrs = &addrs;
{
krb5_boolean noaddr;
krb5_appdefault_boolean(context, NULL, realm,
"no-addresses", KRB5_ADDRESSLESS_DEFAULT,
&noaddr);
if (noaddr)
paddrs = NULL;
}
/*
* If tickets are address-less, forward address-less tickets.
*/
if (paddrs) {
ret = _krb5_get_krbtgt (context,
ccache,
realm,
&ticket);
if(ret == 0) {
if (ticket->addresses.len == 0)
paddrs = NULL;
krb5_free_creds (context, ticket);
}
}
if (paddrs != NULL) {
ret = getaddrinfo (hostname, NULL, NULL, &ai);
if (ret) {
save_errno = errno;
krb5_set_error_string(context, "resolving %s: %s",
hostname, gai_strerror(ret));
return krb5_eai_to_heim_errno(ret, save_errno);
}
ret = add_addrs (context, &addrs, ai);
freeaddrinfo (ai);
if (ret)
return ret;
}
kdc_flags.b = int2KDCOptions(flags);
ret = krb5_get_kdc_cred (context,
ccache,
kdc_flags,
paddrs,
NULL,
in_creds,
&out_creds);
krb5_free_addresses (context, &addrs);
if (ret) {
return ret;
}
memset (&cred, 0, sizeof(cred));
cred.pvno = 5;
cred.msg_type = krb_cred;
ALLOC_SEQ(&cred.tickets, 1);
if (cred.tickets.val == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto out2;
}
ret = decode_Ticket(out_creds->ticket.data,
out_creds->ticket.length,
cred.tickets.val, &len);
if (ret)
goto out3;
memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1);
if (enc_krb_cred_part.ticket_info.val == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto out4;
}
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_timestamp sec;
int32_t usec;
krb5_us_timeofday (context, &sec, &usec);
ALLOC(enc_krb_cred_part.timestamp, 1);
if (enc_krb_cred_part.timestamp == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto out4;
}
*enc_krb_cred_part.timestamp = sec;
ALLOC(enc_krb_cred_part.usec, 1);
if (enc_krb_cred_part.usec == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto out4;
}
*enc_krb_cred_part.usec = usec;
} else {
enc_krb_cred_part.timestamp = NULL;
enc_krb_cred_part.usec = NULL;
}
if (auth_context->local_address && auth_context->local_port && paddrs) {
ret = krb5_make_addrport (context,
&enc_krb_cred_part.s_address,
auth_context->local_address,
auth_context->local_port);
if (ret)
goto out4;
}
if (auth_context->remote_address) {
if (auth_context->remote_port) {
krb5_boolean noaddr;
krb5_const_realm srealm;
srealm = krb5_principal_get_realm(context, out_creds->server);
/* Is this correct, and should we use the paddrs == NULL
trick here as well? Having an address-less ticket may
indicate that we don't know our own global address, but
it does not necessary mean that we don't know the
server's. */
krb5_appdefault_boolean(context, NULL, srealm, "no-addresses",
FALSE, &noaddr);
if (!noaddr) {
ret = krb5_make_addrport (context,
&enc_krb_cred_part.r_address,
auth_context->remote_address,
auth_context->remote_port);
if (ret)
goto out4;
}
} else {
ALLOC(enc_krb_cred_part.r_address, 1);
if (enc_krb_cred_part.r_address == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto out4;
}
ret = krb5_copy_address (context, auth_context->remote_address,
enc_krb_cred_part.r_address);
if (ret)
goto out4;
}
}
/* fill ticket_info.val[0] */
enc_krb_cred_part.ticket_info.len = 1;
krb_cred_info = enc_krb_cred_part.ticket_info.val;
copy_EncryptionKey (&out_creds->session, &krb_cred_info->key);
ALLOC(krb_cred_info->prealm, 1);
copy_Realm (&out_creds->client->realm, krb_cred_info->prealm);
ALLOC(krb_cred_info->pname, 1);
copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname);
ALLOC(krb_cred_info->flags, 1);
*krb_cred_info->flags = out_creds->flags.b;
ALLOC(krb_cred_info->authtime, 1);
*krb_cred_info->authtime = out_creds->times.authtime;
ALLOC(krb_cred_info->starttime, 1);
*krb_cred_info->starttime = out_creds->times.starttime;
ALLOC(krb_cred_info->endtime, 1);
*krb_cred_info->endtime = out_creds->times.endtime;
ALLOC(krb_cred_info->renew_till, 1);
*krb_cred_info->renew_till = out_creds->times.renew_till;
ALLOC(krb_cred_info->srealm, 1);
copy_Realm (&out_creds->server->realm, krb_cred_info->srealm);
ALLOC(krb_cred_info->sname, 1);
copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname);
ALLOC(krb_cred_info->caddr, 1);
copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr);
krb5_free_creds (context, out_creds);
/* encode EncKrbCredPart */
ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size,
&enc_krb_cred_part, &len, ret);
free_EncKrbCredPart (&enc_krb_cred_part);
if (ret) {
free_KRB_CRED(&cred);
return ret;
}
if(buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) {
cred.enc_part.etype = ENCTYPE_NULL;
cred.enc_part.kvno = NULL;
cred.enc_part.cipher.data = buf;
cred.enc_part.cipher.length = buf_size;
} else {
/*
* Here older versions then 0.7.2 of Heimdal used the local or
* remote subkey. That is wrong, the session key should be
* used. Heimdal 0.7.2 and newer have code to try both in the
* receiving end.
*/
ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
if (ret) {
free(buf);
free_KRB_CRED(&cred);
return ret;
}
ret = krb5_encrypt_EncryptedData (context,
crypto,
KRB5_KU_KRB_CRED,
buf,
len,
0,
&cred.enc_part);
free(buf);
krb5_crypto_destroy(context, crypto);
if (ret) {
free_KRB_CRED(&cred);
return ret;
}
}
ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret);
free_KRB_CRED (&cred);
if (ret)
return ret;
if(buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
out_data->length = len;
out_data->data = buf;
return 0;
out4:
free_EncKrbCredPart(&enc_krb_cred_part);
out3:
free_KRB_CRED(&cred);
out2:
krb5_free_creds (context, out_creds);
return ret;
}
@@ -0,0 +1,257 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include <resolve.h>
RCSID("$Id: get_host_realm.c,v 1.37 2006/10/17 19:28:36 lha Exp $");
/* To automagically find the correct realm of a host (without
* [domain_realm] in krb5.conf) add a text record for your domain with
* the name of your realm, like this:
*
* _kerberos IN TXT "FOO.SE"
*
* The search is recursive, so you can add entries for specific
* hosts. To find the realm of host a.b.c, it first tries
* _kerberos.a.b.c, then _kerberos.b.c and so on.
*
* This method is described in draft-ietf-cat-krb-dns-locate-03.txt.
*
*/
static int
copy_txt_to_realms (struct resource_record *head,
krb5_realm **realms)
{
struct resource_record *rr;
int n, i;
for(n = 0, rr = head; rr; rr = rr->next)
if (rr->type == T_TXT)
++n;
if (n == 0)
return -1;
*realms = malloc ((n + 1) * sizeof(krb5_realm));
if (*realms == NULL)
return -1;
for (i = 0; i < n + 1; ++i)
(*realms)[i] = NULL;
for (i = 0, rr = head; rr; rr = rr->next) {
if (rr->type == T_TXT) {
char *tmp;
tmp = strdup(rr->u.txt);
if (tmp == NULL) {
for (i = 0; i < n; ++i)
free ((*realms)[i]);
free (*realms);
return -1;
}
(*realms)[i] = tmp;
++i;
}
}
return 0;
}
static int
dns_find_realm(krb5_context context,
const char *domain,
krb5_realm **realms)
{
static const char *default_labels[] = { "_kerberos", NULL };
char dom[MAXHOSTNAMELEN];
struct dns_reply *r;
const char **labels;
char **config_labels;
int i, ret;
config_labels = krb5_config_get_strings(context, NULL, "libdefaults",
"dns_lookup_realm_labels", NULL);
if(config_labels != NULL)
labels = (const char **)config_labels;
else
labels = default_labels;
if(*domain == '.')
domain++;
for (i = 0; labels[i] != NULL; i++) {
ret = snprintf(dom, sizeof(dom), "%s.%s.", labels[i], domain);
if(ret < 0 || ret >= sizeof(dom)) {
if (config_labels)
krb5_config_free_strings(config_labels);
return -1;
}
r = dns_lookup(dom, "TXT");
if(r != NULL) {
ret = copy_txt_to_realms (r->head, realms);
dns_free_data(r);
if(ret == 0) {
if (config_labels)
krb5_config_free_strings(config_labels);
return 0;
}
}
}
if (config_labels)
krb5_config_free_strings(config_labels);
return -1;
}
/*
* Try to figure out what realms host in `domain' belong to from the
* configuration file.
*/
static int
config_find_realm(krb5_context context,
const char *domain,
krb5_realm **realms)
{
char **tmp = krb5_config_get_strings (context, NULL,
"domain_realm",
domain,
NULL);
if (tmp == NULL)
return -1;
*realms = tmp;
return 0;
}
/*
* This function assumes that `host' is a FQDN (and doesn't handle the
* special case of host == NULL either).
* Try to find mapping in the config file or DNS and it that fails,
* fall back to guessing
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_get_host_realm_int (krb5_context context,
const char *host,
krb5_boolean use_dns,
krb5_realm **realms)
{
const char *p, *q;
krb5_boolean dns_locate_enable;
dns_locate_enable = krb5_config_get_bool_default(context, NULL, TRUE,
"libdefaults", "dns_lookup_realm", NULL);
for (p = host; p != NULL; p = strchr (p + 1, '.')) {
if(config_find_realm(context, p, realms) == 0) {
if(strcasecmp(*realms[0], "dns_locate") == 0) {
if(use_dns)
for (q = host; q != NULL; q = strchr(q + 1, '.'))
if(dns_find_realm(context, q, realms) == 0)
return 0;
continue;
} else
return 0;
}
else if(use_dns && dns_locate_enable) {
if(dns_find_realm(context, p, realms) == 0)
return 0;
}
}
p = strchr(host, '.');
if(p != NULL) {
p++;
*realms = malloc(2 * sizeof(krb5_realm));
if (*realms == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
(*realms)[0] = strdup(p);
if((*realms)[0] == NULL) {
free(*realms);
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
strupr((*realms)[0]);
(*realms)[1] = NULL;
return 0;
}
krb5_set_error_string(context, "unable to find realm of host %s", host);
return KRB5_ERR_HOST_REALM_UNKNOWN;
}
/*
* Return the realm(s) of `host' as a NULL-terminated list in
* `realms'. Free `realms' with krb5_free_host_realm().
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_host_realm(krb5_context context,
const char *targethost,
krb5_realm **realms)
{
const char *host = targethost;
char hostname[MAXHOSTNAMELEN];
krb5_error_code ret;
int use_dns;
if (host == NULL) {
if (gethostname (hostname, sizeof(hostname))) {
*realms = NULL;
return errno;
}
host = hostname;
}
/*
* If our local hostname is without components, don't even try to dns.
*/
use_dns = (strchr(host, '.') != NULL);
ret = _krb5_get_host_realm_int (context, host, use_dns, realms);
if (ret && targethost != NULL) {
/*
* If there was no realm mapping for the host (and we wasn't
* looking for ourself), guess at the local realm, maybe our
* KDC knows better then we do and we get a referral back.
*/
ret = krb5_get_default_realms(context, realms);
if (ret) {
krb5_set_error_string(context, "Unable to find realm of host %s",
host);
return KRB5_ERR_HOST_REALM_UNKNOWN;
}
}
return ret;
}
+852
View File
@@ -0,0 +1,852 @@
/*
* Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: get_in_tkt.c,v 1.119 2006/10/06 17:05:08 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_init_etype (krb5_context context,
unsigned *len,
krb5_enctype **val,
const krb5_enctype *etypes)
{
int i;
krb5_error_code ret;
krb5_enctype *tmp = NULL;
ret = 0;
if (etypes == NULL) {
ret = krb5_get_default_in_tkt_etypes(context,
&tmp);
if (ret)
return ret;
etypes = tmp;
}
for (i = 0; etypes[i]; ++i)
;
*len = i;
*val = malloc(i * sizeof(**val));
if (i != 0 && *val == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto cleanup;
}
memmove (*val,
etypes,
i * sizeof(*tmp));
cleanup:
if (tmp != NULL)
free (tmp);
return ret;
}
static krb5_error_code
decrypt_tkt (krb5_context context,
krb5_keyblock *key,
krb5_key_usage usage,
krb5_const_pointer decrypt_arg,
krb5_kdc_rep *dec_rep)
{
krb5_error_code ret;
krb5_data data;
size_t size;
krb5_crypto crypto;
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret)
return ret;
ret = krb5_decrypt_EncryptedData (context,
crypto,
usage,
&dec_rep->kdc_rep.enc_part,
&data);
krb5_crypto_destroy(context, crypto);
if (ret)
return ret;
ret = krb5_decode_EncASRepPart(context,
data.data,
data.length,
&dec_rep->enc_part,
&size);
if (ret)
ret = krb5_decode_EncTGSRepPart(context,
data.data,
data.length,
&dec_rep->enc_part,
&size);
krb5_data_free (&data);
if (ret)
return ret;
return 0;
}
int
_krb5_extract_ticket(krb5_context context,
krb5_kdc_rep *rep,
krb5_creds *creds,
krb5_keyblock *key,
krb5_const_pointer keyseed,
krb5_key_usage key_usage,
krb5_addresses *addrs,
unsigned nonce,
krb5_boolean allow_server_mismatch,
krb5_boolean ignore_cname,
krb5_decrypt_proc decrypt_proc,
krb5_const_pointer decryptarg)
{
krb5_error_code ret;
krb5_principal tmp_principal, srv_principal = NULL;
int tmp;
size_t len;
time_t tmp_time;
krb5_timestamp sec_now;
/*
* HACK:
* this is really a ugly hack, to support using the Netbios Domain Name
* as realm against windows KDC's, they always return the full realm
* based on the DNS Name.
*/
allow_server_mismatch = 1;
ignore_cname = 1;
ret = _krb5_principalname2krb5_principal (context,
&tmp_principal,
rep->kdc_rep.cname,
rep->kdc_rep.crealm);
if (ret)
goto out;
/* compare client */
if (!ignore_cname) {
tmp = krb5_principal_compare (context, tmp_principal, creds->client);
if (!tmp) {
krb5_free_principal (context, tmp_principal);
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_MODIFIED;
goto out;
}
}
krb5_free_principal (context, creds->client);
creds->client = tmp_principal;
/* extract ticket */
ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
&rep->kdc_rep.ticket, &len, ret);
if(ret)
goto out;
if (creds->ticket.length != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
creds->second_ticket.length = 0;
creds->second_ticket.data = NULL;
/* decrypt */
if (decrypt_proc == NULL)
decrypt_proc = decrypt_tkt;
ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
if (ret)
goto out;
#if 0
/* XXX should this decode be here, or in the decrypt_proc? */
ret = krb5_decode_keyblock(context, &rep->enc_part.key, 1);
if(ret)
goto out;
#endif
/* compare server */
ret = _krb5_principalname2krb5_principal (context,
&srv_principal,
rep->kdc_rep.ticket.sname,
rep->kdc_rep.ticket.realm);
if (ret)
goto out;
ret = _krb5_principalname2krb5_principal (context,
&tmp_principal,
rep->enc_part.sname,
rep->enc_part.srealm);
if (ret)
goto out;
/*
* see if the service principal matches in the ticket
* and in the enc_part
*/
tmp = krb5_principal_compare (context, tmp_principal, srv_principal);
krb5_free_principal (context, tmp_principal);
if (!tmp) {
ret = KRB5KRB_AP_ERR_MODIFIED;
krb5_clear_error_string (context);
goto out;
}
if(allow_server_mismatch){
krb5_free_principal(context, creds->server);
creds->server = srv_principal;
srv_principal = NULL;
}else{
tmp = krb5_principal_compare (context, srv_principal, creds->server);
if (!tmp) {
ret = KRB5KRB_AP_ERR_MODIFIED;
krb5_clear_error_string (context);
goto out;
}
}
/* compare nonces */
if (nonce != rep->enc_part.nonce) {
ret = KRB5KRB_AP_ERR_MODIFIED;
krb5_set_error_string(context, "malloc: out of memory");
goto out;
}
/* set kdc-offset */
krb5_timeofday (context, &sec_now);
if (rep->enc_part.flags.initial
&& context->kdc_sec_offset == 0
&& krb5_config_get_bool (context, NULL,
"libdefaults",
"kdc_timesync",
NULL)) {
context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
krb5_timeofday (context, &sec_now);
}
/* check all times */
if (rep->enc_part.starttime) {
tmp_time = *rep->enc_part.starttime;
} else
tmp_time = rep->enc_part.authtime;
if (creds->times.starttime == 0
&& abs(tmp_time - sec_now) > context->max_skew) {
ret = KRB5KRB_AP_ERR_SKEW;
krb5_set_error_string (context,
"time skew (%d) larger than max (%d)",
abs(tmp_time - sec_now),
(int)context->max_skew);
goto out;
}
if (creds->times.starttime != 0
&& tmp_time != creds->times.starttime) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_MODIFIED;
goto out;
}
creds->times.starttime = tmp_time;
if (rep->enc_part.renew_till) {
tmp_time = *rep->enc_part.renew_till;
} else
tmp_time = 0;
if (creds->times.renew_till != 0
&& tmp_time > creds->times.renew_till) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_MODIFIED;
goto out;
}
creds->times.renew_till = tmp_time;
creds->times.authtime = rep->enc_part.authtime;
if (creds->times.endtime != 0
&& rep->enc_part.endtime > creds->times.endtime) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_MODIFIED;
goto out;
}
creds->times.endtime = rep->enc_part.endtime;
if(rep->enc_part.caddr)
krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
else if(addrs)
krb5_copy_addresses (context, addrs, &creds->addresses);
else {
creds->addresses.len = 0;
creds->addresses.val = NULL;
}
creds->flags.b = rep->enc_part.flags;
creds->authdata.len = 0;
creds->authdata.val = NULL;
creds->session.keyvalue.length = 0;
creds->session.keyvalue.data = NULL;
creds->session.keytype = rep->enc_part.key.keytype;
ret = krb5_data_copy (&creds->session.keyvalue,
rep->enc_part.key.keyvalue.data,
rep->enc_part.key.keyvalue.length);
out:
memset (rep->enc_part.key.keyvalue.data, 0,
rep->enc_part.key.keyvalue.length);
if (srv_principal)
krb5_free_principal (context, srv_principal);
return ret;
}
static krb5_error_code
make_pa_enc_timestamp(krb5_context context, PA_DATA *pa,
krb5_enctype etype, krb5_keyblock *key)
{
PA_ENC_TS_ENC p;
unsigned char *buf;
size_t buf_size;
size_t len;
EncryptedData encdata;
krb5_error_code ret;
int32_t usec;
int usec2;
krb5_crypto crypto;
krb5_us_timeofday (context, &p.patimestamp, &usec);
usec2 = usec;
p.pausec = &usec2;
ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
if (ret)
return ret;
if(buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret) {
free(buf);
return ret;
}
ret = krb5_encrypt_EncryptedData(context,
crypto,
KRB5_KU_PA_ENC_TIMESTAMP,
buf,
len,
0,
&encdata);
free(buf);
krb5_crypto_destroy(context, crypto);
if (ret)
return ret;
ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
free_EncryptedData(&encdata);
if (ret)
return ret;
if(buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
pa->padata_value.length = len;
pa->padata_value.data = buf;
return 0;
}
static krb5_error_code
add_padata(krb5_context context,
METHOD_DATA *md,
krb5_principal client,
krb5_key_proc key_proc,
krb5_const_pointer keyseed,
krb5_enctype *enctypes,
unsigned netypes,
krb5_salt *salt)
{
krb5_error_code ret;
PA_DATA *pa2;
krb5_salt salt2;
krb5_enctype *ep;
int i;
if(salt == NULL) {
/* default to standard salt */
ret = krb5_get_pw_salt (context, client, &salt2);
salt = &salt2;
}
if (!enctypes) {
enctypes = context->etypes;
netypes = 0;
for (ep = enctypes; *ep != ETYPE_NULL; ep++)
netypes++;
}
pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val));
if (pa2 == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
md->val = pa2;
for (i = 0; i < netypes; ++i) {
krb5_keyblock *key;
ret = (*key_proc)(context, enctypes[i], *salt, keyseed, &key);
if (ret)
continue;
ret = make_pa_enc_timestamp (context, &md->val[md->len],
enctypes[i], key);
krb5_free_keyblock (context, key);
if (ret)
return ret;
++md->len;
}
if(salt == &salt2)
krb5_free_salt(context, salt2);
return 0;
}
static krb5_error_code
init_as_req (krb5_context context,
KDCOptions opts,
krb5_creds *creds,
const krb5_addresses *addrs,
const krb5_enctype *etypes,
const krb5_preauthtype *ptypes,
const krb5_preauthdata *preauth,
krb5_key_proc key_proc,
krb5_const_pointer keyseed,
unsigned nonce,
AS_REQ *a)
{
krb5_error_code ret;
krb5_salt salt;
memset(a, 0, sizeof(*a));
a->pvno = 5;
a->msg_type = krb_as_req;
a->req_body.kdc_options = opts;
a->req_body.cname = malloc(sizeof(*a->req_body.cname));
if (a->req_body.cname == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto fail;
}
a->req_body.sname = malloc(sizeof(*a->req_body.sname));
if (a->req_body.sname == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto fail;
}
ret = _krb5_principal2principalname (a->req_body.cname, creds->client);
if (ret)
goto fail;
ret = _krb5_principal2principalname (a->req_body.sname, creds->server);
if (ret)
goto fail;
ret = copy_Realm(&creds->client->realm, &a->req_body.realm);
if (ret)
goto fail;
if(creds->times.starttime) {
a->req_body.from = malloc(sizeof(*a->req_body.from));
if (a->req_body.from == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto fail;
}
*a->req_body.from = creds->times.starttime;
}
if(creds->times.endtime){
ALLOC(a->req_body.till, 1);
*a->req_body.till = creds->times.endtime;
}
if(creds->times.renew_till){
a->req_body.rtime = malloc(sizeof(*a->req_body.rtime));
if (a->req_body.rtime == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto fail;
}
*a->req_body.rtime = creds->times.renew_till;
}
a->req_body.nonce = nonce;
ret = krb5_init_etype (context,
&a->req_body.etype.len,
&a->req_body.etype.val,
etypes);
if (ret)
goto fail;
/*
* This means no addresses
*/
if (addrs && addrs->len == 0) {
a->req_body.addresses = NULL;
} else {
a->req_body.addresses = malloc(sizeof(*a->req_body.addresses));
if (a->req_body.addresses == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto fail;
}
if (addrs)
ret = krb5_copy_addresses(context, addrs, a->req_body.addresses);
else {
ret = krb5_get_all_client_addrs (context, a->req_body.addresses);
if(ret == 0 && a->req_body.addresses->len == 0) {
free(a->req_body.addresses);
a->req_body.addresses = NULL;
}
}
if (ret)
return ret;
}
a->req_body.enc_authorization_data = NULL;
a->req_body.additional_tickets = NULL;
if(preauth != NULL) {
int i;
ALLOC(a->padata, 1);
if(a->padata == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto fail;
}
a->padata->val = NULL;
a->padata->len = 0;
for(i = 0; i < preauth->len; i++) {
if(preauth->val[i].type == KRB5_PADATA_ENC_TIMESTAMP){
int j;
for(j = 0; j < preauth->val[i].info.len; j++) {
krb5_salt *sp = &salt;
if(preauth->val[i].info.val[j].salttype)
salt.salttype = *preauth->val[i].info.val[j].salttype;
else
salt.salttype = KRB5_PW_SALT;
if(preauth->val[i].info.val[j].salt)
salt.saltvalue = *preauth->val[i].info.val[j].salt;
else
if(salt.salttype == KRB5_PW_SALT)
sp = NULL;
else
krb5_data_zero(&salt.saltvalue);
ret = add_padata(context, a->padata, creds->client,
key_proc, keyseed,
&preauth->val[i].info.val[j].etype, 1,
sp);
if (ret == 0)
break;
}
}
}
} else
/* not sure this is the way to use `ptypes' */
if (ptypes == NULL || *ptypes == KRB5_PADATA_NONE)
a->padata = NULL;
else if (*ptypes == KRB5_PADATA_ENC_TIMESTAMP) {
ALLOC(a->padata, 1);
if (a->padata == NULL) {
ret = ENOMEM;
krb5_set_error_string(context, "malloc: out of memory");
goto fail;
}
a->padata->len = 0;
a->padata->val = NULL;
/* make a v5 salted pa-data */
add_padata(context, a->padata, creds->client,
key_proc, keyseed, a->req_body.etype.val,
a->req_body.etype.len, NULL);
/* make a v4 salted pa-data */
salt.salttype = KRB5_PW_SALT;
krb5_data_zero(&salt.saltvalue);
add_padata(context, a->padata, creds->client,
key_proc, keyseed, a->req_body.etype.val,
a->req_body.etype.len, &salt);
} else {
krb5_set_error_string (context, "pre-auth type %d not supported",
*ptypes);
ret = KRB5_PREAUTH_BAD_TYPE;
goto fail;
}
return 0;
fail:
free_AS_REQ(a);
return ret;
}
static int
set_ptypes(krb5_context context,
KRB_ERROR *error,
const krb5_preauthtype **ptypes,
krb5_preauthdata **preauth)
{
static krb5_preauthdata preauth2;
static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE };
if(error->e_data) {
METHOD_DATA md;
int i;
decode_METHOD_DATA(error->e_data->data,
error->e_data->length,
&md,
NULL);
for(i = 0; i < md.len; i++){
switch(md.val[i].padata_type){
case KRB5_PADATA_ENC_TIMESTAMP:
*ptypes = ptypes2;
break;
case KRB5_PADATA_ETYPE_INFO:
*preauth = &preauth2;
ALLOC_SEQ(*preauth, 1);
(*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP;
krb5_decode_ETYPE_INFO(context,
md.val[i].padata_value.data,
md.val[i].padata_value.length,
&(*preauth)->val[0].info,
NULL);
break;
default:
break;
}
}
free_METHOD_DATA(&md);
} else {
*ptypes = ptypes2;
}
return(1);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_in_cred(krb5_context context,
krb5_flags options,
const krb5_addresses *addrs,
const krb5_enctype *etypes,
const krb5_preauthtype *ptypes,
const krb5_preauthdata *preauth,
krb5_key_proc key_proc,
krb5_const_pointer keyseed,
krb5_decrypt_proc decrypt_proc,
krb5_const_pointer decryptarg,
krb5_creds *creds,
krb5_kdc_rep *ret_as_reply)
{
krb5_error_code ret;
AS_REQ a;
krb5_kdc_rep rep;
krb5_data req, resp;
size_t len;
krb5_salt salt;
krb5_keyblock *key;
size_t size;
KDCOptions opts;
PA_DATA *pa;
krb5_enctype etype;
krb5_preauthdata *my_preauth = NULL;
unsigned nonce;
int done;
opts = int2KDCOptions(options);
krb5_generate_random_block (&nonce, sizeof(nonce));
nonce &= 0xffffffff;
do {
done = 1;
ret = init_as_req (context,
opts,
creds,
addrs,
etypes,
ptypes,
preauth,
key_proc,
keyseed,
nonce,
&a);
if (my_preauth) {
free_ETYPE_INFO(&my_preauth->val[0].info);
free (my_preauth->val);
my_preauth = NULL;
}
if (ret)
return ret;
ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, &a, &len, ret);
free_AS_REQ(&a);
if (ret)
return ret;
if(len != req.length)
krb5_abortx(context, "internal error in ASN.1 encoder");
ret = krb5_sendto_kdc (context, &req, &creds->client->realm, &resp);
krb5_data_free(&req);
if (ret)
return ret;
memset (&rep, 0, sizeof(rep));
ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
if(ret) {
/* let's try to parse it as a KRB-ERROR */
KRB_ERROR error;
int ret2;
ret2 = krb5_rd_error(context, &resp, &error);
if(ret2 && resp.data && ((char*)resp.data)[0] == 4)
ret = KRB5KRB_AP_ERR_V4_REPLY;
krb5_data_free(&resp);
if (ret2 == 0) {
ret = krb5_error_from_rd_error(context, &error, creds);
/* if no preauth was set and KDC requires it, give it
one more try */
if (!ptypes && !preauth
&& ret == KRB5KDC_ERR_PREAUTH_REQUIRED
#if 0
|| ret == KRB5KDC_ERR_BADOPTION
#endif
&& set_ptypes(context, &error, &ptypes, &my_preauth)) {
done = 0;
preauth = my_preauth;
krb5_free_error_contents(context, &error);
krb5_clear_error_string(context);
continue;
}
if(ret_as_reply)
ret_as_reply->error = error;
else
free_KRB_ERROR (&error);
return ret;
}
return ret;
}
krb5_data_free(&resp);
} while(!done);
pa = NULL;
etype = rep.kdc_rep.enc_part.etype;
if(rep.kdc_rep.padata){
int i = 0;
pa = krb5_find_padata(rep.kdc_rep.padata->val, rep.kdc_rep.padata->len,
KRB5_PADATA_PW_SALT, &i);
if(pa == NULL) {
i = 0;
pa = krb5_find_padata(rep.kdc_rep.padata->val,
rep.kdc_rep.padata->len,
KRB5_PADATA_AFS3_SALT, &i);
}
}
if(pa) {
salt.salttype = pa->padata_type;
salt.saltvalue = pa->padata_value;
ret = (*key_proc)(context, etype, salt, keyseed, &key);
} else {
/* make a v5 salted pa-data */
ret = krb5_get_pw_salt (context, creds->client, &salt);
if (ret)
goto out;
ret = (*key_proc)(context, etype, salt, keyseed, &key);
krb5_free_salt(context, salt);
}
if (ret)
goto out;
ret = _krb5_extract_ticket(context,
&rep,
creds,
key,
keyseed,
KRB5_KU_AS_REP_ENC_PART,
NULL,
nonce,
FALSE,
opts.request_anonymous,
decrypt_proc,
decryptarg);
memset (key->keyvalue.data, 0, key->keyvalue.length);
krb5_free_keyblock_contents (context, key);
free (key);
out:
if (ret == 0 && ret_as_reply)
*ret_as_reply = rep;
else
krb5_free_kdc_rep (context, &rep);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_in_tkt(krb5_context context,
krb5_flags options,
const krb5_addresses *addrs,
const krb5_enctype *etypes,
const krb5_preauthtype *ptypes,
krb5_key_proc key_proc,
krb5_const_pointer keyseed,
krb5_decrypt_proc decrypt_proc,
krb5_const_pointer decryptarg,
krb5_creds *creds,
krb5_ccache ccache,
krb5_kdc_rep *ret_as_reply)
{
krb5_error_code ret;
ret = krb5_get_in_cred (context,
options,
addrs,
etypes,
ptypes,
NULL,
key_proc,
keyseed,
decrypt_proc,
decryptarg,
creds,
ret_as_reply);
if(ret)
return ret;
if (ccache)
ret = krb5_cc_store_cred (context, ccache, creds);
return ret;
}
@@ -0,0 +1,99 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: get_in_tkt_with_keytab.c,v 1.9 2005/06/17 04:56:44 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
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;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_in_tkt_with_keytab (krb5_context context,
krb5_flags options,
krb5_addresses *addrs,
const krb5_enctype *etypes,
const krb5_preauthtype *pre_auth_types,
krb5_keytab keytab,
krb5_ccache ccache,
krb5_creds *creds,
krb5_kdc_rep *ret_as_reply)
{
krb5_keytab_key_proc_args a;
a.principal = creds->client;
a.keytab = keytab;
return krb5_get_in_tkt (context,
options,
addrs,
etypes,
pre_auth_types,
krb5_keytab_key_proc,
&a,
NULL,
NULL,
creds,
ccache,
ret_as_reply);
}
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright (c) 1997-2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: get_port.c,v 1.9 2004/05/25 21:29:59 lha Exp $");
int KRB5_LIB_FUNCTION
krb5_getportbyname (krb5_context context,
const char *service,
const char *proto,
int default_port)
{
struct servent *sp;
if ((sp = roken_getservbyname (service, proto)) == NULL) {
#if 0
krb5_warnx(context, "%s/%s unknown service, using default port %d",
service, proto, default_port);
#endif
return htons(default_port);
} else
return sp->s_port;
}
+44
View File
@@ -0,0 +1,44 @@
#
# Error messages for the krb5 library
#
# This might look like a com_err file, but is not
#
id "$Id: heim_err.et,v 1.13 2004/02/13 16:23:40 lha Exp $"
error_table heim
prefix HEIM_ERR
error_code LOG_PARSE, "Error parsing log destination"
error_code V4_PRINC_NO_CONV, "Failed to convert v4 principal"
error_code SALTTYPE_NOSUPP, "Salt type is not supported by enctype"
error_code NOHOST, "Host not found"
error_code OPNOTSUPP, "Operation not supported"
error_code EOF, "End of file"
error_code BAD_MKEY, "Failed to get the master key"
error_code SERVICE_NOMATCH, "Unacceptable service used"
index 64
prefix HEIM_PKINIT
error_code NO_CERTIFICATE, "Certificate missing"
error_code NO_PRIVATE_KEY, "Private key missing"
error_code NO_VALID_CA, "No valid certificate authority"
error_code CERTIFICATE_INVALID, "Certificate invalid"
error_code PRIVATE_KEY_INVALID, "Private key invalid"
index 128
prefix HEIM_EAI
#error_code NOERROR, "no error"
error_code UNKNOWN, "unknown error from getaddrinfo"
error_code ADDRFAMILY, "address family for nodename not supported"
error_code AGAIN, "temporary failure in name resolution"
error_code BADFLAGS, "invalid value for ai_flags"
error_code FAIL, "non-recoverable failure in name resolution"
error_code FAMILY, "ai_family not supported"
error_code MEMORY, "memory allocation failure"
error_code NODATA, "no address associated with nodename"
error_code NONAME, "nodename nor servname provided, or not known"
error_code SERVICE, "servname not supported for ai_socktype"
error_code SOCKTYPE, "ai_socktype not supported"
error_code SYSTEM, "system error returned in errno"
end
+175
View File
@@ -0,0 +1,175 @@
/*
* Copyright (c) 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $Id: heim_threads.h,v 1.11 2004/12/18 16:03:38 lha Exp $ */
/*
* Provide wrapper macros for thread synchronization primitives so we
* can use native thread functions for those operating system that
* supports it.
*
* This is so libkrb5.so (or more importantly, libgssapi.so) can have
* thread support while the program that that dlopen(3)s the library
* don't need to be linked to libpthread.
*/
#ifndef HEIM_THREADS_H
#define HEIM_THREADS_H 1
/* assume headers already included */
#if defined(__NetBSD__) && __NetBSD_Version__ >= 106120000 && __NetBSD_Version__< 299001200 && defined(ENABLE_PTHREAD_SUPPORT)
/*
* NetBSD have a thread lib that we can use that part of libc that
* works regardless if application are linked to pthreads or not.
* NetBSD newer then 2.99.11 just use pthread.h, and the same thing
* will happen.
*/
#include <threadlib.h>
#define HEIMDAL_MUTEX mutex_t
#define HEIMDAL_MUTEX_INITIALIZER MUTEX_INITIALIZER
#define HEIMDAL_MUTEX_init(m) mutex_init(m, NULL)
#define HEIMDAL_MUTEX_lock(m) mutex_lock(m)
#define HEIMDAL_MUTEX_unlock(m) mutex_unlock(m)
#define HEIMDAL_MUTEX_destroy(m) mutex_destroy(m)
#define HEIMDAL_RWLOCK rwlock_t
#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER
#define HEIMDAL_RWLOCK_init(l) rwlock_init(l, NULL)
#define HEIMDAL_RWLOCK_rdlock(l) rwlock_rdlock(l)
#define HEIMDAL_RWLOCK_wrlock(l) rwlock_wrlock(l)
#define HEIMDAL_RWLOCK_tryrdlock(l) rwlock_tryrdlock(l)
#define HEIMDAL_RWLOCK_trywrlock(l) rwlock_trywrlock(l)
#define HEIMDAL_RWLOCK_unlock(l) rwlock_unlock(l)
#define HEIMDAL_RWLOCK_destroy(l) rwlock_destroy(l)
#define HEIMDAL_thread_key thread_key_t
#define HEIMDAL_key_create(k,d,r) do { r = thr_keycreate(k,d); } while(0)
#define HEIMDAL_setspecific(k,s,r) do { r = thr_setspecific(k,s); } while(0)
#define HEIMDAL_getspecific(k) thr_getspecific(k)
#define HEIMDAL_key_delete(k) thr_keydelete(k)
#elif defined(ENABLE_PTHREAD_SUPPORT) && (!defined(__NetBSD__) || __NetBSD_Version__ >= 299001200)
#include <pthread.h>
#define HEIMDAL_MUTEX pthread_mutex_t
#define HEIMDAL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define HEIMDAL_MUTEX_init(m) pthread_mutex_init(m, NULL)
#define HEIMDAL_MUTEX_lock(m) pthread_mutex_lock(m)
#define HEIMDAL_MUTEX_unlock(m) pthread_mutex_unlock(m)
#define HEIMDAL_MUTEX_destroy(m) pthread_mutex_destroy(m)
#define HEIMDAL_RWLOCK rwlock_t
#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER
#define HEIMDAL_RWLOCK_init(l) pthread_rwlock_init(l, NULL)
#define HEIMDAL_RWLOCK_rdlock(l) pthread_rwlock_rdlock(l)
#define HEIMDAL_RWLOCK_wrlock(l) pthread_rwlock_wrlock(l)
#define HEIMDAL_RWLOCK_tryrdlock(l) pthread_rwlock_tryrdlock(l)
#define HEIMDAL_RWLOCK_trywrlock(l) pthread_rwlock_trywrlock(l)
#define HEIMDAL_RWLOCK_unlock(l) pthread_rwlock_unlock(l)
#define HEIMDAL_RWLOCK_destroy(l) pthread_rwlock_destroy(l)
#define HEIMDAL_thread_key pthread_key_t
#define HEIMDAL_key_create(k,d,r) do { r = pthread_key_create(k,d); } while(0)
#define HEIMDAL_setspecific(k,s,r) do { r = pthread_setspecific(k,s); } while(0)
#define HEIMDAL_getspecific(k) pthread_getspecific(k)
#define HEIMDAL_key_delete(k) pthread_key_delete(k)
#elif defined(HEIMDAL_DEBUG_THREADS)
/* no threads support, just do consistency checks */
#include <stdlib.h>
#define HEIMDAL_MUTEX int
#define HEIMDAL_MUTEX_INITIALIZER 0
#define HEIMDAL_MUTEX_init(m) do { (*(m)) = 0; } while(0)
#define HEIMDAL_MUTEX_lock(m) do { if ((*(m))++ != 0) abort(); } while(0)
#define HEIMDAL_MUTEX_unlock(m) do { if ((*(m))-- != 1) abort(); } while(0)
#define HEIMDAL_MUTEX_destroy(m) do {if ((*(m)) != 0) abort(); } while(0)
#define HEIMDAL_RWLOCK rwlock_t int
#define HEIMDAL_RWLOCK_INITIALIZER 0
#define HEIMDAL_RWLOCK_init(l) do { } while(0)
#define HEIMDAL_RWLOCK_rdlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_wrlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_trywrlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_unlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_destroy(l) do { } while(0)
#define HEIMDAL_internal_thread_key 1
#else /* no thread support, no debug case */
#define HEIMDAL_MUTEX int
#define HEIMDAL_MUTEX_INITIALIZER 0
#define HEIMDAL_MUTEX_init(m) do { (void)(m); } while(0)
#define HEIMDAL_MUTEX_lock(m) do { (void)(m); } while(0)
#define HEIMDAL_MUTEX_unlock(m) do { (void)(m); } while(0)
#define HEIMDAL_MUTEX_destroy(m) do { (void)(m); } while(0)
#define HEIMDAL_RWLOCK rwlock_t int
#define HEIMDAL_RWLOCK_INITIALIZER 0
#define HEIMDAL_RWLOCK_init(l) do { } while(0)
#define HEIMDAL_RWLOCK_rdlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_wrlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_trywrlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_unlock(l) do { } while(0)
#define HEIMDAL_RWLOCK_destroy(l) do { } while(0)
#define HEIMDAL_internal_thread_key 1
#endif /* no thread support */
#ifdef HEIMDAL_internal_thread_key
typedef struct heim_thread_key {
void *value;
void (*destructor)(void *);
} heim_thread_key;
#define HEIMDAL_thread_key heim_thread_key
#define HEIMDAL_key_create(k,d,r) \
do { (k)->value = NULL; (k)->destructor = (d); r = 0; } while(0)
#define HEIMDAL_setspecific(k,s,r) do { (k).value = s ; r = 0; } while(0)
#define HEIMDAL_getspecific(k) ((k).value)
#define HEIMDAL_key_delete(k) do { (*(k).destructor)((k).value); } while(0)
#undef HEIMDAL_internal_thread_key
#endif /* HEIMDAL_internal_thread_key */
#endif /* HEIM_THREADS_H */
+409
View File
@@ -0,0 +1,409 @@
/*
* Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: init_creds.c,v 1.28 2006/09/04 14:28:54 lha Exp $");
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
{
memset (opt, 0, sizeof(*opt));
opt->flags = 0;
opt->opt_private = NULL;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_alloc(krb5_context context,
krb5_get_init_creds_opt **opt)
{
krb5_get_init_creds_opt *o;
*opt = NULL;
o = calloc(1, sizeof(*o));
if (o == NULL) {
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
krb5_get_init_creds_opt_init(o);
o->opt_private = calloc(1, sizeof(*o->opt_private));
if (o->opt_private == NULL) {
krb5_set_error_string(context, "out of memory");
free(o);
return ENOMEM;
}
o->opt_private->refcount = 1;
*opt = o;
return 0;
}
krb5_error_code
_krb5_get_init_creds_opt_copy(krb5_context context,
const krb5_get_init_creds_opt *in,
krb5_get_init_creds_opt **out)
{
krb5_get_init_creds_opt *opt;
*out = NULL;
opt = calloc(1, sizeof(*opt));
if (opt == NULL) {
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
if (in)
*opt = *in;
if(opt->opt_private == NULL) {
opt->opt_private = calloc(1, sizeof(*opt->opt_private));
if (opt->opt_private == NULL) {
krb5_set_error_string(context, "out of memory");
free(opt);
return ENOMEM;
}
opt->opt_private->refcount = 1;
} else
opt->opt_private->refcount++;
*out = opt;
return 0;
}
void KRB5_LIB_FUNCTION
_krb5_get_init_creds_opt_free_krb5_error(krb5_get_init_creds_opt *opt)
{
if (opt->opt_private == NULL || opt->opt_private->error == NULL)
return;
free_KRB_ERROR(opt->opt_private->error);
free(opt->opt_private->error);
opt->opt_private->error = NULL;
}
void KRB5_LIB_FUNCTION
_krb5_get_init_creds_opt_set_krb5_error(krb5_context context,
krb5_get_init_creds_opt *opt,
const KRB_ERROR *error)
{
krb5_error_code ret;
if (opt->opt_private == NULL)
return;
_krb5_get_init_creds_opt_free_krb5_error(opt);
opt->opt_private->error = malloc(sizeof(*opt->opt_private->error));
if (opt->opt_private->error == NULL)
return;
ret = copy_KRB_ERROR(error, opt->opt_private->error);
if (ret) {
free(opt->opt_private->error);
opt->opt_private->error = NULL;
}
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt)
{
if (opt->opt_private == NULL)
return;
if (opt->opt_private->refcount < 1) /* abort ? */
return;
if (--opt->opt_private->refcount == 0) {
_krb5_get_init_creds_opt_free_krb5_error(opt);
_krb5_get_init_creds_opt_free_pkinit(opt);
free(opt->opt_private);
}
memset(opt, 0, sizeof(*opt));
free(opt);
}
static int
get_config_time (krb5_context context,
const char *realm,
const char *name,
int def)
{
int ret;
ret = krb5_config_get_time (context, NULL,
"realms",
realm,
name,
NULL);
if (ret >= 0)
return ret;
ret = krb5_config_get_time (context, NULL,
"libdefaults",
name,
NULL);
if (ret >= 0)
return ret;
return def;
}
static krb5_boolean
get_config_bool (krb5_context context,
const char *realm,
const char *name)
{
return krb5_config_get_bool (context,
NULL,
"realms",
realm,
name,
NULL)
|| krb5_config_get_bool (context,
NULL,
"libdefaults",
name,
NULL);
}
/*
* set all the values in `opt' to the appropriate values for
* application `appname' (default to getprogname() if NULL), and realm
* `realm'. First looks in [appdefaults] but falls back to
* [realms] or [libdefaults] for some of the values.
*/
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_default_flags(krb5_context context,
const char *appname,
krb5_const_realm realm,
krb5_get_init_creds_opt *opt)
{
krb5_boolean b;
time_t t;
b = get_config_bool (context, realm, "forwardable");
krb5_appdefault_boolean(context, appname, realm, "forwardable", b, &b);
krb5_get_init_creds_opt_set_forwardable(opt, b);
b = get_config_bool (context, realm, "proxiable");
krb5_appdefault_boolean(context, appname, realm, "proxiable", b, &b);
krb5_get_init_creds_opt_set_proxiable (opt, b);
krb5_appdefault_time(context, appname, realm, "ticket_lifetime", 0, &t);
if (t == 0)
t = get_config_time (context, realm, "ticket_lifetime", 0);
if(t != 0)
krb5_get_init_creds_opt_set_tkt_life(opt, t);
krb5_appdefault_time(context, appname, realm, "renew_lifetime", 0, &t);
if (t == 0)
t = get_config_time (context, realm, "renew_lifetime", 0);
if(t != 0)
krb5_get_init_creds_opt_set_renew_life(opt, t);
krb5_appdefault_boolean(context, appname, realm, "no-addresses",
FALSE, &b);
if (b)
krb5_get_init_creds_opt_set_addressless (context, opt, TRUE);
#if 0
krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b);
krb5_get_init_creds_opt_set_anonymous (opt, b);
krb5_get_init_creds_opt_set_etype_list(opt, enctype,
etype_str.num_strings);
krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt,
krb5_data *salt);
krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt,
krb5_preauthtype *preauth_list,
int preauth_list_length);
#endif
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt,
krb5_deltat tkt_life)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE;
opt->tkt_life = tkt_life;
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt,
krb5_deltat renew_life)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE;
opt->renew_life = renew_life;
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt,
int forwardable)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE;
opt->forwardable = forwardable;
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt,
int proxiable)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE;
opt->proxiable = proxiable;
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt,
krb5_enctype *etype_list,
int etype_list_length)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST;
opt->etype_list = etype_list;
opt->etype_list_length = etype_list_length;
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt,
krb5_addresses *addresses)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST;
opt->address_list = addresses;
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt,
krb5_preauthtype *preauth_list,
int preauth_list_length)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST;
opt->preauth_list_length = preauth_list_length;
opt->preauth_list = preauth_list;
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt,
krb5_data *salt)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT;
opt->salt = salt;
}
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt,
int anonymous)
{
opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS;
opt->anonymous = anonymous;
}
static krb5_error_code
require_ext_opt(krb5_context context,
krb5_get_init_creds_opt *opt,
const char *type)
{
if (opt->opt_private == NULL) {
krb5_set_error_string(context, "%s on non extendable opt", type);
return EINVAL;
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_pa_password(krb5_context context,
krb5_get_init_creds_opt *opt,
const char *password,
krb5_s2k_proc key_proc)
{
krb5_error_code ret;
ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password");
if (ret)
return ret;
opt->opt_private->password = password;
opt->opt_private->key_proc = key_proc;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_pac_request(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_boolean req_pac)
{
krb5_error_code ret;
ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req");
if (ret)
return ret;
opt->opt_private->req_pac = req_pac ?
KRB5_INIT_CREDS_TRISTATE_TRUE :
KRB5_INIT_CREDS_TRISTATE_FALSE;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_get_error(krb5_context context,
krb5_get_init_creds_opt *opt,
KRB_ERROR **error)
{
krb5_error_code ret;
*error = NULL;
ret = require_ext_opt(context, opt, "init_creds_opt_get_error");
if (ret)
return ret;
if (opt->opt_private->error == NULL)
return 0;
*error = malloc(sizeof(**error));
if (*error == NULL) {
krb5_set_error_string(context, "malloc - out memory");
return ENOMEM;
}
ret = copy_KRB_ERROR(*error, opt->opt_private->error);
if (ret)
krb5_clear_error_string(context);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_addressless(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_boolean addressless)
{
krb5_error_code ret;
ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req");
if (ret)
return ret;
if (addressless)
opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_TRUE;
else
opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_FALSE;
return 0;
}
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
#
# Error messages for the k524 functions
#
# This might look like a com_err file, but is not
#
id "$Id: k524_err.et,v 1.1 2001/06/20 02:44:11 joda Exp $"
error_table k524
prefix KRB524
error_code BADKEY, "wrong keytype in ticket"
error_code BADADDR, "incorrect network address"
error_code BADPRINC, "cannot convert V5 principal" #unused
error_code BADREALM, "V5 realm name longer than V4 maximum" #unused
error_code V4ERR, "kerberos V4 error server"
error_code ENCFULL, "encoding too large at server"
error_code DECEMPTY, "decoding out of data" #unused
error_code NOTRESP, "service not responding" #unused
end
File diff suppressed because it is too large Load Diff
+133
View File
@@ -0,0 +1,133 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: keyblock.c,v 1.17 2005/05/18 04:21:31 lha Exp $");
void KRB5_LIB_FUNCTION
krb5_keyblock_zero(krb5_keyblock *keyblock)
{
keyblock->keytype = 0;
krb5_data_zero(&keyblock->keyvalue);
}
void KRB5_LIB_FUNCTION
krb5_free_keyblock_contents(krb5_context context,
krb5_keyblock *keyblock)
{
if(keyblock) {
if (keyblock->keyvalue.data != NULL)
memset(keyblock->keyvalue.data, 0, keyblock->keyvalue.length);
krb5_data_free (&keyblock->keyvalue);
keyblock->keytype = ENCTYPE_NULL;
}
}
void KRB5_LIB_FUNCTION
krb5_free_keyblock(krb5_context context,
krb5_keyblock *keyblock)
{
if(keyblock){
krb5_free_keyblock_contents(context, keyblock);
free(keyblock);
}
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_keyblock_contents (krb5_context context,
const krb5_keyblock *inblock,
krb5_keyblock *to)
{
return copy_EncryptionKey(inblock, to);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_keyblock (krb5_context context,
const krb5_keyblock *inblock,
krb5_keyblock **to)
{
krb5_keyblock *k;
k = malloc (sizeof(*k));
if (k == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
*to = k;
return krb5_copy_keyblock_contents (context, inblock, k);
}
krb5_enctype
krb5_keyblock_get_enctype(const krb5_keyblock *block)
{
return block->keytype;
}
/*
* Fill in `key' with key data of type `enctype' from `data' of length
* `size'. Key should be freed using krb5_free_keyblock_contents.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_keyblock_init(krb5_context context,
krb5_enctype type,
const void *data,
size_t size,
krb5_keyblock *key)
{
krb5_error_code ret;
size_t len;
memset(key, 0, sizeof(*key));
ret = krb5_enctype_keysize(context, type, &len);
if (ret)
return ret;
if (len != size) {
krb5_set_error_string(context, "Encryption key %d is %lu bytes "
"long, %lu was passed in",
type, (unsigned long)len, (unsigned long)size);
return KRB5_PROG_ETYPE_NOSUPP;
}
ret = krb5_data_copy(&key->keyvalue, data, len);
if(ret) {
krb5_set_error_string(context, "malloc failed: %lu",
(unsigned long)len);
return ret;
}
key->keytype = type;
return 0;
}
+527
View File
@@ -0,0 +1,527 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: keytab.c,v 1.63 2005/11/25 21:46:40 lha Exp $");
/*
* Register a new keytab in `ops'
* Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_register(krb5_context context,
const krb5_kt_ops *ops)
{
struct krb5_keytab_data *tmp;
if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) {
krb5_set_error_string(context, "krb5_kt_register; prefix too long");
return KRB5_KT_BADNAME;
}
tmp = realloc(context->kt_types,
(context->num_kt_types + 1) * sizeof(*context->kt_types));
if(tmp == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
memcpy(&tmp[context->num_kt_types], ops,
sizeof(tmp[context->num_kt_types]));
context->kt_types = tmp;
context->num_kt_types++;
return 0;
}
/*
* Resolve the keytab name (of the form `type:residual') in `name'
* into a keytab in `id'.
* Return 0 or an error
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_resolve(krb5_context context,
const char *name,
krb5_keytab *id)
{
krb5_keytab k;
int i;
const char *type, *residual;
size_t type_len;
krb5_error_code ret;
residual = strchr(name, ':');
if(residual == NULL) {
type = "FILE";
type_len = strlen(type);
residual = name;
} else {
type = name;
type_len = residual - name;
residual++;
}
for(i = 0; i < context->num_kt_types; i++) {
if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0)
break;
}
if(i == context->num_kt_types) {
krb5_set_error_string(context, "unknown keytab type %.*s",
(int)type_len, type);
return KRB5_KT_UNKNOWN_TYPE;
}
k = malloc (sizeof(*k));
if (k == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
memcpy(k, &context->kt_types[i], sizeof(*k));
k->data = NULL;
ret = (*k->resolve)(context, residual, k);
if(ret) {
free(k);
k = NULL;
}
*id = k;
return ret;
}
/*
* copy the name of the default keytab into `name'.
* Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_default_name(krb5_context context, char *name, size_t namesize)
{
if (strlcpy (name, context->default_keytab, namesize) >= namesize) {
krb5_clear_error_string (context);
return KRB5_CONFIG_NOTENUFSPACE;
}
return 0;
}
/*
* copy the name of the default modify keytab into `name'.
* Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize)
{
const char *kt = NULL;
if(context->default_keytab_modify == NULL) {
if(strncasecmp(context->default_keytab, "ANY:", 4) != 0)
kt = context->default_keytab;
else {
size_t len = strcspn(context->default_keytab + 4, ",");
if(len >= namesize) {
krb5_clear_error_string(context);
return KRB5_CONFIG_NOTENUFSPACE;
}
strlcpy(name, context->default_keytab + 4, namesize);
name[len] = '\0';
return 0;
}
} else
kt = context->default_keytab_modify;
if (strlcpy (name, kt, namesize) >= namesize) {
krb5_clear_error_string (context);
return KRB5_CONFIG_NOTENUFSPACE;
}
return 0;
}
/*
* Set `id' to the default keytab.
* Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_default(krb5_context context, krb5_keytab *id)
{
return krb5_kt_resolve (context, context->default_keytab, id);
}
/*
* Read the key identified by `(principal, vno, enctype)' from the
* keytab in `keyprocarg' (the default if == NULL) into `*key'.
* Return 0 or an error.
*/
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;
}
/*
* Return the type of the `keytab' in the string `prefix of length
* `prefixsize'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_get_type(krb5_context context,
krb5_keytab keytab,
char *prefix,
size_t prefixsize)
{
strlcpy(prefix, keytab->prefix, prefixsize);
return 0;
}
/*
* Retrieve the name of the keytab `keytab' into `name', `namesize'
* Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_get_name(krb5_context context,
krb5_keytab keytab,
char *name,
size_t namesize)
{
return (*keytab->get_name)(context, keytab, name, namesize);
}
/*
* Retrieve the full name of the keytab `keytab' and store the name in
* `str'. `str' needs to be freed by the caller using free(3).
* Returns 0 or an error. On error, *str is set to NULL.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_get_full_name(krb5_context context,
krb5_keytab keytab,
char **str)
{
char type[KRB5_KT_PREFIX_MAX_LEN];
char name[MAXPATHLEN];
krb5_error_code ret;
*str = NULL;
ret = krb5_kt_get_type(context, keytab, type, sizeof(type));
if (ret)
return ret;
ret = krb5_kt_get_name(context, keytab, name, sizeof(name));
if (ret)
return ret;
if (asprintf(str, "%s:%s", type, name) == -1) {
krb5_set_error_string(context, "malloc - out of memory");
*str = NULL;
return ENOMEM;
}
return 0;
}
/*
* Finish using the keytab in `id'. All resources will be released,
* even on errors. Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_close(krb5_context context,
krb5_keytab id)
{
krb5_error_code ret;
ret = (*id->close)(context, id);
memset(id, 0, sizeof(*id));
free(id);
return ret;
}
/*
* Compare `entry' against `principal, vno, enctype'.
* Any of `principal, vno, enctype' might be 0 which acts as a wildcard.
* Return TRUE if they compare the same, FALSE otherwise.
*/
krb5_boolean KRB5_LIB_FUNCTION
krb5_kt_compare(krb5_context context,
krb5_keytab_entry *entry,
krb5_const_principal principal,
krb5_kvno vno,
krb5_enctype enctype)
{
if(principal != NULL &&
!krb5_principal_compare(context, entry->principal, principal))
return FALSE;
if(vno && vno != entry->vno)
return FALSE;
if(enctype && enctype != entry->keyblock.keytype)
return FALSE;
return TRUE;
}
/*
* Retrieve the keytab entry for `principal, kvno, enctype' into `entry'
* from the keytab `id'.
* kvno == 0 is a wildcard and gives the keytab with the highest vno.
* Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_get_entry(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) {
krb5_clear_error_string(context);
return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */
}
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) {
return 0;
} else {
char princ[256], kt_name[256], kvno_str[25];
char *enctype_str = NULL;
krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
krb5_kt_get_name (context, id, kt_name, sizeof(kt_name));
krb5_enctype_to_string(context, enctype, &enctype_str);
if (kvno)
snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
else
kvno_str[0] = '\0';
krb5_set_error_string (context,
"failed to find %s%s in keytab %s (%s)",
princ,
kvno_str,
kt_name,
enctype_str ? enctype_str : "unknown enctype");
free(enctype_str);
return KRB5_KT_NOTFOUND;
}
}
/*
* Copy the contents of `in' into `out'.
* Return 0 or an error. */
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;
}
/*
* Free the contents of `entry'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_free_entry(krb5_context context,
krb5_keytab_entry *entry)
{
krb5_free_principal (context, entry->principal);
krb5_free_keyblock_contents (context, &entry->keyblock);
memset(entry, 0, sizeof(*entry));
return 0;
}
/*
* Set `cursor' to point at the beginning of `id'.
* Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_start_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
if(id->start_seq_get == NULL) {
krb5_set_error_string(context,
"start_seq_get is not supported in the %s "
" keytab", id->prefix);
return HEIM_ERR_OPNOTSUPP;
}
return (*id->start_seq_get)(context, id, cursor);
}
/*
* Get the next entry from `id' pointed to by `cursor' and advance the
* `cursor'.
* Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_next_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry,
krb5_kt_cursor *cursor)
{
if(id->next_entry == NULL) {
krb5_set_error_string(context,
"next_entry is not supported in the %s "
" keytab", id->prefix);
return HEIM_ERR_OPNOTSUPP;
}
return (*id->next_entry)(context, id, entry, cursor);
}
/*
* Release all resources associated with `cursor'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_end_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
if(id->end_seq_get == NULL) {
krb5_set_error_string(context,
"end_seq_get is not supported in the %s "
" keytab", id->prefix);
return HEIM_ERR_OPNOTSUPP;
}
return (*id->end_seq_get)(context, id, cursor);
}
/*
* Add the entry in `entry' to the keytab `id'.
* Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_add_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
if(id->add == NULL) {
krb5_set_error_string(context, "Add is not supported in the %s keytab",
id->prefix);
return KRB5_KT_NOWRITE;
}
entry->timestamp = time(NULL);
return (*id->add)(context, id,entry);
}
/*
* Remove the entry `entry' from the keytab `id'.
* Return 0 or an error.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_remove_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
if(id->remove == NULL) {
krb5_set_error_string(context,
"Remove is not supported in the %s keytab",
id->prefix);
return KRB5_KT_NOWRITE;
}
return (*id->remove)(context, id, entry);
}
+255
View File
@@ -0,0 +1,255 @@
/*
* Copyright (c) 2001-2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: keytab_any.c,v 1.8 2006/04/10 09:20:13 lha Exp $");
struct any_data {
krb5_keytab kt;
char *name;
struct any_data *next;
};
static void
free_list (krb5_context context, struct any_data *a)
{
struct any_data *next;
for (; a != NULL; a = next) {
next = a->next;
free (a->name);
if(a->kt)
krb5_kt_close(context, a->kt);
free (a);
}
}
static krb5_error_code
any_resolve(krb5_context context, const char *name, krb5_keytab id)
{
struct any_data *a, *a0 = NULL, *prev = NULL;
krb5_error_code ret;
char buf[256];
while (strsep_copy(&name, ",", buf, sizeof(buf)) != -1) {
a = malloc(sizeof(*a));
if (a == NULL) {
ret = ENOMEM;
goto fail;
}
if (a0 == NULL) {
a0 = a;
a->name = strdup(buf);
if (a->name == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
ret = ENOMEM;
goto fail;
}
} else
a->name = NULL;
if (prev != NULL)
prev->next = a;
a->next = NULL;
ret = krb5_kt_resolve (context, buf, &a->kt);
if (ret)
goto fail;
prev = a;
}
if (a0 == NULL) {
krb5_set_error_string(context, "empty ANY: keytab");
return ENOENT;
}
id->data = a0;
return 0;
fail:
free_list (context, a0);
return ret;
}
static krb5_error_code
any_get_name (krb5_context context,
krb5_keytab id,
char *name,
size_t namesize)
{
struct any_data *a = id->data;
strlcpy(name, a->name, namesize);
return 0;
}
static krb5_error_code
any_close (krb5_context context,
krb5_keytab id)
{
struct any_data *a = id->data;
free_list (context, a);
return 0;
}
struct any_cursor_extra_data {
struct any_data *a;
krb5_kt_cursor cursor;
};
static krb5_error_code
any_start_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *c)
{
struct any_data *a = id->data;
struct any_cursor_extra_data *ed;
krb5_error_code ret;
c->data = malloc (sizeof(struct any_cursor_extra_data));
if(c->data == NULL){
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
ed = (struct any_cursor_extra_data *)c->data;
ed->a = a;
ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
if (ret) {
free (c->data);
c->data = NULL;
return ret;
}
return 0;
}
static krb5_error_code
any_next_entry (krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry,
krb5_kt_cursor *cursor)
{
krb5_error_code ret, ret2;
struct any_cursor_extra_data *ed;
ed = (struct any_cursor_extra_data *)cursor->data;
do {
ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor);
if (ret == 0)
return 0;
else if (ret != KRB5_KT_END)
return ret;
ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor);
if (ret2)
return ret2;
while ((ed->a = ed->a->next) != NULL) {
ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
if (ret2 == 0)
break;
}
if (ed->a == NULL) {
krb5_clear_error_string (context);
return KRB5_KT_END;
}
} while (1);
}
static krb5_error_code
any_end_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
krb5_error_code ret = 0;
struct any_cursor_extra_data *ed;
ed = (struct any_cursor_extra_data *)cursor->data;
if (ed->a != NULL)
ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor);
free (ed);
cursor->data = NULL;
return ret;
}
static krb5_error_code
any_add_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
struct any_data *a = id->data;
krb5_error_code ret;
while(a != NULL) {
ret = krb5_kt_add_entry(context, a->kt, entry);
if(ret != 0 && ret != KRB5_KT_NOWRITE) {
krb5_set_error_string(context, "failed to add entry to %s",
a->name);
return ret;
}
a = a->next;
}
return 0;
}
static krb5_error_code
any_remove_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
struct any_data *a = id->data;
krb5_error_code ret;
int found = 0;
while(a != NULL) {
ret = krb5_kt_remove_entry(context, a->kt, entry);
if(ret == 0)
found++;
else {
if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) {
krb5_set_error_string(context, "failed to remove entry from %s",
a->name);
return ret;
}
}
a = a->next;
}
if(!found)
return KRB5_KT_NOTFOUND;
return 0;
}
const krb5_kt_ops krb5_any_ops = {
"ANY",
any_resolve,
any_get_name,
any_close,
NULL, /* get */
any_start_seq_get,
any_next_entry,
any_end_seq_get,
any_add_entry,
any_remove_entry
};
+696
View File
@@ -0,0 +1,696 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: keytab_file.c,v 1.23 2006/05/05 12:36:57 lha Exp $");
#define KRB5_KT_VNO_1 1
#define KRB5_KT_VNO_2 2
#define KRB5_KT_VNO KRB5_KT_VNO_2
#define KRB5_KT_FL_JAVA 1
/* file operations -------------------------------------------- */
struct fkt_data {
char *filename;
int flags;
};
static krb5_error_code
krb5_kt_ret_data(krb5_context context,
krb5_storage *sp,
krb5_data *data)
{
int ret;
int16_t size;
ret = krb5_ret_int16(sp, &size);
if(ret)
return ret;
data->length = size;
data->data = malloc(size);
if (data->data == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
ret = krb5_storage_read(sp, data->data, size);
if(ret != size)
return (ret < 0)? errno : KRB5_KT_END;
return 0;
}
static krb5_error_code
krb5_kt_ret_string(krb5_context context,
krb5_storage *sp,
heim_general_string *data)
{
int ret;
int16_t size;
ret = krb5_ret_int16(sp, &size);
if(ret)
return ret;
*data = malloc(size + 1);
if (*data == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
ret = krb5_storage_read(sp, *data, size);
(*data)[size] = '\0';
if(ret != size)
return (ret < 0)? errno : KRB5_KT_END;
return 0;
}
static krb5_error_code
krb5_kt_store_data(krb5_context context,
krb5_storage *sp,
krb5_data data)
{
int ret;
ret = krb5_store_int16(sp, data.length);
if(ret < 0)
return ret;
ret = krb5_storage_write(sp, data.data, data.length);
if(ret != data.length){
if(ret < 0)
return errno;
return KRB5_KT_END;
}
return 0;
}
static krb5_error_code
krb5_kt_store_string(krb5_storage *sp,
heim_general_string data)
{
int ret;
size_t len = strlen(data);
ret = krb5_store_int16(sp, len);
if(ret < 0)
return ret;
ret = krb5_storage_write(sp, data, len);
if(ret != len){
if(ret < 0)
return errno;
return KRB5_KT_END;
}
return 0;
}
static krb5_error_code
krb5_kt_ret_keyblock(krb5_context context, krb5_storage *sp, krb5_keyblock *p)
{
int ret;
int16_t tmp;
ret = krb5_ret_int16(sp, &tmp); /* keytype + etype */
if(ret) return ret;
p->keytype = tmp;
ret = krb5_kt_ret_data(context, sp, &p->keyvalue);
return ret;
}
static krb5_error_code
krb5_kt_store_keyblock(krb5_context context,
krb5_storage *sp,
krb5_keyblock *p)
{
int ret;
ret = krb5_store_int16(sp, p->keytype); /* keytype + etype */
if(ret) return ret;
ret = krb5_kt_store_data(context, sp, p->keyvalue);
return ret;
}
static krb5_error_code
krb5_kt_ret_principal(krb5_context context,
krb5_storage *sp,
krb5_principal *princ)
{
int i;
int ret;
krb5_principal p;
int16_t len;
ALLOC(p, 1);
if(p == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
ret = krb5_ret_int16(sp, &len);
if(ret) {
krb5_set_error_string(context,
"Failed decoding length of keytab principal");
goto out;
}
if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
len--;
if (len < 0) {
krb5_set_error_string(context,
"Keytab principal contains invalid length");
ret = KRB5_KT_END;
goto out;
}
ret = krb5_kt_ret_string(context, sp, &p->realm);
if(ret)
goto out;
p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val));
if(p->name.name_string.val == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
ret = ENOMEM;
goto out;
}
p->name.name_string.len = len;
for(i = 0; i < p->name.name_string.len; i++){
ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i);
if(ret)
goto out;
}
if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
p->name.name_type = KRB5_NT_UNKNOWN;
else {
int32_t tmp32;
ret = krb5_ret_int32(sp, &tmp32);
p->name.name_type = tmp32;
if (ret)
goto out;
}
*princ = p;
return 0;
out:
krb5_free_principal(context, p);
return ret;
}
static krb5_error_code
krb5_kt_store_principal(krb5_context context,
krb5_storage *sp,
krb5_principal p)
{
int i;
int ret;
if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
ret = krb5_store_int16(sp, p->name.name_string.len + 1);
else
ret = krb5_store_int16(sp, p->name.name_string.len);
if(ret) return ret;
ret = krb5_kt_store_string(sp, p->realm);
if(ret) return ret;
for(i = 0; i < p->name.name_string.len; i++){
ret = krb5_kt_store_string(sp, p->name.name_string.val[i]);
if(ret)
return ret;
}
if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
ret = krb5_store_int32(sp, p->name.name_type);
if(ret)
return ret;
}
return 0;
}
static krb5_error_code
fkt_resolve(krb5_context context, const char *name, krb5_keytab id)
{
struct fkt_data *d;
d = malloc(sizeof(*d));
if(d == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
d->filename = strdup(name);
if(d->filename == NULL) {
free(d);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
d->flags = 0;
id->data = d;
return 0;
}
static krb5_error_code
fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id)
{
krb5_error_code ret;
ret = fkt_resolve(context, name, id);
if (ret == 0) {
struct fkt_data *d = id->data;
d->flags |= KRB5_KT_FL_JAVA;
}
return ret;
}
static krb5_error_code
fkt_close(krb5_context context, krb5_keytab id)
{
struct fkt_data *d = id->data;
free(d->filename);
free(d);
return 0;
}
static krb5_error_code
fkt_get_name(krb5_context context,
krb5_keytab id,
char *name,
size_t namesize)
{
/* This function is XXX */
struct fkt_data *d = id->data;
strlcpy(name, d->filename, namesize);
return 0;
}
static void
storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
{
int flags = 0;
switch(vno) {
case KRB5_KT_VNO_1:
flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS;
flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE;
flags |= KRB5_STORAGE_HOST_BYTEORDER;
break;
case KRB5_KT_VNO_2:
break;
default:
krb5_warnx(context,
"storage_set_flags called with bad vno (%d)", vno);
}
krb5_storage_set_flags(sp, flags);
}
static krb5_error_code
fkt_start_seq_get_int(krb5_context context,
krb5_keytab id,
int flags,
int exclusive,
krb5_kt_cursor *c)
{
int8_t pvno, tag;
krb5_error_code ret;
struct fkt_data *d = id->data;
c->fd = open (d->filename, flags);
if (c->fd < 0) {
ret = errno;
krb5_set_error_string(context, "%s: %s", d->filename,
strerror(ret));
return ret;
}
ret = _krb5_xlock(context, c->fd, exclusive, d->filename);
if (ret) {
close(c->fd);
return ret;
}
c->sp = krb5_storage_from_fd(c->fd);
if (c->sp == NULL) {
_krb5_xunlock(context, c->fd);
close(c->fd);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
krb5_storage_set_eof_code(c->sp, KRB5_KT_END);
ret = krb5_ret_int8(c->sp, &pvno);
if(ret) {
krb5_storage_free(c->sp);
_krb5_xunlock(context, c->fd);
close(c->fd);
krb5_clear_error_string(context);
return ret;
}
if(pvno != 5) {
krb5_storage_free(c->sp);
_krb5_xunlock(context, c->fd);
close(c->fd);
krb5_clear_error_string (context);
return KRB5_KEYTAB_BADVNO;
}
ret = krb5_ret_int8(c->sp, &tag);
if (ret) {
krb5_storage_free(c->sp);
_krb5_xunlock(context, c->fd);
close(c->fd);
krb5_clear_error_string(context);
return ret;
}
id->version = tag;
storage_set_flags(context, c->sp, id->version);
return 0;
}
static krb5_error_code
fkt_start_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *c)
{
return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, 0, c);
}
static krb5_error_code
fkt_next_entry_int(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry,
krb5_kt_cursor *cursor,
off_t *start,
off_t *end)
{
int32_t len;
int ret;
int8_t tmp8;
int32_t tmp32;
off_t pos, curpos;
pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
loop:
ret = krb5_ret_int32(cursor->sp, &len);
if (ret)
return ret;
if(len < 0) {
pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR);
goto loop;
}
ret = krb5_kt_ret_principal (context, cursor->sp, &entry->principal);
if (ret)
goto out;
ret = krb5_ret_int32(cursor->sp, &tmp32);
entry->timestamp = tmp32;
if (ret)
goto out;
ret = krb5_ret_int8(cursor->sp, &tmp8);
if (ret)
goto out;
entry->vno = tmp8;
ret = krb5_kt_ret_keyblock (context, cursor->sp, &entry->keyblock);
if (ret)
goto out;
/* there might be a 32 bit kvno here
* if it's zero, assume that the 8bit one was right,
* otherwise trust the new value */
curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
if(len + 4 + pos - curpos >= 4) {
ret = krb5_ret_int32(cursor->sp, &tmp32);
if (ret == 0 && tmp32 != 0) {
entry->vno = tmp32;
}
}
if(start) *start = pos;
if(end) *end = pos + 4 + len;
out:
krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET);
return ret;
}
static krb5_error_code
fkt_next_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry,
krb5_kt_cursor *cursor)
{
return fkt_next_entry_int(context, id, entry, cursor, NULL, NULL);
}
static krb5_error_code
fkt_end_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
krb5_storage_free(cursor->sp);
_krb5_xunlock(context, cursor->fd);
close(cursor->fd);
return 0;
}
static krb5_error_code
fkt_setup_keytab(krb5_context context,
krb5_keytab id,
krb5_storage *sp)
{
krb5_error_code ret;
ret = krb5_store_int8(sp, 5);
if(ret)
return ret;
if(id->version == 0)
id->version = KRB5_KT_VNO;
return krb5_store_int8 (sp, id->version);
}
static krb5_error_code
fkt_add_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
int ret;
int fd;
krb5_storage *sp;
struct fkt_data *d = id->data;
krb5_data keytab;
int32_t len;
fd = open (d->filename, O_RDWR | O_BINARY);
if (fd < 0) {
fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
if (fd < 0) {
ret = errno;
krb5_set_error_string(context, "open(%s): %s", d->filename,
strerror(ret));
return ret;
}
ret = _krb5_xlock(context, fd, 1, d->filename);
if (ret) {
close(fd);
return ret;
}
sp = krb5_storage_from_fd(fd);
krb5_storage_set_eof_code(sp, KRB5_KT_END);
ret = fkt_setup_keytab(context, id, sp);
if(ret) {
goto out;
}
storage_set_flags(context, sp, id->version);
} else {
int8_t pvno, tag;
ret = _krb5_xlock(context, fd, 1, d->filename);
if (ret) {
close(fd);
return ret;
}
sp = krb5_storage_from_fd(fd);
krb5_storage_set_eof_code(sp, KRB5_KT_END);
ret = krb5_ret_int8(sp, &pvno);
if(ret) {
/* we probably have a zero byte file, so try to set it up
properly */
ret = fkt_setup_keytab(context, id, sp);
if(ret) {
krb5_set_error_string(context, "%s: keytab is corrupted: %s",
d->filename, strerror(ret));
goto out;
}
storage_set_flags(context, sp, id->version);
} else {
if(pvno != 5) {
ret = KRB5_KEYTAB_BADVNO;
krb5_set_error_string(context, "%s: %s",
d->filename, strerror(ret));
goto out;
}
ret = krb5_ret_int8 (sp, &tag);
if (ret) {
krb5_set_error_string(context, "%s: reading tag: %s",
d->filename, strerror(ret));
goto out;
}
id->version = tag;
storage_set_flags(context, sp, id->version);
}
}
{
krb5_storage *emem;
emem = krb5_storage_emem();
if(emem == NULL) {
ret = ENOMEM;
krb5_set_error_string (context, "malloc: out of memory");
goto out;
}
ret = krb5_kt_store_principal(context, emem, entry->principal);
if(ret) {
krb5_storage_free(emem);
goto out;
}
ret = krb5_store_int32 (emem, entry->timestamp);
if(ret) {
krb5_storage_free(emem);
goto out;
}
ret = krb5_store_int8 (emem, entry->vno % 256);
if(ret) {
krb5_storage_free(emem);
goto out;
}
ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock);
if(ret) {
krb5_storage_free(emem);
goto out;
}
if ((d->flags & KRB5_KT_FL_JAVA) == 0) {
ret = krb5_store_int32 (emem, entry->vno);
if (ret) {
krb5_storage_free(emem);
goto out;
}
}
ret = krb5_storage_to_data(emem, &keytab);
krb5_storage_free(emem);
if(ret)
goto out;
}
while(1) {
ret = krb5_ret_int32(sp, &len);
if(ret == KRB5_KT_END) {
len = keytab.length;
break;
}
if(len < 0) {
len = -len;
if(len >= keytab.length) {
krb5_storage_seek(sp, -4, SEEK_CUR);
break;
}
}
krb5_storage_seek(sp, len, SEEK_CUR);
}
ret = krb5_store_int32(sp, len);
if(krb5_storage_write(sp, keytab.data, keytab.length) < 0)
ret = errno;
memset(keytab.data, 0, keytab.length);
krb5_data_free(&keytab);
out:
krb5_storage_free(sp);
_krb5_xunlock(context, fd);
close(fd);
return ret;
}
static krb5_error_code
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, 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(len, sizeof(buf)));
len -= min(len, sizeof(buf));
}
}
krb5_kt_free_entry(context, &e);
}
krb5_kt_end_seq_get(context, id, &cursor);
out:
if (!found) {
krb5_clear_error_string (context);
return KRB5_KT_NOTFOUND;
}
return 0;
}
const krb5_kt_ops krb5_fkt_ops = {
"FILE",
fkt_resolve,
fkt_get_name,
fkt_close,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
fkt_end_seq_get,
fkt_add_entry,
fkt_remove_entry
};
const krb5_kt_ops krb5_wrfkt_ops = {
"WRFILE",
fkt_resolve,
fkt_get_name,
fkt_close,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
fkt_end_seq_get,
fkt_add_entry,
fkt_remove_entry
};
const krb5_kt_ops krb5_javakt_ops = {
"JAVA14",
fkt_resolve_java14,
fkt_get_name,
fkt_close,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
fkt_end_seq_get,
fkt_add_entry,
fkt_remove_entry
};
@@ -0,0 +1,420 @@
/*
* Copyright (c) 1997 - 2002, 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: keytab_keyfile.c,v 1.19 2006/04/24 15:06:57 lha Exp $");
/* afs keyfile operations --------------------------------------- */
/*
* Minimum tools to handle the AFS KeyFile.
*
* Format of the KeyFile is:
* <int32_t numkeys> {[<int32_t kvno> <char[8] deskey>] * numkeys}
*
* It just adds to the end of the keyfile, deleting isn't implemented.
* Use your favorite text/hex editor to delete keys.
*
*/
#define AFS_SERVERTHISCELL "/usr/afs/etc/ThisCell"
#define AFS_SERVERMAGICKRBCONF "/usr/afs/etc/krb.conf"
struct akf_data {
int num_entries;
char *filename;
char *cell;
char *realm;
};
/*
* set `d->cell' and `d->realm'
*/
static int
get_cell_and_realm (krb5_context context, struct akf_data *d)
{
FILE *f;
char buf[BUFSIZ], *cp;
int ret;
f = fopen (AFS_SERVERTHISCELL, "r");
if (f == NULL) {
ret = errno;
krb5_set_error_string (context, "open %s: %s", AFS_SERVERTHISCELL,
strerror(ret));
return ret;
}
if (fgets (buf, sizeof(buf), f) == NULL) {
fclose (f);
krb5_set_error_string (context, "no cell in %s", AFS_SERVERTHISCELL);
return EINVAL;
}
buf[strcspn(buf, "\n")] = '\0';
fclose(f);
d->cell = strdup (buf);
if (d->cell == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
f = fopen (AFS_SERVERMAGICKRBCONF, "r");
if (f != NULL) {
if (fgets (buf, sizeof(buf), f) == NULL) {
free (d->cell);
d->cell = NULL;
fclose (f);
krb5_set_error_string (context, "no realm in %s",
AFS_SERVERMAGICKRBCONF);
return EINVAL;
}
buf[strcspn(buf, "\n")] = '\0';
fclose(f);
}
/* uppercase */
for (cp = buf; *cp != '\0'; cp++)
*cp = toupper((unsigned char)*cp);
d->realm = strdup (buf);
if (d->realm == NULL) {
free (d->cell);
d->cell = NULL;
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
return 0;
}
/*
* init and get filename
*/
static krb5_error_code
akf_resolve(krb5_context context, const char *name, krb5_keytab id)
{
int ret;
struct akf_data *d = malloc(sizeof (struct akf_data));
if (d == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
d->num_entries = 0;
ret = get_cell_and_realm (context, d);
if (ret) {
free (d);
return ret;
}
d->filename = strdup (name);
if (d->filename == NULL) {
free (d->cell);
free (d->realm);
free (d);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
id->data = d;
return 0;
}
/*
* cleanup
*/
static krb5_error_code
akf_close(krb5_context context, krb5_keytab id)
{
struct akf_data *d = id->data;
free (d->filename);
free (d->cell);
free (d);
return 0;
}
/*
* Return filename
*/
static krb5_error_code
akf_get_name(krb5_context context,
krb5_keytab id,
char *name,
size_t name_sz)
{
struct akf_data *d = id->data;
strlcpy (name, d->filename, name_sz);
return 0;
}
/*
* Init
*/
static krb5_error_code
akf_start_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *c)
{
int32_t ret;
struct akf_data *d = id->data;
c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600);
if (c->fd < 0) {
ret = errno;
krb5_set_error_string(context, "open(%s): %s", d->filename,
strerror(ret));
return ret;
}
c->sp = krb5_storage_from_fd(c->fd);
ret = krb5_ret_int32(c->sp, &d->num_entries);
if(ret) {
krb5_storage_free(c->sp);
close(c->fd);
krb5_clear_error_string (context);
if(ret == KRB5_KT_END)
return KRB5_KT_NOTFOUND;
return ret;
}
return 0;
}
static krb5_error_code
akf_next_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry,
krb5_kt_cursor *cursor)
{
struct akf_data *d = id->data;
int32_t kvno;
off_t pos;
int ret;
pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
if ((pos - 4) / (4 + 8) >= d->num_entries)
return KRB5_KT_END;
ret = krb5_make_principal (context, &entry->principal,
d->realm, "afs", d->cell, NULL);
if (ret)
goto out;
ret = krb5_ret_int32(cursor->sp, &kvno);
if (ret) {
krb5_free_principal (context, entry->principal);
goto out;
}
entry->vno = kvno;
entry->keyblock.keytype = ETYPE_DES_CBC_MD5;
entry->keyblock.keyvalue.length = 8;
entry->keyblock.keyvalue.data = malloc (8);
if (entry->keyblock.keyvalue.data == NULL) {
krb5_free_principal (context, entry->principal);
krb5_set_error_string (context, "malloc: out of memory");
ret = ENOMEM;
goto out;
}
ret = krb5_storage_read(cursor->sp, entry->keyblock.keyvalue.data, 8);
if(ret != 8)
ret = (ret < 0) ? errno : KRB5_KT_END;
else
ret = 0;
entry->timestamp = time(NULL);
out:
krb5_storage_seek(cursor->sp, pos + 4 + 8, SEEK_SET);
return ret;
}
static krb5_error_code
akf_end_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
krb5_storage_free(cursor->sp);
close(cursor->fd);
return 0;
}
static krb5_error_code
akf_add_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
struct akf_data *d = id->data;
int fd, created = 0;
krb5_error_code ret;
int32_t len;
krb5_storage *sp;
if (entry->keyblock.keyvalue.length != 8)
return 0;
switch(entry->keyblock.keytype) {
case ETYPE_DES_CBC_CRC:
case ETYPE_DES_CBC_MD4:
case ETYPE_DES_CBC_MD5:
break;
default:
return 0;
}
fd = open (d->filename, O_RDWR | O_BINARY);
if (fd < 0) {
fd = open (d->filename,
O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600);
if (fd < 0) {
ret = errno;
krb5_set_error_string(context, "open(%s): %s", d->filename,
strerror(ret));
return ret;
}
created = 1;
}
sp = krb5_storage_from_fd(fd);
if(sp == NULL) {
close(fd);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
if (created)
len = 0;
else {
if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) {
ret = errno;
krb5_storage_free(sp);
close(fd);
krb5_set_error_string (context, "seek: %s", strerror(ret));
return ret;
}
ret = krb5_ret_int32(sp, &len);
if(ret) {
krb5_storage_free(sp);
close(fd);
return ret;
}
}
/*
* Make sure we don't add the entry twice, assumes the DES
* encryption types are all the same key.
*/
if (len > 0) {
int32_t kvno;
int i;
for (i = 0; i < len; i++) {
ret = krb5_ret_int32(sp, &kvno);
if (ret) {
krb5_set_error_string (context, "Failed got get kvno ");
goto out;
}
if(krb5_storage_seek(sp, 8, SEEK_CUR) < 0) {
krb5_set_error_string (context, "seek: %s", strerror(ret));
goto out;
}
if (kvno == entry->vno) {
ret = 0;
goto out;
}
}
}
len++;
if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) {
ret = errno;
krb5_set_error_string (context, "seek: %s", strerror(ret));
goto out;
}
ret = krb5_store_int32(sp, len);
if(ret) {
krb5_set_error_string(context, "keytab keyfile failed new length");
return ret;
}
if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) {
ret = errno;
krb5_set_error_string (context, "seek to end: %s", strerror(ret));
goto out;
}
ret = krb5_store_int32(sp, entry->vno);
if(ret) {
krb5_set_error_string(context, "keytab keyfile failed store kvno");
goto out;
}
ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data,
entry->keyblock.keyvalue.length);
if(ret != entry->keyblock.keyvalue.length) {
if (ret < 0)
ret = errno;
else
ret = ENOTTY;
krb5_set_error_string(context, "keytab keyfile failed to add key");
goto out;
}
ret = 0;
out:
krb5_storage_free(sp);
close (fd);
return ret;
}
const krb5_kt_ops krb5_akf_ops = {
"AFSKEYFILE",
akf_resolve,
akf_get_name,
akf_close,
NULL, /* get */
akf_start_seq_get,
akf_next_entry,
akf_end_seq_get,
akf_add_entry,
NULL /* remove */
};
+448
View File
@@ -0,0 +1,448 @@
/*
* Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: keytab_krb4.c,v 1.15 2006/04/10 17:10:53 lha Exp $");
struct krb4_kt_data {
char *filename;
};
static krb5_error_code
krb4_kt_resolve(krb5_context context, const char *name, krb5_keytab id)
{
struct krb4_kt_data *d;
d = malloc (sizeof(*d));
if (d == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
d->filename = strdup (name);
if (d->filename == NULL) {
free(d);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
id->data = d;
return 0;
}
static krb5_error_code
krb4_kt_get_name (krb5_context context,
krb5_keytab id,
char *name,
size_t name_sz)
{
struct krb4_kt_data *d = id->data;
strlcpy (name, d->filename, name_sz);
return 0;
}
static krb5_error_code
krb4_kt_close (krb5_context context,
krb5_keytab id)
{
struct krb4_kt_data *d = id->data;
free (d->filename);
free (d);
return 0;
}
struct krb4_cursor_extra_data {
krb5_keytab_entry entry;
int num;
};
static int
open_flock(const char *filename, int flags, int mode)
{
int lock_mode;
int tries = 0;
int fd = open(filename, flags, mode);
if(fd < 0)
return fd;
if((flags & O_ACCMODE) == O_RDONLY)
lock_mode = LOCK_SH | LOCK_NB;
else
lock_mode = LOCK_EX | LOCK_NB;
while(flock(fd, lock_mode) < 0) {
if(++tries < 5) {
sleep(1);
} else {
close(fd);
return -1;
}
}
return fd;
}
static krb5_error_code
krb4_kt_start_seq_get_int (krb5_context context,
krb5_keytab id,
int flags,
krb5_kt_cursor *c)
{
struct krb4_kt_data *d = id->data;
struct krb4_cursor_extra_data *ed;
int ret;
ed = malloc (sizeof(*ed));
if (ed == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
ed->entry.principal = NULL;
ed->num = -1;
c->data = ed;
c->fd = open_flock (d->filename, flags, 0);
if (c->fd < 0) {
ret = errno;
free (ed);
krb5_set_error_string(context, "open(%s): %s", d->filename,
strerror(ret));
return ret;
}
c->sp = krb5_storage_from_fd(c->fd);
if(c->sp == NULL) {
close(c->fd);
free(ed);
return ENOMEM;
}
krb5_storage_set_eof_code(c->sp, KRB5_KT_END);
return 0;
}
static krb5_error_code
krb4_kt_start_seq_get (krb5_context context,
krb5_keytab id,
krb5_kt_cursor *c)
{
return krb4_kt_start_seq_get_int (context, id, O_BINARY | O_RDONLY, c);
}
static krb5_error_code
read_v4_entry (krb5_context context,
struct krb4_kt_data *d,
krb5_kt_cursor *c,
struct krb4_cursor_extra_data *ed)
{
unsigned char des_key[8];
krb5_error_code ret;
char *service, *instance, *realm;
int8_t kvno;
ret = krb5_ret_stringz(c->sp, &service);
if (ret)
return ret;
ret = krb5_ret_stringz(c->sp, &instance);
if (ret) {
free (service);
return ret;
}
ret = krb5_ret_stringz(c->sp, &realm);
if (ret) {
free (service);
free (instance);
return ret;
}
ret = krb5_425_conv_principal (context, service, instance, realm,
&ed->entry.principal);
free (service);
free (instance);
free (realm);
if (ret)
return ret;
ret = krb5_ret_int8(c->sp, &kvno);
if (ret) {
krb5_free_principal (context, ed->entry.principal);
return ret;
}
ret = krb5_storage_read(c->sp, des_key, sizeof(des_key));
if (ret < 0) {
krb5_free_principal(context, ed->entry.principal);
return ret;
}
if (ret < 8) {
krb5_free_principal(context, ed->entry.principal);
return EINVAL;
}
ed->entry.vno = kvno;
ret = krb5_data_copy (&ed->entry.keyblock.keyvalue,
des_key, sizeof(des_key));
if (ret)
return ret;
ed->entry.timestamp = time(NULL);
ed->num = 0;
return 0;
}
static krb5_error_code
krb4_kt_next_entry (krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry,
krb5_kt_cursor *c)
{
krb5_error_code ret;
struct krb4_kt_data *d = id->data;
struct krb4_cursor_extra_data *ed = c->data;
const krb5_enctype keytypes[] = {ETYPE_DES_CBC_MD5,
ETYPE_DES_CBC_MD4,
ETYPE_DES_CBC_CRC};
if (ed->num == -1) {
ret = read_v4_entry (context, d, c, ed);
if (ret)
return ret;
}
ret = krb5_kt_copy_entry_contents (context,
&ed->entry,
entry);
if (ret)
return ret;
entry->keyblock.keytype = keytypes[ed->num];
if (++ed->num == 3) {
krb5_kt_free_entry (context, &ed->entry);
ed->num = -1;
}
return 0;
}
static krb5_error_code
krb4_kt_end_seq_get (krb5_context context,
krb5_keytab id,
krb5_kt_cursor *c)
{
struct krb4_cursor_extra_data *ed = c->data;
krb5_storage_free (c->sp);
if (ed->num != -1)
krb5_kt_free_entry (context, &ed->entry);
free (c->data);
close (c->fd);
return 0;
}
static krb5_error_code
krb4_store_keytab_entry(krb5_context context,
krb5_keytab_entry *entry,
krb5_storage *sp)
{
krb5_error_code ret;
#define ANAME_SZ 40
#define INST_SZ 40
#define REALM_SZ 40
char service[ANAME_SZ];
char instance[INST_SZ];
char realm[REALM_SZ];
ret = krb5_524_conv_principal (context, entry->principal,
service, instance, realm);
if (ret)
return ret;
if (entry->keyblock.keyvalue.length == 8
&& entry->keyblock.keytype == ETYPE_DES_CBC_MD5) {
ret = krb5_store_stringz(sp, service);
ret = krb5_store_stringz(sp, instance);
ret = krb5_store_stringz(sp, realm);
ret = krb5_store_int8(sp, entry->vno);
ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, 8);
}
return 0;
}
static krb5_error_code
krb4_kt_add_entry (krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
struct krb4_kt_data *d = id->data;
krb5_storage *sp;
krb5_error_code ret;
int fd;
fd = open_flock (d->filename, O_WRONLY | O_APPEND | O_BINARY, 0);
if (fd < 0) {
fd = open_flock (d->filename,
O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600);
if (fd < 0) {
ret = errno;
krb5_set_error_string(context, "open(%s): %s", d->filename,
strerror(ret));
return ret;
}
}
sp = krb5_storage_from_fd(fd);
if(sp == NULL) {
close(fd);
return ENOMEM;
}
krb5_storage_set_eof_code(sp, KRB5_KT_END);
ret = krb4_store_keytab_entry(context, entry, sp);
krb5_storage_free(sp);
if(close (fd) < 0)
return errno;
return ret;
}
static krb5_error_code
krb4_kt_remove_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
struct krb4_kt_data *d = id->data;
krb5_error_code ret;
krb5_keytab_entry e;
krb5_kt_cursor cursor;
krb5_storage *sp;
int remove_flag = 0;
sp = krb5_storage_emem();
if (sp == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
ret = krb5_kt_start_seq_get(context, id, &cursor);
if (ret) {
krb5_storage_free(sp);
return ret;
}
while(krb5_kt_next_entry(context, id, &e, &cursor) == 0) {
if(!krb5_kt_compare(context, &e, entry->principal,
entry->vno, entry->keyblock.keytype)) {
ret = krb4_store_keytab_entry(context, &e, sp);
if(ret) {
krb5_kt_free_entry(context, &e);
krb5_storage_free(sp);
return ret;
}
} else
remove_flag = 1;
krb5_kt_free_entry(context, &e);
}
krb5_kt_end_seq_get(context, id, &cursor);
if(remove_flag) {
int fd;
unsigned char buf[1024];
ssize_t n;
krb5_data data;
struct stat st;
krb5_storage_to_data(sp, &data);
krb5_storage_free(sp);
fd = open_flock (d->filename, O_RDWR | O_BINARY, 0);
if(fd < 0) {
memset(data.data, 0, data.length);
krb5_data_free(&data);
if(errno == EACCES || errno == EROFS)
return KRB5_KT_NOWRITE;
return errno;
}
if(write(fd, data.data, data.length) != data.length) {
memset(data.data, 0, data.length);
krb5_data_free(&data);
close(fd);
krb5_set_error_string(context, "failed writing to \"%s\"", d->filename);
return errno;
}
memset(data.data, 0, data.length);
if(fstat(fd, &st) < 0) {
krb5_data_free(&data);
close(fd);
krb5_set_error_string(context, "failed getting size of \"%s\"", d->filename);
return errno;
}
st.st_size -= data.length;
memset(buf, 0, sizeof(buf));
while(st.st_size > 0) {
n = min(st.st_size, sizeof(buf));
n = write(fd, buf, n);
if(n <= 0) {
krb5_data_free(&data);
close(fd);
krb5_set_error_string(context, "failed writing to \"%s\"", d->filename);
return errno;
}
st.st_size -= n;
}
if(ftruncate(fd, data.length) < 0) {
krb5_data_free(&data);
close(fd);
krb5_set_error_string(context, "failed truncating \"%s\"", d->filename);
return errno;
}
krb5_data_free(&data);
if(close(fd) < 0) {
krb5_set_error_string(context, "error closing \"%s\"", d->filename);
return errno;
}
return 0;
} else {
krb5_storage_free(sp);
return KRB5_KT_NOTFOUND;
}
}
const krb5_kt_ops krb4_fkt_ops = {
"krb4",
krb4_kt_resolve,
krb4_kt_get_name,
krb4_kt_close,
NULL, /* get */
krb4_kt_start_seq_get,
krb4_kt_next_entry,
krb4_kt_end_seq_get,
krb4_kt_add_entry, /* add_entry */
krb4_kt_remove_entry /* remove_entry */
};
const krb5_kt_ops krb5_srvtab_fkt_ops = {
"SRVTAB",
krb4_kt_resolve,
krb4_kt_get_name,
krb4_kt_close,
NULL, /* get */
krb4_kt_start_seq_get,
krb4_kt_next_entry,
krb4_kt_end_seq_get,
krb4_kt_add_entry, /* add_entry */
krb4_kt_remove_entry /* remove_entry */
};
@@ -0,0 +1,234 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: keytab_memory.c,v 1.8 2005/12/05 18:39:46 lha Exp $");
/* memory operations -------------------------------------------- */
struct mkt_data {
krb5_keytab_entry *entries;
int num_entries;
char *name;
int refcount;
struct mkt_data *next;
};
/* this mutex protects mkt_head, ->refcount, and ->next
* content is not protected (name is static and need no protection)
*/
static HEIMDAL_MUTEX mkt_mutex = HEIMDAL_MUTEX_INITIALIZER;
static struct mkt_data *mkt_head;
static krb5_error_code
mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
{
struct mkt_data *d;
HEIMDAL_MUTEX_lock(&mkt_mutex);
for (d = mkt_head; d != NULL; d = d->next)
if (strcmp(d->name, name) == 0)
break;
if (d) {
if (d->refcount < 1)
krb5_abortx(context, "Double close on memory keytab, "
"refcount < 1 %d", d->refcount);
d->refcount++;
id->data = d;
HEIMDAL_MUTEX_unlock(&mkt_mutex);
return 0;
}
d = calloc(1, sizeof(*d));
if(d == NULL) {
HEIMDAL_MUTEX_unlock(&mkt_mutex);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
d->name = strdup(name);
if (d->name == NULL) {
HEIMDAL_MUTEX_unlock(&mkt_mutex);
free(d);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
d->entries = NULL;
d->num_entries = 0;
d->refcount = 1;
d->next = mkt_head;
mkt_head = d;
HEIMDAL_MUTEX_unlock(&mkt_mutex);
id->data = d;
return 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;
}
static krb5_error_code
mkt_get_name(krb5_context context,
krb5_keytab id,
char *name,
size_t namesize)
{
struct mkt_data *d = id->data;
strlcpy(name, d->name, namesize);
return 0;
}
static krb5_error_code
mkt_start_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *c)
{
/* XXX */
c->fd = 0;
return 0;
}
static krb5_error_code
mkt_next_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry,
krb5_kt_cursor *c)
{
struct mkt_data *d = id->data;
if(c->fd >= d->num_entries)
return KRB5_KT_END;
return krb5_kt_copy_entry_contents(context, &d->entries[c->fd++], entry);
}
static krb5_error_code
mkt_end_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *cursor)
{
return 0;
}
static krb5_error_code
mkt_add_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
{
struct mkt_data *d = id->data;
krb5_keytab_entry *tmp;
tmp = realloc(d->entries, (d->num_entries + 1) * sizeof(*d->entries));
if(tmp == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
d->entries = tmp;
return krb5_kt_copy_entry_contents(context, entry,
&d->entries[d->num_entries++]);
}
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;
}
const krb5_kt_ops krb5_mkt_ops = {
"MEMORY",
mkt_resolve,
mkt_get_name,
mkt_close,
NULL, /* get */
mkt_start_seq_get,
mkt_next_entry,
mkt_end_seq_get,
mkt_add_entry,
mkt_remove_entry
};
@@ -0,0 +1,485 @@
/* This is a generated file */
#ifndef __krb5_private_h__
#define __krb5_private_h__
#include <stdarg.h>
#ifndef KRB5_LIB_FUNCTION
#if defined(_WIN32)
#define KRB5_LIB_FUNCTION _stdcall
#else
#define KRB5_LIB_FUNCTION
#endif
#endif
void KRB5_LIB_FUNCTION
_krb5_aes_cts_encrypt (
const unsigned char */*in*/,
unsigned char */*out*/,
size_t /*len*/,
const AES_KEY */*key*/,
unsigned char */*ivec*/,
const int /*encryptp*/);
krb5_error_code
_krb5_cc_allocate (
krb5_context /*context*/,
const krb5_cc_ops */*ops*/,
krb5_ccache */*id*/);
void
_krb5_crc_init_table (void);
uint32_t
_krb5_crc_update (
const char */*p*/,
size_t /*len*/,
uint32_t /*res*/);
krb5_error_code
_krb5_dh_group_ok (
krb5_context /*context*/,
unsigned long /*bits*/,
heim_integer */*p*/,
heim_integer */*g*/,
heim_integer */*q*/,
struct krb5_dh_moduli **/*moduli*/,
char **/*name*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_enctype_to_oid (
krb5_context /*context*/,
krb5_enctype /*etype*/,
heim_oid */*oid*/);
krb5_error_code
_krb5_expand_default_cc_name (
krb5_context /*context*/,
const char */*str*/,
char **/*res*/);
int
_krb5_extract_ticket (
krb5_context /*context*/,
krb5_kdc_rep */*rep*/,
krb5_creds */*creds*/,
krb5_keyblock */*key*/,
krb5_const_pointer /*keyseed*/,
krb5_key_usage /*key_usage*/,
krb5_addresses */*addrs*/,
unsigned /*nonce*/,
krb5_boolean /*allow_server_mismatch*/,
krb5_boolean /*ignore_cname*/,
krb5_decrypt_proc /*decrypt_proc*/,
krb5_const_pointer /*decryptarg*/);
int
_krb5_find_type_in_ad (
krb5_context /*context*/,
int /*type*/,
krb5_data */*data*/,
krb5_boolean */*found*/,
krb5_keyblock */*sessionkey*/,
const AuthorizationData */*ad*/);
void
_krb5_free_krbhst_info (krb5_krbhst_info */*hi*/);
void
_krb5_free_moduli (struct krb5_dh_moduli **/*moduli*/);
krb5_error_code
_krb5_get_default_principal_local (
krb5_context /*context*/,
krb5_principal */*princ*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_get_host_realm_int (
krb5_context /*context*/,
const char */*host*/,
krb5_boolean /*use_dns*/,
krb5_realm **/*realms*/);
krb5_error_code
_krb5_get_init_creds_opt_copy (
krb5_context /*context*/,
const krb5_get_init_creds_opt */*in*/,
krb5_get_init_creds_opt **/*out*/);
void KRB5_LIB_FUNCTION
_krb5_get_init_creds_opt_free_krb5_error (krb5_get_init_creds_opt */*opt*/);
void KRB5_LIB_FUNCTION
_krb5_get_init_creds_opt_free_pkinit (krb5_get_init_creds_opt */*opt*/);
void KRB5_LIB_FUNCTION
_krb5_get_init_creds_opt_set_krb5_error (
krb5_context /*context*/,
krb5_get_init_creds_opt */*opt*/,
const KRB_ERROR */*error*/);
krb5_ssize_t KRB5_LIB_FUNCTION
_krb5_get_int (
void */*buffer*/,
unsigned long */*value*/,
size_t /*size*/);
krb5_error_code
_krb5_get_krbtgt (
krb5_context /*context*/,
krb5_ccache /*id*/,
krb5_realm /*realm*/,
krb5_creds **/*cred*/);
krb5_error_code
_krb5_kcm_chmod (
krb5_context /*context*/,
krb5_ccache /*id*/,
uint16_t /*mode*/);
krb5_error_code
_krb5_kcm_chown (
krb5_context /*context*/,
krb5_ccache /*id*/,
uint32_t /*uid*/,
uint32_t /*gid*/);
krb5_error_code
_krb5_kcm_get_initial_ticket (
krb5_context /*context*/,
krb5_ccache /*id*/,
krb5_principal /*server*/,
krb5_keyblock */*key*/);
krb5_error_code
_krb5_kcm_get_ticket (
krb5_context /*context*/,
krb5_ccache /*id*/,
krb5_kdc_flags /*flags*/,
krb5_enctype /*enctype*/,
krb5_principal /*server*/);
krb5_boolean
_krb5_kcm_is_running (krb5_context /*context*/);
krb5_error_code
_krb5_kcm_noop (
krb5_context /*context*/,
krb5_ccache /*id*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_cr_err_reply (
krb5_context /*context*/,
const char */*name*/,
const char */*inst*/,
const char */*realm*/,
uint32_t /*time_ws*/,
uint32_t /*e*/,
const char */*e_string*/,
krb5_data */*data*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_create_auth_reply (
krb5_context /*context*/,
const char */*pname*/,
const char */*pinst*/,
const char */*prealm*/,
int32_t /*time_ws*/,
int /*n*/,
uint32_t /*x_date*/,
unsigned char /*kvno*/,
const krb5_data */*cipher*/,
krb5_data */*data*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_create_ciph (
krb5_context /*context*/,
const krb5_keyblock */*session*/,
const char */*service*/,
const char */*instance*/,
const char */*realm*/,
uint32_t /*life*/,
unsigned char /*kvno*/,
const krb5_data */*ticket*/,
uint32_t /*kdc_time*/,
const krb5_keyblock */*key*/,
krb5_data */*enc_data*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_create_ticket (
krb5_context /*context*/,
unsigned char /*flags*/,
const char */*pname*/,
const char */*pinstance*/,
const char */*prealm*/,
int32_t /*paddress*/,
const krb5_keyblock */*session*/,
int16_t /*life*/,
int32_t /*life_sec*/,
const char */*sname*/,
const char */*sinstance*/,
const krb5_keyblock */*key*/,
krb5_data */*enc_data*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_decomp_ticket (
krb5_context /*context*/,
const krb5_data */*enc_ticket*/,
const krb5_keyblock */*key*/,
const char */*local_realm*/,
char **/*sname*/,
char **/*sinstance*/,
struct _krb5_krb_auth_data */*ad*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_dest_tkt (
krb5_context /*context*/,
const char */*tkfile*/);
void KRB5_LIB_FUNCTION
_krb5_krb_free_auth_data (
krb5_context /*context*/,
struct _krb5_krb_auth_data */*ad*/);
time_t KRB5_LIB_FUNCTION
_krb5_krb_life_to_time (
int /*start*/,
int /*life_*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_rd_req (
krb5_context /*context*/,
krb5_data */*authent*/,
const char */*service*/,
const char */*instance*/,
const char */*local_realm*/,
int32_t /*from_addr*/,
const krb5_keyblock */*key*/,
struct _krb5_krb_auth_data */*ad*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_tf_setup (
krb5_context /*context*/,
struct credentials */*v4creds*/,
const char */*tkfile*/,
int /*append*/);
int KRB5_LIB_FUNCTION
_krb5_krb_time_to_life (
time_t /*start*/,
time_t /*end*/);
krb5_error_code
_krb5_krbhost_info_move (
krb5_context /*context*/,
krb5_krbhst_info */*from*/,
krb5_krbhst_info **/*to*/);
krb5_error_code
_krb5_mk_req_internal (
krb5_context /*context*/,
krb5_auth_context */*auth_context*/,
const krb5_flags /*ap_req_options*/,
krb5_data */*in_data*/,
krb5_creds */*in_creds*/,
krb5_data */*outbuf*/,
krb5_key_usage /*checksum_usage*/,
krb5_key_usage /*encrypt_usage*/);
void KRB5_LIB_FUNCTION
_krb5_n_fold (
const void */*str*/,
size_t /*len*/,
void */*key*/,
size_t /*size*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_oid_to_enctype (
krb5_context /*context*/,
const heim_oid */*oid*/,
krb5_enctype */*etype*/);
void
_krb5_pac_free (
krb5_context /*context*/,
struct krb5_pac */*pac*/);
krb5_error_code
_krb5_pac_parse (
krb5_context /*context*/,
const void */*ptr*/,
size_t /*len*/,
struct krb5_pac **/*pac*/);
krb5_error_code
_krb5_pac_sign (
krb5_context /*context*/,
struct krb5_pac */*p*/,
time_t /*authtime*/,
krb5_principal /*principal*/,
krb5_keyblock */*server_key*/,
krb5_keyblock */*priv_key*/,
krb5_data */*data*/);
krb5_error_code
_krb5_pac_verify (
krb5_context /*context*/,
struct krb5_pac */*pac*/,
time_t /*authtime*/,
krb5_principal /*principal*/,
krb5_keyblock */*server*/,
krb5_keyblock */*privsvr*/);
krb5_error_code
_krb5_parse_moduli (
krb5_context /*context*/,
const char */*file*/,
struct krb5_dh_moduli ***/*moduli*/);
krb5_error_code
_krb5_parse_moduli_line (
krb5_context /*context*/,
const char */*file*/,
int /*lineno*/,
char */*p*/,
struct krb5_dh_moduli **/*m*/);
void KRB5_LIB_FUNCTION
_krb5_pk_allow_proxy_certificate (
struct krb5_pk_identity */*id*/,
int /*boolean*/);
void KRB5_LIB_FUNCTION
_krb5_pk_cert_free (struct krb5_pk_cert */*cert*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_load_id (
krb5_context /*context*/,
struct krb5_pk_identity **/*ret_id*/,
const char */*user_id*/,
const char */*anchor_id*/,
char * const */*chain_list*/,
char * const */*revoke_list*/,
krb5_prompter_fct /*prompter*/,
void */*prompter_data*/,
char */*password*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_mk_ContentInfo (
krb5_context /*context*/,
const krb5_data */*buf*/,
const heim_oid */*oid*/,
struct ContentInfo */*content_info*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_mk_padata (
krb5_context /*context*/,
void */*c*/,
const KDC_REQ_BODY */*req_body*/,
unsigned /*nonce*/,
METHOD_DATA */*md*/);
krb5_error_code
_krb5_pk_octetstring2key (
krb5_context /*context*/,
krb5_enctype /*type*/,
const void */*dhdata*/,
size_t /*dhsize*/,
const heim_octet_string */*c_n*/,
const heim_octet_string */*k_n*/,
krb5_keyblock */*key*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_rd_pa_reply (
krb5_context /*context*/,
const char */*realm*/,
void */*c*/,
krb5_enctype /*etype*/,
const krb5_krbhst_info */*hi*/,
unsigned /*nonce*/,
const krb5_data */*req_buffer*/,
PA_DATA */*pa*/,
krb5_keyblock **/*key*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_verify_sign (
krb5_context /*context*/,
const void */*data*/,
size_t /*length*/,
struct krb5_pk_identity */*id*/,
heim_oid */*contentType*/,
krb5_data */*content*/,
struct krb5_pk_cert **/*signer*/);
krb5_error_code
_krb5_plugin_find (
krb5_context /*context*/,
enum plugin_type /*type*/,
const char */*name*/,
struct krb5_plugin **/*list*/);
void
_krb5_plugin_free (struct krb5_plugin */*list*/);
struct krb5_plugin *
_krb5_plugin_get_next (struct krb5_plugin */*p*/);
void *
_krb5_plugin_get_symbol (struct krb5_plugin */*p*/);
krb5_error_code
_krb5_plugin_register (
krb5_context /*context*/,
enum plugin_type /*type*/,
const char */*name*/,
void */*symbol*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_principal2principalname (
PrincipalName */*p*/,
const krb5_principal /*from*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_principalname2krb5_principal (
krb5_context /*context*/,
krb5_principal */*principal*/,
const PrincipalName /*from*/,
const Realm /*realm*/);
krb5_ssize_t KRB5_LIB_FUNCTION
_krb5_put_int (
void */*buffer*/,
unsigned long /*value*/,
size_t /*size*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_rd_req_out_ctx_alloc (
krb5_context /*context*/,
krb5_rd_req_out_ctx */*ctx*/);
krb5_error_code KRB5_LIB_FUNCTION
_krb5_s4u2self_to_checksumdata (
krb5_context /*context*/,
const PA_S4U2Self */*self*/,
krb5_data */*data*/);
int
_krb5_send_and_recv_tcp (
int /*fd*/,
time_t /*tmout*/,
const krb5_data */*req*/,
krb5_data */*rep*/);
int
_krb5_xlock (
krb5_context /*context*/,
int /*fd*/,
krb5_boolean /*exclusive*/,
const char */*filename*/);
int
_krb5_xunlock (
krb5_context /*context*/,
int /*fd*/);
#endif /* __krb5_private_h__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,176 @@
/*
* Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $Id: krb5-v4compat.h,v 1.7 2006/05/05 09:29:07 lha Exp $ */
#ifndef __KRB5_V4COMPAT_H__
#define __KRB5_V4COMPAT_H__
/*
* This file must only be included with v4 compat glue stuff in
* heimdal sources.
*
* It MUST NOT be installed.
*/
#define KRB_PROT_VERSION 4
#define AUTH_MSG_KDC_REQUEST (1<<1)
#define AUTH_MSG_KDC_REPLY (2<<1)
#define AUTH_MSG_APPL_REQUEST (3<<1)
#define AUTH_MSG_APPL_REQUEST_MUTUAL (4<<1)
#define AUTH_MSG_ERR_REPLY (5<<1)
#define AUTH_MSG_PRIVATE (6<<1)
#define AUTH_MSG_SAFE (7<<1)
#define AUTH_MSG_APPL_ERR (8<<1)
#define AUTH_MSG_KDC_FORWARD (9<<1)
#define AUTH_MSG_KDC_RENEW (10<<1)
#define AUTH_MSG_DIE (63<<1)
/* values for kerb error codes */
#define KERB_ERR_OK 0
#define KERB_ERR_NAME_EXP 1
#define KERB_ERR_SERVICE_EXP 2
#define KERB_ERR_AUTH_EXP 3
#define KERB_ERR_PKT_VER 4
#define KERB_ERR_NAME_MAST_KEY_VER 5
#define KERB_ERR_SERV_MAST_KEY_VER 6
#define KERB_ERR_BYTE_ORDER 7
#define KERB_ERR_PRINCIPAL_UNKNOWN 8
#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9
#define KERB_ERR_NULL_KEY 10
#define KERB_ERR_TIMEOUT 11
/* Error codes returned from the KDC */
#define KDC_OK 0 /* Request OK */
#define KDC_NAME_EXP 1 /* Principal expired */
#define KDC_SERVICE_EXP 2 /* Service expired */
#define KDC_AUTH_EXP 3 /* Auth expired */
#define KDC_PKT_VER 4 /* Protocol version unknown */
#define KDC_P_MKEY_VER 5 /* Wrong master key version */
#define KDC_S_MKEY_VER 6 /* Wrong master key version */
#define KDC_BYTE_ORDER 7 /* Byte order unknown */
#define KDC_PR_UNKNOWN 8 /* Principal unknown */
#define KDC_PR_N_UNIQUE 9 /* Principal not unique */
#define KDC_NULL_KEY 10 /* Principal has null key */
#define KDC_GEN_ERR 20 /* Generic error from KDC */
/* General definitions */
#define KSUCCESS 0
#define KFAILURE 255
/* Values returned by rd_ap_req */
#define RD_AP_OK 0 /* Request authentic */
#define RD_AP_UNDEC 31 /* Can't decode authenticator */
#define RD_AP_EXP 32 /* Ticket expired */
#define RD_AP_NYV 33 /* Ticket not yet valid */
#define RD_AP_REPEAT 34 /* Repeated request */
#define RD_AP_NOT_US 35 /* The ticket isn't for us */
#define RD_AP_INCON 36 /* Request is inconsistent */
#define RD_AP_TIME 37 /* delta_t too big */
#define RD_AP_BADD 38 /* Incorrect net address */
#define RD_AP_VERSION 39 /* protocol version mismatch */
#define RD_AP_MSG_TYPE 40 /* invalid msg type */
#define RD_AP_MODIFIED 41 /* message stream modified */
#define RD_AP_ORDER 42 /* message out of order */
#define RD_AP_UNAUTHOR 43 /* unauthorized request */
/* */
#define MAX_KTXT_LEN 1250
#define ANAME_SZ 40
#define REALM_SZ 40
#define SNAME_SZ 40
#define INST_SZ 40
struct ktext {
unsigned int length; /* Length of the text */
unsigned char dat[MAX_KTXT_LEN]; /* The data itself */
uint32_t mbz; /* zero to catch runaway strings */
};
struct credentials {
char service[ANAME_SZ]; /* Service name */
char instance[INST_SZ]; /* Instance */
char realm[REALM_SZ]; /* Auth domain */
char session[8]; /* Session key */
int lifetime; /* Lifetime */
int kvno; /* Key version number */
struct ktext ticket_st; /* The ticket itself */
int32_t issue_date; /* The issue time */
char pname[ANAME_SZ]; /* Principal's name */
char pinst[INST_SZ]; /* Principal's instance */
};
#define TKTLIFENUMFIXED 64
#define TKTLIFEMINFIXED 0x80
#define TKTLIFEMAXFIXED 0xBF
#define TKTLIFENOEXPIRE 0xFF
#define MAXTKTLIFETIME (30*24*3600) /* 30 days */
#ifndef NEVERDATE
#define NEVERDATE ((time_t)0x7fffffffL)
#endif
#define KERB_ERR_NULL_KEY 10
#define CLOCK_SKEW 5*60
#ifndef TKT_ROOT
#define TKT_ROOT "/tmp/tkt"
#endif
struct _krb5_krb_auth_data {
int8_t k_flags; /* Flags from ticket */
char *pname; /* Principal's name */
char *pinst; /* His Instance */
char *prealm; /* His Realm */
uint32_t checksum; /* Data checksum (opt) */
krb5_keyblock session; /* Session Key */
unsigned char life; /* Life of ticket */
uint32_t time_sec; /* Time ticket issued */
uint32_t address; /* Address in ticket */
};
time_t _krb5_krb_life_to_time (int, int);
int _krb5_krb_time_to_life (time_t, time_t);
krb5_error_code _krb5_krb_tf_setup (krb5_context, struct credentials *,
const char *, int);
krb5_error_code _krb5_krb_dest_tkt(krb5_context, const char *);
#define krb_time_to_life _krb5_krb_time_to_life
#define krb_life_to_time _krb5_krb_life_to_time
#endif /* __KRB5_V4COMPAT_H__ */
+762
View File
@@ -0,0 +1,762 @@
/*
* Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $Id: krb5.h,v 1.255 2006/11/12 08:33:07 lha Exp $ */
#ifndef __KRB5_H__
#define __KRB5_H__
#include <time.h>
#include <krb5-types.h>
#include <asn1_err.h>
#include <krb5_err.h>
#include <heim_err.h>
#include <k524_err.h>
#include <krb5_asn1.h>
/* name confusion with MIT */
#ifndef KRB5KDC_ERR_KEY_EXP
#define KRB5KDC_ERR_KEY_EXP KRB5KDC_ERR_KEY_EXPIRED
#endif
/* simple constants */
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
typedef int krb5_boolean;
typedef int32_t krb5_error_code;
typedef int krb5_kvno;
typedef uint32_t krb5_flags;
typedef void *krb5_pointer;
typedef const void *krb5_const_pointer;
struct krb5_crypto_data;
typedef struct krb5_crypto_data *krb5_crypto;
struct krb5_get_creds_opt_data;
typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt;
struct krb5_digest;
typedef struct krb5_digest *krb5_digest;
struct krb5_pac;
typedef struct krb5_rd_req_in_ctx *krb5_rd_req_in_ctx;
typedef struct krb5_rd_req_out_ctx *krb5_rd_req_out_ctx;
typedef CKSUMTYPE krb5_cksumtype;
typedef Checksum krb5_checksum;
typedef ENCTYPE krb5_enctype;
typedef heim_octet_string krb5_data;
/* PKINIT related forward declarations */
struct ContentInfo;
struct krb5_pk_identity;
struct krb5_pk_cert;
/* krb5_enc_data is a mit compat structure */
typedef struct krb5_enc_data {
krb5_enctype enctype;
krb5_kvno kvno;
krb5_data ciphertext;
} krb5_enc_data;
/* alternative names */
enum {
ENCTYPE_NULL = ETYPE_NULL,
ENCTYPE_DES_CBC_CRC = ETYPE_DES_CBC_CRC,
ENCTYPE_DES_CBC_MD4 = ETYPE_DES_CBC_MD4,
ENCTYPE_DES_CBC_MD5 = ETYPE_DES_CBC_MD5,
ENCTYPE_DES3_CBC_MD5 = ETYPE_DES3_CBC_MD5,
ENCTYPE_OLD_DES3_CBC_SHA1 = ETYPE_OLD_DES3_CBC_SHA1,
ENCTYPE_SIGN_DSA_GENERATE = ETYPE_SIGN_DSA_GENERATE,
ENCTYPE_ENCRYPT_RSA_PRIV = ETYPE_ENCRYPT_RSA_PRIV,
ENCTYPE_ENCRYPT_RSA_PUB = ETYPE_ENCRYPT_RSA_PUB,
ENCTYPE_DES3_CBC_SHA1 = ETYPE_DES3_CBC_SHA1,
ENCTYPE_AES128_CTS_HMAC_SHA1_96 = ETYPE_AES128_CTS_HMAC_SHA1_96,
ENCTYPE_AES256_CTS_HMAC_SHA1_96 = ETYPE_AES256_CTS_HMAC_SHA1_96,
ENCTYPE_ARCFOUR_HMAC = ETYPE_ARCFOUR_HMAC_MD5,
ENCTYPE_ARCFOUR_HMAC_MD5 = ETYPE_ARCFOUR_HMAC_MD5,
ENCTYPE_ARCFOUR_HMAC_MD5_56 = ETYPE_ARCFOUR_HMAC_MD5_56,
ENCTYPE_ENCTYPE_PK_CROSS = ETYPE_ENCTYPE_PK_CROSS,
ENCTYPE_DES_CBC_NONE = ETYPE_DES_CBC_NONE,
ENCTYPE_DES3_CBC_NONE = ETYPE_DES3_CBC_NONE,
ENCTYPE_DES_CFB64_NONE = ETYPE_DES_CFB64_NONE,
ENCTYPE_DES_PCBC_NONE = ETYPE_DES_PCBC_NONE
};
typedef PADATA_TYPE krb5_preauthtype;
typedef enum krb5_key_usage {
KRB5_KU_PA_ENC_TIMESTAMP = 1,
/* AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with the
client key (section 5.4.1) */
KRB5_KU_TICKET = 2,
/* AS-REP Ticket and TGS-REP Ticket (includes tgs session key or
application session key), encrypted with the service key
(section 5.4.2) */
KRB5_KU_AS_REP_ENC_PART = 3,
/* AS-REP encrypted part (includes tgs session key or application
session key), encrypted with the client key (section 5.4.2) */
KRB5_KU_TGS_REQ_AUTH_DAT_SESSION = 4,
/* TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs
session key (section 5.4.1) */
KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY = 5,
/* TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs
authenticator subkey (section 5.4.1) */
KRB5_KU_TGS_REQ_AUTH_CKSUM = 6,
/* TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum, keyed
with the tgs session key (sections 5.3.2, 5.4.1) */
KRB5_KU_TGS_REQ_AUTH = 7,
/* TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes tgs
authenticator subkey), encrypted with the tgs session key
(section 5.3.2) */
KRB5_KU_TGS_REP_ENC_PART_SESSION = 8,
/* TGS-REP encrypted part (includes application session key),
encrypted with the tgs session key (section 5.4.2) */
KRB5_KU_TGS_REP_ENC_PART_SUB_KEY = 9,
/* TGS-REP encrypted part (includes application session key),
encrypted with the tgs authenticator subkey (section 5.4.2) */
KRB5_KU_AP_REQ_AUTH_CKSUM = 10,
/* AP-REQ Authenticator cksum, keyed with the application session
key (section 5.3.2) */
KRB5_KU_AP_REQ_AUTH = 11,
/* AP-REQ Authenticator (includes application authenticator
subkey), encrypted with the application session key (section
5.3.2) */
KRB5_KU_AP_REQ_ENC_PART = 12,
/* AP-REP encrypted part (includes application session subkey),
encrypted with the application session key (section 5.5.2) */
KRB5_KU_KRB_PRIV = 13,
/* KRB-PRIV encrypted part, encrypted with a key chosen by the
application (section 5.7.1) */
KRB5_KU_KRB_CRED = 14,
/* KRB-CRED encrypted part, encrypted with a key chosen by the
application (section 5.8.1) */
KRB5_KU_KRB_SAFE_CKSUM = 15,
/* KRB-SAFE cksum, keyed with a key chosen by the application
(section 5.6.1) */
KRB5_KU_OTHER_ENCRYPTED = 16,
/* Data which is defined in some specification outside of
Kerberos to be encrypted using an RFC1510 encryption type. */
KRB5_KU_OTHER_CKSUM = 17,
/* Data which is defined in some specification outside of
Kerberos to be checksummed using an RFC1510 checksum type. */
KRB5_KU_KRB_ERROR = 18,
/* Krb-error checksum */
KRB5_KU_AD_KDC_ISSUED = 19,
/* AD-KDCIssued checksum */
KRB5_KU_MANDATORY_TICKET_EXTENSION = 20,
/* Checksum for Mandatory Ticket Extensions */
KRB5_KU_AUTH_DATA_TICKET_EXTENSION = 21,
/* Checksum in Authorization Data in Ticket Extensions */
KRB5_KU_USAGE_SEAL = 22,
/* seal in GSSAPI krb5 mechanism */
KRB5_KU_USAGE_SIGN = 23,
/* sign in GSSAPI krb5 mechanism */
KRB5_KU_USAGE_SEQ = 24,
/* SEQ in GSSAPI krb5 mechanism */
KRB5_KU_USAGE_ACCEPTOR_SEAL = 22,
/* acceptor sign in GSSAPI CFX krb5 mechanism */
KRB5_KU_USAGE_ACCEPTOR_SIGN = 23,
/* acceptor seal in GSSAPI CFX krb5 mechanism */
KRB5_KU_USAGE_INITIATOR_SEAL = 24,
/* initiator sign in GSSAPI CFX krb5 mechanism */
KRB5_KU_USAGE_INITIATOR_SIGN = 25,
/* initiator seal in GSSAPI CFX krb5 mechanism */
KRB5_KU_PA_SERVER_REFERRAL_DATA = 22,
/* encrypted server referral data */
KRB5_KU_SAM_CHECKSUM = 25,
/* Checksum for the SAM-CHECKSUM field */
KRB5_KU_SAM_ENC_TRACK_ID = 26,
/* Encryption of the SAM-TRACK-ID field */
KRB5_KU_PA_SERVER_REFERRAL = 26,
/* Keyusage for the server referral in a TGS req */
KRB5_KU_SAM_ENC_NONCE_SAD = 27,
/* Encryption of the SAM-NONCE-OR-SAD field */
KRB5_KU_TGS_IMPERSONATE = -17,
/* Checksum type used in the impersonate field */
KRB5_KU_DIGEST_ENCRYPT = -18,
/* Encryption key usage used in the digest encryption field */
KRB5_KU_DIGEST_OPAQUE = -19,
/* Checksum key usage used in the digest opaque field */
KRB5_KU_KRB5SIGNEDPATH = -21
/* Checksum key usage on KRB5SignedPath */
} krb5_key_usage;
typedef krb5_key_usage krb5_keyusage;
typedef enum krb5_salttype {
KRB5_PW_SALT = KRB5_PADATA_PW_SALT,
KRB5_AFS3_SALT = KRB5_PADATA_AFS3_SALT
}krb5_salttype;
typedef struct krb5_salt {
krb5_salttype salttype;
krb5_data saltvalue;
} krb5_salt;
typedef ETYPE_INFO krb5_preauthinfo;
typedef struct {
krb5_preauthtype type;
krb5_preauthinfo info; /* list of preauthinfo for this type */
} krb5_preauthdata_entry;
typedef struct krb5_preauthdata {
unsigned len;
krb5_preauthdata_entry *val;
}krb5_preauthdata;
typedef enum krb5_address_type {
KRB5_ADDRESS_INET = 2,
KRB5_ADDRESS_NETBIOS = 20,
KRB5_ADDRESS_INET6 = 24,
KRB5_ADDRESS_ADDRPORT = 256,
KRB5_ADDRESS_IPPORT = 257
} krb5_address_type;
enum {
AP_OPTS_USE_SESSION_KEY = 1,
AP_OPTS_MUTUAL_REQUIRED = 2,
AP_OPTS_USE_SUBKEY = 4 /* library internal */
};
typedef HostAddress krb5_address;
typedef HostAddresses krb5_addresses;
typedef enum krb5_keytype {
KEYTYPE_NULL = 0,
KEYTYPE_DES = 1,
KEYTYPE_DES3 = 7,
KEYTYPE_AES128 = 17,
KEYTYPE_AES256 = 18,
KEYTYPE_ARCFOUR = 23,
KEYTYPE_ARCFOUR_56 = 24
} krb5_keytype;
typedef EncryptionKey krb5_keyblock;
typedef AP_REQ krb5_ap_req;
struct krb5_cc_ops;
#define KRB5_DEFAULT_CCFILE_ROOT "/tmp/krb5cc_"
#define KRB5_DEFAULT_CCROOT "FILE:" KRB5_DEFAULT_CCFILE_ROOT
#define KRB5_ACCEPT_NULL_ADDRESSES(C) \
krb5_config_get_bool_default((C), NULL, TRUE, \
"libdefaults", "accept_null_addresses", \
NULL)
typedef void *krb5_cc_cursor;
typedef struct krb5_ccache_data {
const struct krb5_cc_ops *ops;
krb5_data data;
}krb5_ccache_data;
typedef struct krb5_ccache_data *krb5_ccache;
typedef struct krb5_context_data *krb5_context;
typedef Realm krb5_realm;
typedef const char *krb5_const_realm; /* stupid language */
#define krb5_realm_length(r) strlen(r)
#define krb5_realm_data(r) (r)
typedef Principal krb5_principal_data;
typedef struct Principal *krb5_principal;
typedef const struct Principal *krb5_const_principal;
typedef time_t krb5_deltat;
typedef time_t krb5_timestamp;
typedef struct krb5_times {
krb5_timestamp authtime;
krb5_timestamp starttime;
krb5_timestamp endtime;
krb5_timestamp renew_till;
} krb5_times;
typedef union {
TicketFlags b;
krb5_flags i;
} krb5_ticket_flags;
/* options for krb5_get_in_tkt() */
#define KDC_OPT_FORWARDABLE (1 << 1)
#define KDC_OPT_FORWARDED (1 << 2)
#define KDC_OPT_PROXIABLE (1 << 3)
#define KDC_OPT_PROXY (1 << 4)
#define KDC_OPT_ALLOW_POSTDATE (1 << 5)
#define KDC_OPT_POSTDATED (1 << 6)
#define KDC_OPT_RENEWABLE (1 << 8)
#define KDC_OPT_REQUEST_ANONYMOUS (1 << 14)
#define KDC_OPT_DISABLE_TRANSITED_CHECK (1 << 26)
#define KDC_OPT_RENEWABLE_OK (1 << 27)
#define KDC_OPT_ENC_TKT_IN_SKEY (1 << 28)
#define KDC_OPT_RENEW (1 << 30)
#define KDC_OPT_VALIDATE (1 << 31)
typedef union {
KDCOptions b;
krb5_flags i;
} krb5_kdc_flags;
/* flags for krb5_verify_ap_req */
#define KRB5_VERIFY_AP_REQ_IGNORE_INVALID (1 << 0)
#define KRB5_GC_CACHED (1U << 0)
#define KRB5_GC_USER_USER (1U << 1)
#define KRB5_GC_EXPIRED_OK (1U << 2)
#define KRB5_GC_NO_STORE (1U << 3)
#define KRB5_GC_FORWARDABLE (1U << 4)
#define KRB5_GC_NO_TRANSIT_CHECK (1U << 5)
/* constants for compare_creds (and cc_retrieve_cred) */
#define KRB5_TC_DONT_MATCH_REALM (1U << 31)
#define KRB5_TC_MATCH_KEYTYPE (1U << 30)
#define KRB5_TC_MATCH_KTYPE KRB5_TC_MATCH_KEYTYPE /* MIT name */
#define KRB5_TC_MATCH_SRV_NAMEONLY (1 << 29)
#define KRB5_TC_MATCH_FLAGS_EXACT (1 << 28)
#define KRB5_TC_MATCH_FLAGS (1 << 27)
#define KRB5_TC_MATCH_TIMES_EXACT (1 << 26)
#define KRB5_TC_MATCH_TIMES (1 << 25)
#define KRB5_TC_MATCH_AUTHDATA (1 << 24)
#define KRB5_TC_MATCH_2ND_TKT (1 << 23)
#define KRB5_TC_MATCH_IS_SKEY (1 << 22)
typedef AuthorizationData krb5_authdata;
typedef KRB_ERROR krb5_error;
typedef struct krb5_creds {
krb5_principal client;
krb5_principal server;
krb5_keyblock session;
krb5_times times;
krb5_data ticket;
krb5_data second_ticket;
krb5_authdata authdata;
krb5_addresses addresses;
krb5_ticket_flags flags;
} krb5_creds;
typedef struct krb5_cc_cache_cursor_data *krb5_cc_cache_cursor;
typedef struct krb5_cc_ops {
const char *prefix;
const char* (*get_name)(krb5_context, krb5_ccache);
krb5_error_code (*resolve)(krb5_context, krb5_ccache *, const char *);
krb5_error_code (*gen_new)(krb5_context, krb5_ccache *);
krb5_error_code (*init)(krb5_context, krb5_ccache, krb5_principal);
krb5_error_code (*destroy)(krb5_context, krb5_ccache);
krb5_error_code (*close)(krb5_context, krb5_ccache);
krb5_error_code (*store)(krb5_context, krb5_ccache, krb5_creds*);
krb5_error_code (*retrieve)(krb5_context, krb5_ccache,
krb5_flags, const krb5_creds*, krb5_creds *);
krb5_error_code (*get_princ)(krb5_context, krb5_ccache, krb5_principal*);
krb5_error_code (*get_first)(krb5_context, krb5_ccache, krb5_cc_cursor *);
krb5_error_code (*get_next)(krb5_context, krb5_ccache,
krb5_cc_cursor*, krb5_creds*);
krb5_error_code (*end_get)(krb5_context, krb5_ccache, krb5_cc_cursor*);
krb5_error_code (*remove_cred)(krb5_context, krb5_ccache,
krb5_flags, krb5_creds*);
krb5_error_code (*set_flags)(krb5_context, krb5_ccache, krb5_flags);
int (*get_version)(krb5_context, krb5_ccache);
krb5_error_code (*get_cache_first)(krb5_context, krb5_cc_cursor *);
krb5_error_code (*get_cache_next)(krb5_context, krb5_cc_cursor, krb5_ccache *);
krb5_error_code (*end_cache_get)(krb5_context, krb5_cc_cursor);
} krb5_cc_ops;
struct krb5_log_facility;
struct krb5_config_binding {
enum { krb5_config_string, krb5_config_list } type;
char *name;
struct krb5_config_binding *next;
union {
char *string;
struct krb5_config_binding *list;
void *generic;
} u;
};
typedef struct krb5_config_binding krb5_config_binding;
typedef krb5_config_binding krb5_config_section;
enum {
KRB5_PKINIT_WIN2K = 1, /* wire compatible with Windows 2k */
KRB5_PKINIT_PACKET_CABLE = 2 /* use packet cable standard */
};
typedef struct krb5_ticket {
EncTicketPart ticket;
krb5_principal client;
krb5_principal server;
} krb5_ticket;
typedef Authenticator krb5_authenticator_data;
typedef krb5_authenticator_data *krb5_authenticator;
struct krb5_rcache_data;
typedef struct krb5_rcache_data *krb5_rcache;
typedef Authenticator krb5_donot_replay;
#define KRB5_STORAGE_HOST_BYTEORDER 0x01 /* old */
#define KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS 0x02
#define KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE 0x04
#define KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE 0x08
#define KRB5_STORAGE_BYTEORDER_MASK 0x60
#define KRB5_STORAGE_BYTEORDER_BE 0x00 /* default */
#define KRB5_STORAGE_BYTEORDER_LE 0x20
#define KRB5_STORAGE_BYTEORDER_HOST 0x40
#define KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER 0x80
struct krb5_storage_data;
typedef struct krb5_storage_data krb5_storage;
typedef struct krb5_keytab_entry {
krb5_principal principal;
krb5_kvno vno;
krb5_keyblock keyblock;
uint32_t timestamp;
} krb5_keytab_entry;
typedef struct krb5_kt_cursor {
int fd;
krb5_storage *sp;
void *data;
} krb5_kt_cursor;
struct krb5_keytab_data;
typedef struct krb5_keytab_data *krb5_keytab;
#define KRB5_KT_PREFIX_MAX_LEN 30
struct krb5_keytab_data {
const char *prefix;
krb5_error_code (*resolve)(krb5_context, const char*, krb5_keytab);
krb5_error_code (*get_name)(krb5_context, krb5_keytab, char*, size_t);
krb5_error_code (*close)(krb5_context, krb5_keytab);
krb5_error_code (*get)(krb5_context, krb5_keytab, krb5_const_principal,
krb5_kvno, krb5_enctype, krb5_keytab_entry*);
krb5_error_code (*start_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
krb5_error_code (*next_entry)(krb5_context, krb5_keytab,
krb5_keytab_entry*, krb5_kt_cursor*);
krb5_error_code (*end_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
krb5_error_code (*add)(krb5_context, krb5_keytab, krb5_keytab_entry*);
krb5_error_code (*remove)(krb5_context, krb5_keytab, krb5_keytab_entry*);
void *data;
int32_t version;
};
typedef struct krb5_keytab_data krb5_kt_ops;
struct krb5_keytab_key_proc_args {
krb5_keytab keytab;
krb5_principal principal;
};
typedef struct krb5_keytab_key_proc_args krb5_keytab_key_proc_args;
typedef struct krb5_replay_data {
krb5_timestamp timestamp;
int32_t usec;
uint32_t seq;
} krb5_replay_data;
/* flags for krb5_auth_con_setflags */
enum {
KRB5_AUTH_CONTEXT_DO_TIME = 1,
KRB5_AUTH_CONTEXT_RET_TIME = 2,
KRB5_AUTH_CONTEXT_DO_SEQUENCE = 4,
KRB5_AUTH_CONTEXT_RET_SEQUENCE = 8,
KRB5_AUTH_CONTEXT_PERMIT_ALL = 16,
KRB5_AUTH_CONTEXT_USE_SUBKEY = 32,
KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED = 64
};
/* flags for krb5_auth_con_genaddrs */
enum {
KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR = 1,
KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR = 3,
KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR = 4,
KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR = 12
};
typedef struct krb5_auth_context_data {
unsigned int flags;
krb5_address *local_address;
krb5_address *remote_address;
int16_t local_port;
int16_t remote_port;
krb5_keyblock *keyblock;
krb5_keyblock *local_subkey;
krb5_keyblock *remote_subkey;
uint32_t local_seqnumber;
uint32_t remote_seqnumber;
krb5_authenticator authenticator;
krb5_pointer i_vector;
krb5_rcache rcache;
krb5_keytype keytype; /* ¿requested key type ? */
krb5_cksumtype cksumtype; /* ¡requested checksum type! */
}krb5_auth_context_data, *krb5_auth_context;
typedef struct {
KDC_REP kdc_rep;
EncKDCRepPart enc_part;
KRB_ERROR error;
} krb5_kdc_rep;
extern const char *heimdal_version, *heimdal_long_version;
typedef void (*krb5_log_log_func_t)(const char*, const char*, void*);
typedef void (*krb5_log_close_func_t)(void*);
typedef struct krb5_log_facility {
char *program;
int len;
struct facility *val;
} krb5_log_facility;
typedef EncAPRepPart krb5_ap_rep_enc_part;
#define KRB5_RECVAUTH_IGNORE_VERSION 1
#define KRB5_SENDAUTH_VERSION "KRB5_SENDAUTH_V1.0"
#define KRB5_TGS_NAME_SIZE (6)
#define KRB5_TGS_NAME ("krbtgt")
#define KRB5_DIGEST_NAME ("digest")
/* variables */
extern const char *krb5_config_file;
extern const char *krb5_defkeyname;
typedef enum {
KRB5_PROMPT_TYPE_PASSWORD = 0x1,
KRB5_PROMPT_TYPE_NEW_PASSWORD = 0x2,
KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN = 0x3,
KRB5_PROMPT_TYPE_PREAUTH = 0x4,
KRB5_PROMPT_TYPE_INFO = 0x5
} krb5_prompt_type;
typedef struct _krb5_prompt {
const char *prompt;
int hidden;
krb5_data *reply;
krb5_prompt_type type;
} krb5_prompt;
typedef int (*krb5_prompter_fct)(krb5_context /*context*/,
void * /*data*/,
const char * /*name*/,
const char * /*banner*/,
int /*num_prompts*/,
krb5_prompt /*prompts*/[]);
typedef krb5_error_code (*krb5_key_proc)(krb5_context /*context*/,
krb5_enctype /*type*/,
krb5_salt /*salt*/,
krb5_const_pointer /*keyseed*/,
krb5_keyblock ** /*key*/);
typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context /*context*/,
krb5_keyblock * /*key*/,
krb5_key_usage /*usage*/,
krb5_const_pointer /*decrypt_arg*/,
krb5_kdc_rep * /*dec_rep*/);
typedef krb5_error_code (*krb5_s2k_proc)(krb5_context /*context*/,
krb5_enctype /*type*/,
krb5_const_pointer /*keyseed*/,
krb5_salt /*salt*/,
krb5_data * /*s2kparms*/,
krb5_keyblock ** /*key*/);
struct _krb5_get_init_creds_opt_private;
typedef struct _krb5_get_init_creds_opt {
krb5_flags flags;
krb5_deltat tkt_life;
krb5_deltat renew_life;
int forwardable;
int proxiable;
int anonymous;
krb5_enctype *etype_list;
int etype_list_length;
krb5_addresses *address_list;
/* XXX the next three should not be used, as they may be
removed later */
krb5_preauthtype *preauth_list;
int preauth_list_length;
krb5_data *salt;
struct _krb5_get_init_creds_opt_private *opt_private;
} krb5_get_init_creds_opt;
#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001
#define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE 0x0002
#define KRB5_GET_INIT_CREDS_OPT_FORWARDABLE 0x0004
#define KRB5_GET_INIT_CREDS_OPT_PROXIABLE 0x0008
#define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST 0x0010
#define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST 0x0020
#define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST 0x0040
#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080
#define KRB5_GET_INIT_CREDS_OPT_ANONYMOUS 0x0100
#define KRB5_GET_INIT_CREDS_OPT_DISABLE_TRANSITED_CHECK 0x0200
typedef struct _krb5_verify_init_creds_opt {
krb5_flags flags;
int ap_req_nofail;
} krb5_verify_init_creds_opt;
#define KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL 0x0001
typedef struct krb5_verify_opt {
unsigned int flags;
krb5_ccache ccache;
krb5_keytab keytab;
krb5_boolean secure;
const char *service;
} krb5_verify_opt;
#define KRB5_VERIFY_LREALMS 1
#define KRB5_VERIFY_NO_ADDRESSES 2
extern const krb5_cc_ops krb5_acc_ops;
extern const krb5_cc_ops krb5_fcc_ops;
extern const krb5_cc_ops krb5_mcc_ops;
extern const krb5_cc_ops krb5_kcm_ops;
extern const krb5_kt_ops krb5_fkt_ops;
extern const krb5_kt_ops krb5_wrfkt_ops;
extern const krb5_kt_ops krb5_javakt_ops;
extern const krb5_kt_ops krb5_mkt_ops;
extern const krb5_kt_ops krb5_akf_ops;
extern const krb5_kt_ops krb4_fkt_ops;
extern const krb5_kt_ops krb5_srvtab_fkt_ops;
extern const krb5_kt_ops krb5_any_ops;
#define KRB5_KPASSWD_VERS_CHANGEPW 1
#define KRB5_KPASSWD_VERS_SETPW 0xff80
#define KRB5_KPASSWD_SUCCESS 0
#define KRB5_KPASSWD_MALFORMED 1
#define KRB5_KPASSWD_HARDERROR 2
#define KRB5_KPASSWD_AUTHERROR 3
#define KRB5_KPASSWD_SOFTERROR 4
#define KRB5_KPASSWD_ACCESSDENIED 5
#define KRB5_KPASSWD_BAD_VERSION 6
#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7
#define KPASSWD_PORT 464
/* types for the new krbhst interface */
struct krb5_krbhst_data;
typedef struct krb5_krbhst_data *krb5_krbhst_handle;
#define KRB5_KRBHST_KDC 1
#define KRB5_KRBHST_ADMIN 2
#define KRB5_KRBHST_CHANGEPW 3
#define KRB5_KRBHST_KRB524 4
typedef struct krb5_krbhst_info {
enum { KRB5_KRBHST_UDP,
KRB5_KRBHST_TCP,
KRB5_KRBHST_HTTP } proto;
unsigned short port;
unsigned short def_port;
struct addrinfo *ai;
struct krb5_krbhst_info *next;
char hostname[1]; /* has to come last */
} krb5_krbhst_info;
/* flags for krb5_krbhst_init_flags (and krb5_send_to_kdc_flags) */
enum {
KRB5_KRBHST_FLAGS_MASTER = 1,
KRB5_KRBHST_FLAGS_LARGE_MSG = 2
};
typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context,
void *,
krb5_krbhst_info *,
const krb5_data *,
krb5_data *);
/* flags for krb5_parse_name_flags */
enum {
KRB5_PRINCIPAL_PARSE_NO_REALM = 1,
KRB5_PRINCIPAL_PARSE_MUST_REALM = 2
};
/* flags for krb5_unparse_name_flags */
enum {
KRB5_PRINCIPAL_UNPARSE_SHORT = 1,
KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2
};
struct credentials; /* this is to keep the compiler happy */
struct getargs;
struct sockaddr;
#include <krb5-protos.h>
#endif /* __KRB5_H__ */
+230
View File
@@ -0,0 +1,230 @@
/*
* Copyright (c) 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $Id: krb5_ccapi.h,v 1.3 2006/05/05 09:29:59 lha Exp $ */
#ifndef KRB5_CCAPI_H
#define KRB5_CCAPI_H 1
#include <krb5-types.h>
enum {
cc_credentials_v5 = 2
};
enum {
ccapi_version_3 = 3,
ccapi_version_4 = 4
};
enum {
ccNoError = 0,
ccIteratorEnd = 201,
ccErrBadParam,
ccErrNoMem,
ccErrInvalidContext,
ccErrInvalidCCache,
ccErrInvalidString, /* 206 */
ccErrInvalidCredentials,
ccErrInvalidCCacheIterator,
ccErrInvalidCredentialsIterator,
ccErrInvalidLock,
ccErrBadName, /* 211 */
ccErrBadCredentialsVersion,
ccErrBadAPIVersion,
ccErrContextLocked,
ccErrContextUnlocked,
ccErrCCacheLocked, /* 216 */
ccErrCCacheUnlocked,
ccErrBadLockType,
ccErrNeverDefault,
ccErrCredentialsNotFound,
ccErrCCacheNotFound, /* 221 */
ccErrContextNotFound,
ccErrServerUnavailable,
ccErrServerInsecure,
ccErrServerCantBecomeUID,
ccErrTimeOffsetNotSet /* 226 */
};
typedef int32_t cc_int32;
typedef uint32_t cc_uint32;
typedef struct cc_context_t *cc_context_t;
typedef struct cc_ccache_t *cc_ccache_t;
typedef struct cc_ccache_iterator_t *cc_ccache_iterator_t;
typedef struct cc_credentials_v5_t cc_credentials_v5_t;
typedef struct cc_credentials_t *cc_credentials_t;
typedef struct cc_credentials_iterator_t *cc_credentials_iterator_t;
typedef struct cc_string_t *cc_string_t;
typedef time_t cc_time_t;
typedef struct cc_data {
cc_uint32 type;
cc_uint32 length;
void *data;
} cc_data;
struct cc_credentials_v5_t {
char *client;
char *server;
cc_data keyblock;
cc_time_t authtime;
cc_time_t starttime;
cc_time_t endtime;
cc_time_t renew_till;
cc_uint32 is_skey;
cc_uint32 ticket_flags;
#define KRB5_CCAPI_TKT_FLG_FORWARDABLE 0x40000000
#define KRB5_CCAPI_TKT_FLG_FORWARDED 0x20000000
#define KRB5_CCAPI_TKT_FLG_PROXIABLE 0x10000000
#define KRB5_CCAPI_TKT_FLG_PROXY 0x08000000
#define KRB5_CCAPI_TKT_FLG_MAY_POSTDATE 0x04000000
#define KRB5_CCAPI_TKT_FLG_POSTDATED 0x02000000
#define KRB5_CCAPI_TKT_FLG_INVALID 0x01000000
#define KRB5_CCAPI_TKT_FLG_RENEWABLE 0x00800000
#define KRB5_CCAPI_TKT_FLG_INITIAL 0x00400000
#define KRB5_CCAPI_TKT_FLG_PRE_AUTH 0x00200000
#define KRB5_CCAPI_TKT_FLG_HW_AUTH 0x00100000
#define KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED 0x00080000
#define KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE 0x00040000
#define KRB5_CCAPI_TKT_FLG_ANONYMOUS 0x00020000
cc_data **addresses;
cc_data ticket;
cc_data second_ticket;
cc_data **authdata;
};
typedef struct cc_string_functions {
cc_int32 (*release)(cc_string_t);
} cc_string_functions;
struct cc_string_t {
const char *data;
const cc_string_functions *func;
};
typedef struct cc_credentials_union {
cc_int32 version;
union {
cc_credentials_v5_t* credentials_v5;
} credentials;
} cc_credentials_union;
struct cc_credentials_functions {
cc_int32 (*release)(cc_credentials_t);
cc_int32 (*compare)(cc_credentials_t, cc_credentials_t, cc_uint32*);
};
struct cc_credentials_t {
const cc_credentials_union* data;
const struct cc_credentials_functions* func;
};
struct cc_credentials_iterator_functions {
cc_int32 (*release)(cc_credentials_iterator_t);
cc_int32 (*next)(cc_credentials_iterator_t, cc_credentials_t*);
};
struct cc_credentials_iterator_t {
const struct cc_credentials_iterator_functions *func;
};
struct cc_ccache_iterator_functions {
cc_int32 (*release) (cc_ccache_iterator_t);
cc_int32 (*next)(cc_ccache_iterator_t, cc_ccache_t*);
};
struct cc_ccache_iterator_t {
const struct cc_ccache_iterator_functions* func;
};
typedef struct cc_ccache_functions {
cc_int32 (*release)(cc_ccache_t);
cc_int32 (*destroy)(cc_ccache_t);
cc_int32 (*set_default)(cc_ccache_t);
cc_int32 (*get_credentials_version)(cc_ccache_t, cc_uint32*);
cc_int32 (*get_name)(cc_ccache_t ccache,cc_string_t*);
cc_int32 (*get_principal)(cc_ccache_t, cc_uint32, cc_string_t*);
cc_int32 (*set_principal)(cc_ccache_t, cc_uint32, const char*);
cc_int32 (*store_credentials)(cc_ccache_t, const cc_credentials_union*);
cc_int32 (*remove_credentials)(cc_ccache_t, cc_credentials_t);
cc_int32 (*new_credentials_iterator)(cc_ccache_t,
cc_credentials_iterator_t*);
cc_int32 (*move)(cc_ccache_t source, cc_ccache_t);
cc_int32 (*lock)(cc_ccache_t, cc_uint32, cc_uint32);
cc_int32 (*unlock)(cc_ccache_t);
cc_int32 (*get_last_default_time)(cc_ccache_t, cc_time_t*);
cc_int32 (*get_change_time)(cc_ccache_t ccache, cc_time_t*);
cc_int32 (*compare)(cc_ccache_t, cc_ccache_t, cc_uint32*);
cc_int32 (*get_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t *);
cc_int32 (*set_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t);
cc_int32 (*clear_kdc_time_offset)(cc_ccache_t, cc_int32);
} cc_ccache_functions;
struct cc_ccache_t {
const cc_ccache_functions *func;
};
struct cc_context_functions {
cc_int32 (*release)(cc_context_t);
cc_int32 (*get_change_time)(cc_context_t, cc_time_t *);
cc_int32 (*get_default_ccache_name)(cc_context_t, cc_string_t*);
cc_int32 (*open_ccache)(cc_context_t, const char*, cc_ccache_t *);
cc_int32 (*open_default_ccache)(cc_context_t, cc_ccache_t*);
cc_int32 (*create_ccache)(cc_context_t,const char*, cc_uint32,
const char*, cc_ccache_t*);
cc_int32 (*create_default_ccache)(cc_context_t, cc_uint32,
const char*, cc_ccache_t*);
cc_int32 (*create_new_ccache)(cc_context_t, cc_uint32,
const char*, cc_ccache_t*);
cc_int32 (*new_ccache_iterator)(cc_context_t, cc_ccache_iterator_t*);
cc_int32 (*lock)(cc_context_t, cc_uint32, cc_uint32);
cc_int32 (*unlock)(cc_context_t);
cc_int32 (*compare)(cc_context_t, cc_context_t, cc_uint32*);
};
struct cc_context_t {
const struct cc_context_functions* func;
};
typedef cc_int32
(*cc_initialize_func)(cc_context_t*, cc_int32, cc_int32 *, char const **);
#endif /* KRB5_CCAPI_H */
+259
View File
@@ -0,0 +1,259 @@
#
# Error messages for the krb5 library
#
# This might look like a com_err file, but is not
#
id "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $"
error_table krb5
prefix KRB5KDC_ERR
error_code NONE, "No error"
error_code NAME_EXP, "Client's entry in database has expired"
error_code SERVICE_EXP, "Server's entry in database has expired"
error_code BAD_PVNO, "Requested protocol version not supported"
error_code C_OLD_MAST_KVNO, "Client's key is encrypted in an old master key"
error_code S_OLD_MAST_KVNO, "Server's key is encrypted in an old master key"
error_code C_PRINCIPAL_UNKNOWN, "Client not found in Kerberos database"
error_code S_PRINCIPAL_UNKNOWN, "Server not found in Kerberos database"
error_code PRINCIPAL_NOT_UNIQUE,"Principal has multiple entries in Kerberos database"
error_code NULL_KEY, "Client or server has a null key"
error_code CANNOT_POSTDATE, "Ticket is ineligible for postdating"
error_code NEVER_VALID, "Requested effective lifetime is negative or too short"
error_code POLICY, "KDC policy rejects request"
error_code BADOPTION, "KDC can't fulfill requested option"
error_code ETYPE_NOSUPP, "KDC has no support for encryption type"
error_code SUMTYPE_NOSUPP, "KDC has no support for checksum type"
error_code PADATA_TYPE_NOSUPP, "KDC has no support for padata type"
error_code TRTYPE_NOSUPP, "KDC has no support for transited type"
error_code CLIENT_REVOKED, "Clients credentials have been revoked"
error_code SERVICE_REVOKED, "Credentials for server have been revoked"
error_code TGT_REVOKED, "TGT has been revoked"
error_code CLIENT_NOTYET, "Client not yet valid - try again later"
error_code SERVICE_NOTYET, "Server not yet valid - try again later"
error_code KEY_EXPIRED, "Password has expired"
error_code PREAUTH_FAILED, "Preauthentication failed"
error_code PREAUTH_REQUIRED, "Additional pre-authentication required"
error_code SERVER_NOMATCH, "Requested server and ticket don't match"
# 27-30 are reserved
index 31
prefix KRB5KRB_AP
error_code ERR_BAD_INTEGRITY, "Decrypt integrity check failed"
error_code ERR_TKT_EXPIRED, "Ticket expired"
error_code ERR_TKT_NYV, "Ticket not yet valid"
error_code ERR_REPEAT, "Request is a replay"
error_code ERR_NOT_US, "The ticket isn't for us"
error_code ERR_BADMATCH, "Ticket/authenticator don't match"
error_code ERR_SKEW, "Clock skew too great"
error_code ERR_BADADDR, "Incorrect net address"
error_code ERR_BADVERSION, "Protocol version mismatch"
error_code ERR_MSG_TYPE, "Invalid message type"
error_code ERR_MODIFIED, "Message stream modified"
error_code ERR_BADORDER, "Message out of order"
error_code ERR_ILL_CR_TKT, "Invalid cross-realm ticket"
error_code ERR_BADKEYVER, "Key version is not available"
error_code ERR_NOKEY, "Service key not available"
error_code ERR_MUT_FAIL, "Mutual authentication failed"
error_code ERR_BADDIRECTION, "Incorrect message direction"
error_code ERR_METHOD, "Alternative authentication method required"
error_code ERR_BADSEQ, "Incorrect sequence number in message"
error_code ERR_INAPP_CKSUM, "Inappropriate type of checksum in message"
error_code PATH_NOT_ACCEPTED, "Policy rejects transited path"
prefix KRB5KRB_ERR
error_code RESPONSE_TOO_BIG, "Response too big for UDP, retry with TCP"
# 53-59 are reserved
index 60
error_code GENERIC, "Generic error (see e-text)"
error_code FIELD_TOOLONG, "Field is too long for this implementation"
# pkinit
index 62
prefix KRB5_KDC_ERR
error_code CLIENT_NOT_TRUSTED, "Client not trusted"
error_code KDC_NOT_TRUSTED, "KDC not trusted"
error_code INVALID_SIG, "Invalid signature"
error_code DH_KEY_PARAMETERS_NOT_ACCEPTED, "DH parameters not accepted"
index 69
prefix KRB5_AP_ERR
error_code USER_TO_USER_REQUIRED, "User to user required"
index 70
prefix KRB5_KDC_ERR
error_code CANT_VERIFY_CERTIFICATE, "Cannot verify certificate"
error_code INVALID_CERTIFICATE, "Certificate invalid"
error_code REVOKED_CERTIFICATE, "Certificate revoked"
error_code REVOCATION_STATUS_UNKNOWN, "Revocation status unknown"
error_code CLIENT_NAME_MISMATCH, "Revocation status unknown"
error_code INCONSISTENT_KEY_PURPOSE, "Inconsistent key purpose"
error_code DIGEST_IN_CERT_NOT_ACCEPTED, "Digest in certificate not accepted"
error_code PA_CHECKSUM_MUST_BE_INCLUDED, "paChecksum must be included"
error_code DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED, "Digest in signedData not accepted"
error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not supported"
## these are never used
#index 80
#prefix KRB5_IAKERB
#error_code ERR_KDC_NOT_FOUND, "IAKERB proxy could not find a KDC"
#error_code ERR_KDC_NO_RESPONSE, "IAKERB proxy never reeived a response from a KDC"
# 82-127 are reserved
index 128
prefix
error_code KRB5_ERR_RCSID, "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $"
error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode"
error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password"
error_code KRB5_LIBOS_BADPWDMATCH, "Password mismatch"
error_code KRB5_LIBOS_PWDINTR, "Password read interrupted"
error_code KRB5_PARSE_ILLCHAR, "Invalid character in component name"
error_code KRB5_PARSE_MALFORMED, "Malformed representation of principal"
error_code KRB5_CONFIG_CANTOPEN, "Can't open/find configuration file"
error_code KRB5_CONFIG_BADFORMAT, "Improper format of configuration file"
error_code KRB5_CONFIG_NOTENUFSPACE, "Insufficient space to return complete information"
error_code KRB5_BADMSGTYPE, "Invalid message type specified for encoding"
error_code KRB5_CC_BADNAME, "Credential cache name malformed"
error_code KRB5_CC_UNKNOWN_TYPE, "Unknown credential cache type"
error_code KRB5_CC_NOTFOUND, "Matching credential not found"
error_code KRB5_CC_END, "End of credential cache reached"
error_code KRB5_NO_TKT_SUPPLIED, "Request did not supply a ticket"
error_code KRB5KRB_AP_WRONG_PRINC, "Wrong principal in request"
error_code KRB5KRB_AP_ERR_TKT_INVALID, "Ticket has invalid flag set"
error_code KRB5_PRINC_NOMATCH, "Requested principal and ticket don't match"
error_code KRB5_KDCREP_MODIFIED, "KDC reply did not match expectations"
error_code KRB5_KDCREP_SKEW, "Clock skew too great in KDC reply"
error_code KRB5_IN_TKT_REALM_MISMATCH, "Client/server realm mismatch in initial ticket request"
error_code KRB5_PROG_ETYPE_NOSUPP, "Program lacks support for encryption type"
error_code KRB5_PROG_KEYTYPE_NOSUPP, "Program lacks support for key type"
error_code KRB5_WRONG_ETYPE, "Requested encryption type not used in message"
error_code KRB5_PROG_SUMTYPE_NOSUPP, "Program lacks support for checksum type"
error_code KRB5_REALM_UNKNOWN, "Cannot find KDC for requested realm"
error_code KRB5_SERVICE_UNKNOWN, "Kerberos service unknown"
error_code KRB5_KDC_UNREACH, "Cannot contact any KDC for requested realm"
error_code KRB5_NO_LOCALNAME, "No local name found for principal name"
error_code KRB5_MUTUAL_FAILED, "Mutual authentication failed"
# some of these should be combined/supplanted by system codes
error_code KRB5_RC_TYPE_EXISTS, "Replay cache type is already registered"
error_code KRB5_RC_MALLOC, "No more memory to allocate (in replay cache code)"
error_code KRB5_RC_TYPE_NOTFOUND, "Replay cache type is unknown"
error_code KRB5_RC_UNKNOWN, "Generic unknown RC error"
error_code KRB5_RC_REPLAY, "Message is a replay"
error_code KRB5_RC_IO, "Replay I/O operation failed XXX"
error_code KRB5_RC_NOIO, "Replay cache type does not support non-volatile storage"
error_code KRB5_RC_PARSE, "Replay cache name parse/format error"
error_code KRB5_RC_IO_EOF, "End-of-file on replay cache I/O"
error_code KRB5_RC_IO_MALLOC, "No more memory to allocate (in replay cache I/O code)"
error_code KRB5_RC_IO_PERM, "Permission denied in replay cache code"
error_code KRB5_RC_IO_IO, "I/O error in replay cache i/o code"
error_code KRB5_RC_IO_UNKNOWN, "Generic unknown RC/IO error"
error_code KRB5_RC_IO_SPACE, "Insufficient system space to store replay information"
error_code KRB5_TRANS_CANTOPEN, "Can't open/find realm translation file"
error_code KRB5_TRANS_BADFORMAT, "Improper format of realm translation file"
error_code KRB5_LNAME_CANTOPEN, "Can't open/find lname translation database"
error_code KRB5_LNAME_NOTRANS, "No translation available for requested principal"
error_code KRB5_LNAME_BADFORMAT, "Improper format of translation database entry"
error_code KRB5_CRYPTO_INTERNAL, "Cryptosystem internal error"
error_code KRB5_KT_BADNAME, "Key table name malformed"
error_code KRB5_KT_UNKNOWN_TYPE, "Unknown Key table type"
error_code KRB5_KT_NOTFOUND, "Key table entry not found"
error_code KRB5_KT_END, "End of key table reached"
error_code KRB5_KT_NOWRITE, "Cannot write to specified key table"
error_code KRB5_KT_IOERR, "Error writing to key table"
error_code KRB5_NO_TKT_IN_RLM, "Cannot find ticket for requested realm"
error_code KRB5DES_BAD_KEYPAR, "DES key has bad parity"
error_code KRB5DES_WEAK_KEY, "DES key is a weak key"
error_code KRB5_BAD_ENCTYPE, "Bad encryption type"
error_code KRB5_BAD_KEYSIZE, "Key size is incompatible with encryption type"
error_code KRB5_BAD_MSIZE, "Message size is incompatible with encryption type"
error_code KRB5_CC_TYPE_EXISTS, "Credentials cache type is already registered."
error_code KRB5_KT_TYPE_EXISTS, "Key table type is already registered."
error_code KRB5_CC_IO, "Credentials cache I/O operation failed XXX"
error_code KRB5_FCC_PERM, "Credentials cache file permissions incorrect"
error_code KRB5_FCC_NOFILE, "No credentials cache file found"
error_code KRB5_FCC_INTERNAL, "Internal file credentials cache error"
error_code KRB5_CC_WRITE, "Error writing to credentials cache file"
error_code KRB5_CC_NOMEM, "No more memory to allocate (in credentials cache code)"
error_code KRB5_CC_FORMAT, "Bad format in credentials cache"
error_code KRB5_CC_NOT_KTYPE, "No credentials found with supported encryption types"
# errors for dual tgt library calls
error_code KRB5_INVALID_FLAGS, "Invalid KDC option combination (library internal error)"
error_code KRB5_NO_2ND_TKT, "Request missing second ticket"
error_code KRB5_NOCREDS_SUPPLIED, "No credentials supplied to library routine"
# errors for sendauth (and recvauth)
error_code KRB5_SENDAUTH_BADAUTHVERS, "Bad sendauth version was sent"
error_code KRB5_SENDAUTH_BADAPPLVERS, "Bad application version was sent (via sendauth)"
error_code KRB5_SENDAUTH_BADRESPONSE, "Bad response (during sendauth exchange)"
error_code KRB5_SENDAUTH_REJECTED, "Server rejected authentication (during sendauth exchange)"
# errors for preauthentication
error_code KRB5_PREAUTH_BAD_TYPE, "Unsupported preauthentication type"
error_code KRB5_PREAUTH_NO_KEY, "Required preauthentication key not supplied"
error_code KRB5_PREAUTH_FAILED, "Generic preauthentication failure"
# version number errors
error_code KRB5_RCACHE_BADVNO, "Unsupported replay cache format version number"
error_code KRB5_CCACHE_BADVNO, "Unsupported credentials cache format version number"
error_code KRB5_KEYTAB_BADVNO, "Unsupported key table format version number"
#
#
error_code KRB5_PROG_ATYPE_NOSUPP, "Program lacks support for address type"
error_code KRB5_RC_REQUIRED, "Message replay detection requires rcache parameter"
error_code KRB5_ERR_BAD_HOSTNAME, "Hostname cannot be canonicalized"
error_code KRB5_ERR_HOST_REALM_UNKNOWN, "Cannot determine realm for host"
error_code KRB5_SNAME_UNSUPP_NAMETYPE, "Conversion to service principal undefined for name type"
error_code KRB5KRB_AP_ERR_V4_REPLY, "Initial Ticket response appears to be Version 4"
error_code KRB5_REALM_CANT_RESOLVE, "Cannot resolve KDC for requested realm"
error_code KRB5_TKT_NOT_FORWARDABLE, "Requesting ticket can't get forwardable tickets"
error_code KRB5_FWD_BAD_PRINCIPAL, "Bad principal name while trying to forward credentials"
error_code KRB5_GET_IN_TKT_LOOP, "Looping detected inside krb5_get_in_tkt"
error_code KRB5_CONFIG_NODEFREALM, "Configuration file does not specify default realm"
error_code KRB5_SAM_UNSUPPORTED, "Bad SAM flags in obtain_sam_padata"
error_code KRB5_SAM_INVALID_ETYPE, "Invalid encryption type in SAM challenge"
error_code KRB5_SAM_NO_CHECKSUM, "Missing checksum in SAM challenge"
error_code KRB5_SAM_BAD_CHECKSUM, "Bad checksum in SAM challenge"
index 238
error_code KRB5_OBSOLETE_FN, "Program called an obsolete, deleted function"
index 245
error_code KRB5_ERR_BAD_S2K_PARAMS, "Invalid key generation parameters from KDC"
error_code KRB5_ERR_NO_SERVICE, "Service not available"
error_code KRB5_CC_NOSUPP, "Credential cache function not supported"
error_code KRB5_DELTAT_BADFORMAT, "Invalid format of Kerberos lifetime or clock skew string"
end
+263
View File
@@ -0,0 +1,263 @@
/*
* Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $Id: krb5_locl.h,v 1.93 2006/10/20 18:13:31 lha Exp $ */
#ifndef __KRB5_LOCL_H__
#define __KRB5_LOCL_H__
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
#include <sys/ioctl.h>
#endif
#ifdef HAVE_PWD_H
#undef _POSIX_PTHREAD_SEMANTICS
/* This gets us the 5-arg getpwnam_r on Solaris 9. */
#define _POSIX_PTHREAD_SEMANTICS
#include <pwd.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <time.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#ifdef HAVE_NETINET6_IN6_H
#include <netinet6/in6.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef _AIX
struct ether_addr;
struct mbuf;
struct sockaddr_dl;
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
#endif
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#ifdef HAVE_CRYPT_H
#undef des_encrypt
#define des_encrypt wingless_pigs_mostly_fail_to_fly
#include <crypt.h>
#undef des_encrypt
#endif
#ifdef HAVE_DOOR_CREATE
#include <door.h>
#endif
#include <roken.h>
#include <parse_time.h>
#include <base64.h>
#include "crypto-headers.h"
#include <krb5_asn1.h>
struct send_to_kdc;
/* XXX glue for pkinit */
struct krb5_pk_identity;
struct krb5_pk_cert;
struct ContentInfo;
typedef struct krb5_pk_init_ctx_data *krb5_pk_init_ctx;
struct krb5_dh_moduli;
/* v4 glue */
struct _krb5_krb_auth_data;
struct krb5_plugin;
enum plugin_type {
PLUGIN_TYPE_DATA = 1,
PLUGIN_TYPE_FUNC
};
#include <der.h>
#include <krb5.h>
#include <krb5_err.h>
#include <asn1_err.h>
#ifdef PKINIT
#include <hx509_err.h>
#endif
#include <krb5-private.h>
#include "heim_threads.h"
#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
/* should this be public? */
#define KEYTAB_DEFAULT "ANY:FILE:" SYSCONFDIR "/krb5.keytab,krb4:" SYSCONFDIR "/srvtab"
#define KEYTAB_DEFAULT_MODIFY "FILE:" SYSCONFDIR "/krb5.keytab"
#define MODULI_FILE SYSCONFDIR "/krb5.moduli"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define KRB5_BUFSIZ 1024
typedef enum {
KRB5_INIT_CREDS_TRISTATE_UNSET = 0,
KRB5_INIT_CREDS_TRISTATE_TRUE,
KRB5_INIT_CREDS_TRISTATE_FALSE
} krb5_get_init_creds_tristate;
struct _krb5_get_init_creds_opt_private {
int refcount;
/* ENC_TIMESTAMP */
const char *password;
krb5_s2k_proc key_proc;
/* PA_PAC_REQUEST */
krb5_get_init_creds_tristate req_pac;
/* PKINIT */
krb5_pk_init_ctx pk_init_ctx;
int canonicalize;
KRB_ERROR *error;
krb5_get_init_creds_tristate addressless;
};
typedef struct krb5_context_data {
krb5_enctype *etypes;
krb5_enctype *etypes_des;
char **default_realms;
time_t max_skew;
time_t kdc_timeout;
unsigned max_retries;
int32_t kdc_sec_offset;
int32_t kdc_usec_offset;
krb5_config_section *cf;
struct et_list *et_list;
struct krb5_log_facility *warn_dest;
krb5_cc_ops *cc_ops;
int num_cc_ops;
const char *http_proxy;
const char *time_fmt;
krb5_boolean log_utc;
const char *default_keytab;
const char *default_keytab_modify;
krb5_boolean use_admin_kdc;
krb5_addresses *extra_addresses;
krb5_boolean scan_interfaces; /* `ifconfig -a' */
krb5_boolean srv_lookup; /* do SRV lookups */
krb5_boolean srv_try_txt; /* try TXT records also */
int32_t fcache_vno; /* create cache files w/ this
version */
int num_kt_types; /* # of registered keytab types */
struct krb5_keytab_data *kt_types; /* registered keytab types */
const char *date_fmt;
char *error_string;
char error_buf[256];
krb5_addresses *ignore_addresses;
char *default_cc_name;
int pkinit_flags;
void *mutex; /* protects error_string/error_buf */
int large_msg_size;
int dns_canonicalize_hostname;
struct send_to_kdc *send_to_kdc;
void *mem_ctx; /* Some parts of Samba4 need a valid
memory context (under the event
context) to use */
} krb5_context_data;
/*
* Configurable options
*/
#ifndef KRB5_DEFAULT_CCNAME
#ifdef __APPLE__
#define KRB5_DEFAULT_CCNAME "API:"
#else
#define KRB5_DEFAULT_CCNAME "FILE:/tmp/krb5cc_%{uid}"
#endif
#endif
#ifndef KRB5_ADDRESSLESS_DEFAULT
#define KRB5_ADDRESSLESS_DEFAULT TRUE
#endif
#endif /* __KRB5_LOCL_H__ */
+988
View File
@@ -0,0 +1,988 @@
/*
* Copyright (c) 2001 - 2003 Kungliga Tekniska Hgskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include <resolve.h>
#include "locate_plugin.h"
RCSID("$Id: krbhst.c,v 1.58 2006/11/12 20:05:20 lha Exp $");
static int
string_to_proto(const char *string)
{
if(strcasecmp(string, "udp") == 0)
return KRB5_KRBHST_UDP;
else if(strcasecmp(string, "tcp") == 0)
return KRB5_KRBHST_TCP;
else if(strcasecmp(string, "http") == 0)
return KRB5_KRBHST_HTTP;
return -1;
}
/*
* set `res' and `count' to the result of looking up SRV RR in DNS for
* `proto', `proto', `realm' using `dns_type'.
* if `port' != 0, force that port number
*/
static krb5_error_code
srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
const char *realm, const char *dns_type,
const char *proto, const char *service, int port)
{
char domain[1024];
struct dns_reply *r;
struct resource_record *rr;
int num_srv;
int proto_num;
int def_port;
*res = NULL;
*count = 0;
proto_num = string_to_proto(proto);
if(proto_num < 0) {
krb5_set_error_string(context, "unknown protocol `%s'", proto);
return EINVAL;
}
if(proto_num == KRB5_KRBHST_HTTP)
def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80));
else if(port == 0)
def_port = ntohs(krb5_getportbyname (context, service, proto, 88));
else
def_port = port;
snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm);
r = dns_lookup(domain, dns_type);
if(r == NULL)
return KRB5_KDC_UNREACH;
for(num_srv = 0, rr = r->head; rr; rr = rr->next)
if(rr->type == T_SRV)
num_srv++;
*res = malloc(num_srv * sizeof(**res));
if(*res == NULL) {
dns_free_data(r);
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
dns_srv_order(r);
for(num_srv = 0, rr = r->head; rr; rr = rr->next)
if(rr->type == T_SRV) {
krb5_krbhst_info *hi;
size_t len = strlen(rr->u.srv->target);
hi = calloc(1, sizeof(*hi) + len);
if(hi == NULL) {
dns_free_data(r);
while(--num_srv >= 0)
free((*res)[num_srv]);
free(*res);
*res = NULL;
return ENOMEM;
}
(*res)[num_srv++] = hi;
hi->proto = proto_num;
hi->def_port = def_port;
if (port != 0)
hi->port = port;
else
hi->port = rr->u.srv->port;
strlcpy(hi->hostname, rr->u.srv->target, len + 1);
}
*count = num_srv;
dns_free_data(r);
return 0;
}
struct krb5_krbhst_data {
char *realm;
unsigned int flags;
int def_port;
int port; /* hardwired port number if != 0 */
#define KD_CONFIG 1
#define KD_SRV_UDP 2
#define KD_SRV_TCP 4
#define KD_SRV_HTTP 8
#define KD_FALLBACK 16
#define KD_CONFIG_EXISTS 32
#define KD_LARGE_MSG 64
#define KD_PLUGIN 128
krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *,
krb5_krbhst_info**);
unsigned int fallback_count;
struct krb5_krbhst_info *hosts, **index, **end;
};
static krb5_boolean
krbhst_empty(const struct krb5_krbhst_data *kd)
{
return kd->index == &kd->hosts;
}
/*
* Return the default protocol for the `kd' (either TCP or UDP)
*/
static int
krbhst_get_default_proto(struct krb5_krbhst_data *kd)
{
if (kd->flags & KD_LARGE_MSG)
return KRB5_KRBHST_TCP;
return KRB5_KRBHST_UDP;
}
/*
* parse `spec' into a krb5_krbhst_info, defaulting the port to `def_port'
* and forcing it to `port' if port != 0
*/
static struct krb5_krbhst_info*
parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd,
const char *spec, int def_port, int port)
{
const char *p = spec;
struct krb5_krbhst_info *hi;
hi = calloc(1, sizeof(*hi) + strlen(spec));
if(hi == NULL)
return NULL;
hi->proto = krbhst_get_default_proto(kd);
if(strncmp(p, "http://", 7) == 0){
hi->proto = KRB5_KRBHST_HTTP;
p += 7;
} else if(strncmp(p, "http/", 5) == 0) {
hi->proto = KRB5_KRBHST_HTTP;
p += 5;
def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80));
}else if(strncmp(p, "tcp/", 4) == 0){
hi->proto = KRB5_KRBHST_TCP;
p += 4;
} else if(strncmp(p, "udp/", 4) == 0) {
p += 4;
}
if(strsep_copy(&p, ":", hi->hostname, strlen(spec) + 1) < 0) {
free(hi);
return NULL;
}
/* get rid of trailing /, and convert to lower case */
hi->hostname[strcspn(hi->hostname, "/")] = '\0';
strlwr(hi->hostname);
hi->port = hi->def_port = def_port;
if(p != NULL) {
char *end;
hi->port = strtol(p, &end, 0);
if(end == p) {
free(hi);
return NULL;
}
}
if (port)
hi->port = port;
return hi;
}
void
_krb5_free_krbhst_info(krb5_krbhst_info *hi)
{
if (hi->ai != NULL)
freeaddrinfo(hi->ai);
free(hi);
}
krb5_error_code
_krb5_krbhost_info_move(krb5_context context,
krb5_krbhst_info *from,
krb5_krbhst_info **to)
{
size_t hostnamelen = strlen(from->hostname);
/* trailing NUL is included in structure */
*to = calloc(1, sizeof(**to) + hostnamelen);
if(*to == NULL) {
krb5_set_error_string(context, "malloc - out of memory");
return ENOMEM;
}
(*to)->proto = from->proto;
(*to)->port = from->port;
(*to)->def_port = from->def_port;
(*to)->ai = from->ai;
from->ai = NULL;
(*to)->next = NULL;
memcpy((*to)->hostname, from->hostname, hostnamelen + 1);
return 0;
}
static void
append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host)
{
struct krb5_krbhst_info *h;
for(h = kd->hosts; h; h = h->next)
if(h->proto == host->proto &&
h->port == host->port &&
strcmp(h->hostname, host->hostname) == 0) {
_krb5_free_krbhst_info(host);
return;
}
*kd->end = host;
kd->end = &host->next;
}
static krb5_error_code
append_host_string(krb5_context context, struct krb5_krbhst_data *kd,
const char *host, int def_port, int port)
{
struct krb5_krbhst_info *hi;
hi = parse_hostspec(context, kd, host, def_port, port);
if(hi == NULL)
return ENOMEM;
append_host_hostinfo(kd, hi);
return 0;
}
/*
* return a readable representation of `host' in `hostname, hostlen'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_krbhst_format_string(krb5_context context, const krb5_krbhst_info *host,
char *hostname, size_t hostlen)
{
const char *proto = "";
char portstr[7] = "";
if(host->proto == KRB5_KRBHST_TCP)
proto = "tcp/";
else if(host->proto == KRB5_KRBHST_HTTP)
proto = "http://";
if(host->port != host->def_port)
snprintf(portstr, sizeof(portstr), ":%d", host->port);
snprintf(hostname, hostlen, "%s%s%s", proto, host->hostname, portstr);
return 0;
}
/*
* create a getaddrinfo `hints' based on `proto'
*/
static void
make_hints(struct addrinfo *hints, int proto)
{
memset(hints, 0, sizeof(*hints));
hints->ai_family = AF_UNSPEC;
switch(proto) {
case KRB5_KRBHST_UDP :
hints->ai_socktype = SOCK_DGRAM;
break;
case KRB5_KRBHST_HTTP :
case KRB5_KRBHST_TCP :
hints->ai_socktype = SOCK_STREAM;
break;
}
}
/*
* return an `struct addrinfo *' in `ai' corresponding to the information
* in `host'. free:ing is handled by krb5_krbhst_free.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host,
struct addrinfo **ai)
{
struct addrinfo hints;
char portstr[NI_MAXSERV];
int ret;
if (host->ai == NULL) {
make_hints(&hints, host->proto);
snprintf (portstr, sizeof(portstr), "%d", host->port);
ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai);
if (ret)
return krb5_eai_to_heim_errno(ret, errno);
}
*ai = host->ai;
return 0;
}
static krb5_boolean
get_next(struct krb5_krbhst_data *kd, krb5_krbhst_info **host)
{
struct krb5_krbhst_info *hi = *kd->index;
if(hi != NULL) {
*host = hi;
kd->index = &(*kd->index)->next;
return TRUE;
}
return FALSE;
}
static void
srv_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
const char *proto, const char *service)
{
krb5_krbhst_info **res;
int count, i;
if (srv_find_realm(context, &res, &count, kd->realm, "SRV", proto, service,
kd->port))
return;
for(i = 0; i < count; i++)
append_host_hostinfo(kd, res[i]);
free(res);
}
/*
* read the configuration for `conf_string', defaulting to kd->def_port and
* forcing it to `kd->port' if kd->port != 0
*/
static void
config_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
const char *conf_string)
{
int i;
char **hostlist;
hostlist = krb5_config_get_strings(context, NULL,
"realms", kd->realm, conf_string, NULL);
if(hostlist == NULL)
return;
kd->flags |= KD_CONFIG_EXISTS;
for(i = 0; hostlist && hostlist[i] != NULL; i++)
append_host_string(context, kd, hostlist[i], kd->def_port, kd->port);
krb5_config_free_strings(hostlist);
}
/*
* as a fallback, look for `serv_string.kd->realm' (typically
* kerberos.REALM, kerberos-1.REALM, ...
* `port' is the default port for the service, and `proto' the
* protocol
*/
static krb5_error_code
fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
const char *serv_string, int port, int proto)
{
char *host;
int ret;
struct addrinfo *ai;
struct addrinfo hints;
char portstr[NI_MAXSERV];
/*
* Don't try forever in case the DNS server keep returning us
* entries (like wildcard entries or the .nu TLD)
*/
if(kd->fallback_count >= 5) {
kd->flags |= KD_FALLBACK;
return 0;
}
if(kd->fallback_count == 0)
asprintf(&host, "%s.%s.", serv_string, kd->realm);
else
asprintf(&host, "%s-%d.%s.",
serv_string, kd->fallback_count, kd->realm);
if (host == NULL)
return ENOMEM;
make_hints(&hints, proto);
snprintf(portstr, sizeof(portstr), "%d", port);
ret = getaddrinfo(host, portstr, &hints, &ai);
if (ret) {
/* no more hosts, so we're done here */
free(host);
kd->flags |= KD_FALLBACK;
} else {
struct krb5_krbhst_info *hi;
size_t hostlen = strlen(host);
hi = calloc(1, sizeof(*hi) + hostlen);
if(hi == NULL) {
free(host);
return ENOMEM;
}
hi->proto = proto;
hi->port = hi->def_port = port;
hi->ai = ai;
memmove(hi->hostname, host, hostlen);
hi->hostname[hostlen] = '\0';
free(host);
append_host_hostinfo(kd, hi);
kd->fallback_count++;
}
return 0;
}
/*
* Fetch hosts from plugin
*/
static krb5_error_code
add_locate(void *ctx, int type, struct sockaddr *addr)
{
struct krb5_krbhst_info *hi;
struct krb5_krbhst_data *kd = ctx;
char host[NI_MAXHOST], port[NI_MAXSERV];
struct addrinfo hints, *ai;
socklen_t socklen;
size_t hostlen;
int ret;
socklen = socket_sockaddr_size(addr);
ret = getnameinfo(addr, socklen, host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST|NI_NUMERICSERV);
if (ret != 0)
return 0;
memset(&hints, 0, sizeof(hints));
ret = getaddrinfo(host, port, &hints, &ai);
if (ret)
return 0;
hostlen = strlen(host);
hi = calloc(1, sizeof(*hi) + hostlen);
if(hi == NULL) {
return ENOMEM;
}
hi->proto = krbhst_get_default_proto(kd);
hi->port = hi->def_port = socket_get_port(addr);
hi->ai = ai;
memmove(hi->hostname, host, hostlen);
hi->hostname[hostlen] = '\0';
append_host_hostinfo(kd, hi);
return 0;
}
static void
plugin_get_hosts(krb5_context context,
struct krb5_krbhst_data *kd,
enum locate_service_type type)
{
struct krb5_plugin *list, *e;
krb5_error_code ret;
ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list);
if(ret != 0 || list == NULL)
return;
kd->flags |= KD_CONFIG_EXISTS;
for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) {
krb5plugin_service_locate_ftable *service;
void *ctx;
service = _krb5_plugin_get_symbol(e);
if (service->minor_version != 0)
continue;
(*service->init)(context, &ctx);
ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd);
(*service->fini)(ctx);
if (ret) {
krb5_set_error_string(context, "Plugin failed to lookup");
break;
}
}
_krb5_plugin_free(list);
}
/*
*
*/
static krb5_error_code
kdc_get_next(krb5_context context,
struct krb5_krbhst_data *kd,
krb5_krbhst_info **host)
{
krb5_error_code ret;
if ((kd->flags & KD_PLUGIN) == 0) {
plugin_get_hosts(context, kd, locate_service_kdc);
kd->flags |= KD_PLUGIN;
if(get_next(kd, host))
return 0;
}
if((kd->flags & KD_CONFIG) == 0) {
config_get_hosts(context, kd, "kdc");
kd->flags |= KD_CONFIG;
if(get_next(kd, host))
return 0;
}
if (kd->flags & KD_CONFIG_EXISTS)
return KRB5_KDC_UNREACH; /* XXX */
if(context->srv_lookup) {
if((kd->flags & KD_SRV_UDP) == 0 && (kd->flags & KD_LARGE_MSG) == 0) {
srv_get_hosts(context, kd, "udp", "kerberos");
kd->flags |= KD_SRV_UDP;
if(get_next(kd, host))
return 0;
}
if((kd->flags & KD_SRV_TCP) == 0) {
srv_get_hosts(context, kd, "tcp", "kerberos");
kd->flags |= KD_SRV_TCP;
if(get_next(kd, host))
return 0;
}
if((kd->flags & KD_SRV_HTTP) == 0) {
srv_get_hosts(context, kd, "http", "kerberos");
kd->flags |= KD_SRV_HTTP;
if(get_next(kd, host))
return 0;
}
}
while((kd->flags & KD_FALLBACK) == 0) {
ret = fallback_get_hosts(context, kd, "kerberos",
kd->def_port,
krbhst_get_default_proto(kd));
if(ret)
return ret;
if(get_next(kd, host))
return 0;
}
return KRB5_KDC_UNREACH; /* XXX */
}
static krb5_error_code
admin_get_next(krb5_context context,
struct krb5_krbhst_data *kd,
krb5_krbhst_info **host)
{
krb5_error_code ret;
if((kd->flags & KD_CONFIG) == 0) {
config_get_hosts(context, kd, "admin_server");
kd->flags |= KD_CONFIG;
if(get_next(kd, host))
return 0;
}
if (kd->flags & KD_CONFIG_EXISTS)
return KRB5_KDC_UNREACH; /* XXX */
if(context->srv_lookup) {
if((kd->flags & KD_SRV_TCP) == 0) {
srv_get_hosts(context, kd, "tcp", "kerberos-adm");
kd->flags |= KD_SRV_TCP;
if(get_next(kd, host))
return 0;
}
}
if (krbhst_empty(kd)
&& (kd->flags & KD_FALLBACK) == 0) {
ret = fallback_get_hosts(context, kd, "kerberos",
kd->def_port,
krbhst_get_default_proto(kd));
if(ret)
return ret;
kd->flags |= KD_FALLBACK;
if(get_next(kd, host))
return 0;
}
return KRB5_KDC_UNREACH; /* XXX */
}
static krb5_error_code
kpasswd_get_next(krb5_context context,
struct krb5_krbhst_data *kd,
krb5_krbhst_info **host)
{
krb5_error_code ret;
if((kd->flags & KD_CONFIG) == 0) {
config_get_hosts(context, kd, "kpasswd_server");
kd->flags |= KD_CONFIG;
if(get_next(kd, host))
return 0;
}
if (kd->flags & KD_CONFIG_EXISTS)
return KRB5_KDC_UNREACH; /* XXX */
if(context->srv_lookup) {
if((kd->flags & KD_SRV_UDP) == 0) {
srv_get_hosts(context, kd, "udp", "kpasswd");
kd->flags |= KD_SRV_UDP;
if(get_next(kd, host))
return 0;
}
if((kd->flags & KD_SRV_TCP) == 0) {
srv_get_hosts(context, kd, "tcp", "kpasswd");
kd->flags |= KD_SRV_TCP;
if(get_next(kd, host))
return 0;
}
}
/* no matches -> try admin */
if (krbhst_empty(kd)) {
kd->flags = 0;
kd->port = kd->def_port;
kd->get_next = admin_get_next;
ret = (*kd->get_next)(context, kd, host);
if (ret == 0)
(*host)->proto = krbhst_get_default_proto(kd);
return ret;
}
return KRB5_KDC_UNREACH; /* XXX */
}
static krb5_error_code
krb524_get_next(krb5_context context,
struct krb5_krbhst_data *kd,
krb5_krbhst_info **host)
{
if((kd->flags & KD_CONFIG) == 0) {
config_get_hosts(context, kd, "krb524_server");
if(get_next(kd, host))
return 0;
kd->flags |= KD_CONFIG;
}
if (kd->flags & KD_CONFIG_EXISTS)
return KRB5_KDC_UNREACH; /* XXX */
if(context->srv_lookup) {
if((kd->flags & KD_SRV_UDP) == 0) {
srv_get_hosts(context, kd, "udp", "krb524");
kd->flags |= KD_SRV_UDP;
if(get_next(kd, host))
return 0;
}
if((kd->flags & KD_SRV_TCP) == 0) {
srv_get_hosts(context, kd, "tcp", "krb524");
kd->flags |= KD_SRV_TCP;
if(get_next(kd, host))
return 0;
}
}
/* no matches -> try kdc */
if (krbhst_empty(kd)) {
kd->flags = 0;
kd->port = kd->def_port;
kd->get_next = kdc_get_next;
return (*kd->get_next)(context, kd, host);
}
return KRB5_KDC_UNREACH; /* XXX */
}
static struct krb5_krbhst_data*
common_init(krb5_context context,
const char *realm,
int flags)
{
struct krb5_krbhst_data *kd;
if((kd = calloc(1, sizeof(*kd))) == NULL)
return NULL;
if((kd->realm = strdup(realm)) == NULL) {
free(kd);
return NULL;
}
/* For 'realms' without a . do not even think of going to DNS */
if (!strchr(realm, '.'))
kd->flags |= KD_CONFIG_EXISTS;
if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG)
kd->flags |= KD_LARGE_MSG;
kd->end = kd->index = &kd->hosts;
return kd;
}
/*
* initialize `handle' to look for hosts of type `type' in realm `realm'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_krbhst_init(krb5_context context,
const char *realm,
unsigned int type,
krb5_krbhst_handle *handle)
{
return krb5_krbhst_init_flags(context, realm, type, 0, handle);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_krbhst_init_flags(krb5_context context,
const char *realm,
unsigned int type,
int flags,
krb5_krbhst_handle *handle)
{
struct krb5_krbhst_data *kd;
krb5_error_code (*next)(krb5_context, struct krb5_krbhst_data *,
krb5_krbhst_info **);
int def_port;
switch(type) {
case KRB5_KRBHST_KDC:
next = kdc_get_next;
def_port = ntohs(krb5_getportbyname (context, "kerberos", "udp", 88));
break;
case KRB5_KRBHST_ADMIN:
next = admin_get_next;
def_port = ntohs(krb5_getportbyname (context, "kerberos-adm",
"tcp", 749));
break;
case KRB5_KRBHST_CHANGEPW:
next = kpasswd_get_next;
def_port = ntohs(krb5_getportbyname (context, "kpasswd", "udp",
KPASSWD_PORT));
break;
case KRB5_KRBHST_KRB524:
next = krb524_get_next;
def_port = ntohs(krb5_getportbyname (context, "krb524", "udp", 4444));
break;
default:
krb5_set_error_string(context, "unknown krbhst type (%u)", type);
return ENOTTY;
}
if((kd = common_init(context, realm, flags)) == NULL)
return ENOMEM;
kd->get_next = next;
kd->def_port = def_port;
*handle = kd;
return 0;
}
/*
* return the next host information from `handle' in `host'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_krbhst_next(krb5_context context,
krb5_krbhst_handle handle,
krb5_krbhst_info **host)
{
if(get_next(handle, host))
return 0;
return (*handle->get_next)(context, handle, host);
}
/*
* return the next host information from `handle' as a host name
* in `hostname' (or length `hostlen)
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_krbhst_next_as_string(krb5_context context,
krb5_krbhst_handle handle,
char *hostname,
size_t hostlen)
{
krb5_error_code ret;
krb5_krbhst_info *host;
ret = krb5_krbhst_next(context, handle, &host);
if(ret)
return ret;
return krb5_krbhst_format_string(context, host, hostname, hostlen);
}
void KRB5_LIB_FUNCTION
krb5_krbhst_reset(krb5_context context, krb5_krbhst_handle handle)
{
handle->index = &handle->hosts;
}
void KRB5_LIB_FUNCTION
krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle)
{
krb5_krbhst_info *h, *next;
if (handle == NULL)
return;
for (h = handle->hosts; h != NULL; h = next) {
next = h->next;
_krb5_free_krbhst_info(h);
}
free(handle->realm);
free(handle);
}
/* backwards compatibility ahead */
static krb5_error_code
gethostlist(krb5_context context, const char *realm,
unsigned int type, char ***hostlist)
{
krb5_error_code ret;
int nhost = 0;
krb5_krbhst_handle handle;
char host[MAXHOSTNAMELEN];
krb5_krbhst_info *hostinfo;
ret = krb5_krbhst_init(context, realm, type, &handle);
if (ret)
return ret;
while(krb5_krbhst_next(context, handle, &hostinfo) == 0)
nhost++;
if(nhost == 0)
return KRB5_KDC_UNREACH;
*hostlist = calloc(nhost + 1, sizeof(**hostlist));
if(*hostlist == NULL) {
krb5_krbhst_free(context, handle);
return ENOMEM;
}
krb5_krbhst_reset(context, handle);
nhost = 0;
while(krb5_krbhst_next_as_string(context, handle,
host, sizeof(host)) == 0) {
if(((*hostlist)[nhost++] = strdup(host)) == NULL) {
krb5_free_krbhst(context, *hostlist);
krb5_krbhst_free(context, handle);
return ENOMEM;
}
}
(*hostlist)[nhost++] = NULL;
krb5_krbhst_free(context, handle);
return 0;
}
/*
* return an malloced list of kadmin-hosts for `realm' in `hostlist'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_krb_admin_hst (krb5_context context,
const krb5_realm *realm,
char ***hostlist)
{
return gethostlist(context, *realm, KRB5_KRBHST_ADMIN, hostlist);
}
/*
* return an malloced list of changepw-hosts for `realm' in `hostlist'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_krb_changepw_hst (krb5_context context,
const krb5_realm *realm,
char ***hostlist)
{
return gethostlist(context, *realm, KRB5_KRBHST_CHANGEPW, hostlist);
}
/*
* return an malloced list of 524-hosts for `realm' in `hostlist'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_krb524hst (krb5_context context,
const krb5_realm *realm,
char ***hostlist)
{
return gethostlist(context, *realm, KRB5_KRBHST_KRB524, hostlist);
}
/*
* return an malloced list of KDC's for `realm' in `hostlist'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_krbhst (krb5_context context,
const krb5_realm *realm,
char ***hostlist)
{
return gethostlist(context, *realm, KRB5_KRBHST_KDC, hostlist);
}
/*
* free all the memory allocated in `hostlist'
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_krbhst (krb5_context context,
char **hostlist)
{
char **p;
for (p = hostlist; *p; ++p)
free (*p);
free (hostlist);
return 0;
}
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2006 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $Id: locate_plugin.h,v 1.1 2006/11/12 19:00:03 lha Exp $ */
#ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H
#define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1
#include <krb5.h>
enum locate_service_type {
locate_service_kdc = 1,
locate_service_master_kdc,
locate_service_kadmin,
locate_service_krb524,
locate_service_kpasswd
};
typedef krb5_error_code
(*krb5plugin_service_locate_lookup) (void *, enum locate_service_type,
const char *, int, int,
int (*)(void *,int,struct sockaddr *),
void *);
typedef struct krb5plugin_service_locate_ftable {
int minor_version;
krb5_error_code (*init)(krb5_context, void **);
void (*fini)(void *);
krb5plugin_service_locate_lookup lookup;
} krb5plugin_service_locate_ftable;
#endif /* HEIMDAL_KRB5_LOCATE_PLUGIN_H */
+471
View File
@@ -0,0 +1,471 @@
/*
* Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: log.c,v 1.39 2006/04/24 15:09:27 lha Exp $");
struct facility {
int min;
int max;
krb5_log_log_func_t log_func;
krb5_log_close_func_t close_func;
void *data;
};
static struct facility*
log_realloc(krb5_log_facility *f)
{
struct facility *fp;
fp = realloc(f->val, (f->len + 1) * sizeof(*f->val));
if(fp == NULL)
return NULL;
f->len++;
f->val = fp;
fp += f->len - 1;
return fp;
}
struct s2i {
const char *s;
int val;
};
#define L(X) { #X, LOG_ ## X }
static struct s2i syslogvals[] = {
L(EMERG),
L(ALERT),
L(CRIT),
L(ERR),
L(WARNING),
L(NOTICE),
L(INFO),
L(DEBUG),
L(AUTH),
#ifdef LOG_AUTHPRIV
L(AUTHPRIV),
#endif
#ifdef LOG_CRON
L(CRON),
#endif
L(DAEMON),
#ifdef LOG_FTP
L(FTP),
#endif
L(KERN),
L(LPR),
L(MAIL),
#ifdef LOG_NEWS
L(NEWS),
#endif
L(SYSLOG),
L(USER),
#ifdef LOG_UUCP
L(UUCP),
#endif
L(LOCAL0),
L(LOCAL1),
L(LOCAL2),
L(LOCAL3),
L(LOCAL4),
L(LOCAL5),
L(LOCAL6),
L(LOCAL7),
{ NULL, -1 }
};
static int
find_value(const char *s, struct s2i *table)
{
while(table->s && strcasecmp(table->s, s))
table++;
return table->val;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_initlog(krb5_context context,
const char *program,
krb5_log_facility **fac)
{
krb5_log_facility *f = calloc(1, sizeof(*f));
if(f == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
f->program = strdup(program);
if(f->program == NULL){
free(f);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
*fac = f;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_addlog_func(krb5_context context,
krb5_log_facility *fac,
int min,
int max,
krb5_log_log_func_t log_func,
krb5_log_close_func_t close_func,
void *data)
{
struct facility *fp = log_realloc(fac);
if(fp == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
fp->min = min;
fp->max = max;
fp->log_func = log_func;
fp->close_func = close_func;
fp->data = data;
return 0;
}
struct _heimdal_syslog_data{
int priority;
};
static void
log_syslog(const char *timestr,
const char *msg,
void *data)
{
struct _heimdal_syslog_data *s = data;
syslog(s->priority, "%s", msg);
}
static void
close_syslog(void *data)
{
free(data);
closelog();
}
static krb5_error_code
open_syslog(krb5_context context,
krb5_log_facility *facility, int min, int max,
const char *sev, const char *fac)
{
struct _heimdal_syslog_data *sd = malloc(sizeof(*sd));
int i;
if(sd == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
i = find_value(sev, syslogvals);
if(i == -1)
i = LOG_ERR;
sd->priority = i;
i = find_value(fac, syslogvals);
if(i == -1)
i = LOG_AUTH;
sd->priority |= i;
roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i);
return krb5_addlog_func(context, facility, min, max,
log_syslog, close_syslog, sd);
}
struct file_data{
const char *filename;
const char *mode;
FILE *fd;
int keep_open;
};
static void
log_file(const char *timestr,
const char *msg,
void *data)
{
struct file_data *f = data;
if(f->keep_open == 0)
f->fd = fopen(f->filename, f->mode);
if(f->fd == NULL)
return;
fprintf(f->fd, "%s %s\n", timestr, msg);
if(f->keep_open == 0) {
fclose(f->fd);
f->fd = NULL;
}
}
static void
close_file(void *data)
{
struct file_data *f = data;
if(f->keep_open && f->filename)
fclose(f->fd);
free(data);
}
static krb5_error_code
open_file(krb5_context context, krb5_log_facility *fac, int min, int max,
const char *filename, const char *mode, FILE *f, int keep_open)
{
struct file_data *fd = malloc(sizeof(*fd));
if(fd == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
fd->filename = filename;
fd->mode = mode;
fd->fd = f;
fd->keep_open = keep_open;
return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
{
krb5_error_code ret = 0;
int min = 0, max = -1, n;
char c;
const char *p = orig;
n = sscanf(p, "%d%c%d/", &min, &c, &max);
if(n == 2){
if(c == '/') {
if(min < 0){
max = -min;
min = 0;
}else{
max = min;
}
}
}
if(n){
p = strchr(p, '/');
if(p == NULL) {
krb5_set_error_string (context, "failed to parse \"%s\"", orig);
return HEIM_ERR_LOG_PARSE;
}
p++;
}
if(strcmp(p, "STDERR") == 0){
ret = open_file(context, f, min, max, NULL, NULL, stderr, 1);
}else if(strcmp(p, "CONSOLE") == 0){
ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0);
}else if(strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')){
char *fn;
FILE *file = NULL;
int keep_open = 0;
fn = strdup(p + 5);
if(fn == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
if(p[4] == '='){
int i = open(fn, O_WRONLY | O_CREAT |
O_TRUNC | O_APPEND, 0666);
if(i < 0) {
ret = errno;
krb5_set_error_string (context, "open(%s): %s", fn,
strerror(ret));
free(fn);
return ret;
}
file = fdopen(i, "a");
if(file == NULL){
ret = errno;
close(i);
krb5_set_error_string (context, "fdopen(%s): %s", fn,
strerror(ret));
free(fn);
return ret;
}
keep_open = 1;
}
ret = open_file(context, f, min, max, fn, "a", file, keep_open);
}else if(strncmp(p, "DEVICE", 6) == 0 && (p[6] == ':' || p[6] == '=')){
ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0);
}else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){
char severity[128] = "";
char facility[128] = "";
p += 6;
if(*p != '\0')
p++;
if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1)
strsep_copy(&p, ":", facility, sizeof(facility));
if(*severity == '\0')
strlcpy(severity, "ERR", sizeof(severity));
if(*facility == '\0')
strlcpy(facility, "AUTH", sizeof(facility));
ret = open_syslog(context, f, min, max, severity, facility);
}else{
krb5_set_error_string (context, "unknown log type: %s", p);
ret = HEIM_ERR_LOG_PARSE; /* XXX */
}
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_openlog(krb5_context context,
const char *program,
krb5_log_facility **fac)
{
krb5_error_code ret;
char **p, **q;
ret = krb5_initlog(context, program, fac);
if(ret)
return ret;
p = krb5_config_get_strings(context, NULL, "logging", program, NULL);
if(p == NULL)
p = krb5_config_get_strings(context, NULL, "logging", "default", NULL);
if(p){
for(q = p; *q; q++)
ret = krb5_addlog_dest(context, *fac, *q);
krb5_config_free_strings(p);
}else
ret = krb5_addlog_dest(context, *fac, "SYSLOG");
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_closelog(krb5_context context,
krb5_log_facility *fac)
{
int i;
for(i = 0; i < fac->len; i++)
(*fac->val[i].close_func)(fac->val[i].data);
free(fac->val);
free(fac->program);
fac->val = NULL;
fac->len = 0;
fac->program = NULL;
free(fac);
return 0;
}
#undef __attribute__
#define __attribute__(X)
krb5_error_code KRB5_LIB_FUNCTION
krb5_vlog_msg(krb5_context context,
krb5_log_facility *fac,
char **reply,
int level,
const char *fmt,
va_list ap)
__attribute__((format (printf, 5, 0)))
{
char *msg = NULL;
const char *actual = NULL;
char buf[64];
time_t t = 0;
int i;
for(i = 0; fac && i < fac->len; i++)
if(fac->val[i].min <= level &&
(fac->val[i].max < 0 || fac->val[i].max >= level)) {
if(t == 0) {
t = time(NULL);
krb5_format_time(context, t, buf, sizeof(buf), TRUE);
}
if(actual == NULL) {
vasprintf(&msg, fmt, ap);
if(msg == NULL)
actual = fmt;
else
actual = msg;
}
(*fac->val[i].log_func)(buf, actual, fac->val[i].data);
}
if(reply == NULL)
free(msg);
else
*reply = msg;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_vlog(krb5_context context,
krb5_log_facility *fac,
int level,
const char *fmt,
va_list ap)
__attribute__((format (printf, 4, 0)))
{
return krb5_vlog_msg(context, fac, NULL, level, fmt, ap);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_log_msg(krb5_context context,
krb5_log_facility *fac,
int level,
char **reply,
const char *fmt,
...)
__attribute__((format (printf, 5, 6)))
{
va_list ap;
krb5_error_code ret;
va_start(ap, fmt);
ret = krb5_vlog_msg(context, fac, reply, level, fmt, ap);
va_end(ap);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_log(krb5_context context,
krb5_log_facility *fac,
int level,
const char *fmt,
...)
__attribute__((format (printf, 4, 5)))
{
va_list ap;
krb5_error_code ret;
va_start(ap, fmt);
ret = krb5_vlog(context, fac, level, fmt, ap);
va_end(ap);
return ret;
}
+426
View File
@@ -0,0 +1,426 @@
/*
* Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: mcache.c,v 1.20 2005/09/30 11:16:04 lha Exp $");
typedef struct krb5_mcache {
char *name;
unsigned int refcnt;
int dead;
krb5_principal primary_principal;
struct link {
krb5_creds cred;
struct link *next;
} *creds;
struct krb5_mcache *next;
} krb5_mcache;
static HEIMDAL_MUTEX mcc_mutex = HEIMDAL_MUTEX_INITIALIZER;
static struct krb5_mcache *mcc_head;
#define MCACHE(X) ((krb5_mcache *)(X)->data.data)
#define MISDEAD(X) ((X)->dead)
#define MCC_CURSOR(C) ((struct link*)(C))
static const char*
mcc_get_name(krb5_context context,
krb5_ccache id)
{
return MCACHE(id)->name;
}
static krb5_mcache *
mcc_alloc(const char *name)
{
krb5_mcache *m, *m_c;
ALLOC(m, 1);
if(m == NULL)
return NULL;
if(name == NULL)
asprintf(&m->name, "%p", m);
else
m->name = strdup(name);
if(m->name == NULL) {
free(m);
return NULL;
}
/* check for dups first */
HEIMDAL_MUTEX_lock(&mcc_mutex);
for (m_c = mcc_head; m_c != NULL; m_c = m_c->next)
if (strcmp(m->name, m_c->name) == 0)
break;
if (m_c) {
free(m->name);
free(m);
HEIMDAL_MUTEX_unlock(&mcc_mutex);
return NULL;
}
m->dead = 0;
m->refcnt = 1;
m->primary_principal = NULL;
m->creds = NULL;
m->next = mcc_head;
mcc_head = m;
HEIMDAL_MUTEX_unlock(&mcc_mutex);
return m;
}
static krb5_error_code
mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
{
krb5_mcache *m;
HEIMDAL_MUTEX_lock(&mcc_mutex);
for (m = mcc_head; m != NULL; m = m->next)
if (strcmp(m->name, res) == 0)
break;
HEIMDAL_MUTEX_unlock(&mcc_mutex);
if (m != NULL) {
m->refcnt++;
(*id)->data.data = m;
(*id)->data.length = sizeof(*m);
return 0;
}
m = mcc_alloc(res);
if (m == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
(*id)->data.data = m;
(*id)->data.length = sizeof(*m);
return 0;
}
static krb5_error_code
mcc_gen_new(krb5_context context, krb5_ccache *id)
{
krb5_mcache *m;
m = mcc_alloc(NULL);
if (m == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
(*id)->data.data = m;
(*id)->data.length = sizeof(*m);
return 0;
}
static krb5_error_code
mcc_initialize(krb5_context context,
krb5_ccache id,
krb5_principal primary_principal)
{
krb5_mcache *m = MCACHE(id);
m->dead = 0;
return krb5_copy_principal (context,
primary_principal,
&m->primary_principal);
}
static int
mcc_close_internal(krb5_mcache *m)
{
if (--m->refcnt != 0)
return 0;
if (MISDEAD(m)) {
free (m->name);
return 1;
}
return 0;
}
static krb5_error_code
mcc_close(krb5_context context,
krb5_ccache id)
{
if (mcc_close_internal(MCACHE(id)))
krb5_data_free(&id->data);
return 0;
}
static krb5_error_code
mcc_destroy(krb5_context context,
krb5_ccache id)
{
krb5_mcache **n, *m = MCACHE(id);
struct link *l;
if (m->refcnt == 0)
krb5_abortx(context, "mcc_destroy: refcnt already 0");
if (!MISDEAD(m)) {
/* if this is an active mcache, remove it from the linked
list, and free all data */
HEIMDAL_MUTEX_lock(&mcc_mutex);
for(n = &mcc_head; n && *n; n = &(*n)->next) {
if(m == *n) {
*n = m->next;
break;
}
}
HEIMDAL_MUTEX_unlock(&mcc_mutex);
if (m->primary_principal != NULL) {
krb5_free_principal (context, m->primary_principal);
m->primary_principal = NULL;
}
m->dead = 1;
l = m->creds;
while (l != NULL) {
struct link *old;
krb5_free_cred_contents (context, &l->cred);
old = l;
l = l->next;
free (old);
}
m->creds = NULL;
}
return 0;
}
static krb5_error_code
mcc_store_cred(krb5_context context,
krb5_ccache id,
krb5_creds *creds)
{
krb5_mcache *m = MCACHE(id);
krb5_error_code ret;
struct link *l;
if (MISDEAD(m))
return ENOENT;
l = malloc (sizeof(*l));
if (l == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return KRB5_CC_NOMEM;
}
l->next = m->creds;
m->creds = l;
memset (&l->cred, 0, sizeof(l->cred));
ret = krb5_copy_creds_contents (context, creds, &l->cred);
if (ret) {
m->creds = l->next;
free (l);
return ret;
}
return 0;
}
static krb5_error_code
mcc_get_principal(krb5_context context,
krb5_ccache id,
krb5_principal *principal)
{
krb5_mcache *m = MCACHE(id);
if (MISDEAD(m) || m->primary_principal == NULL)
return ENOENT;
return krb5_copy_principal (context,
m->primary_principal,
principal);
}
static krb5_error_code
mcc_get_first (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor)
{
krb5_mcache *m = MCACHE(id);
if (MISDEAD(m))
return ENOENT;
*cursor = m->creds;
return 0;
}
static krb5_error_code
mcc_get_next (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor,
krb5_creds *creds)
{
krb5_mcache *m = MCACHE(id);
struct link *l;
if (MISDEAD(m))
return ENOENT;
l = *cursor;
if (l != NULL) {
*cursor = l->next;
return krb5_copy_creds_contents (context,
&l->cred,
creds);
} else
return KRB5_CC_END;
}
static krb5_error_code
mcc_end_get (krb5_context context,
krb5_ccache id,
krb5_cc_cursor *cursor)
{
return 0;
}
static krb5_error_code
mcc_remove_cred(krb5_context context,
krb5_ccache id,
krb5_flags which,
krb5_creds *mcreds)
{
krb5_mcache *m = MCACHE(id);
struct link **q, *p;
for(q = &m->creds, p = *q; p; p = *q) {
if(krb5_compare_creds(context, which, mcreds, &p->cred)) {
*q = p->next;
krb5_free_cred_contents(context, &p->cred);
free(p);
} else
q = &p->next;
}
return 0;
}
static krb5_error_code
mcc_set_flags(krb5_context context,
krb5_ccache id,
krb5_flags flags)
{
return 0; /* XXX */
}
struct mcache_iter {
krb5_mcache *cache;
};
static krb5_error_code
mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
{
struct mcache_iter *iter;
iter = calloc(1, sizeof(*iter));
if (iter == NULL) {
krb5_set_error_string(context, "malloc - out of memory");
return ENOMEM;
}
HEIMDAL_MUTEX_lock(&mcc_mutex);
iter->cache = mcc_head;
if (iter->cache)
iter->cache->refcnt++;
HEIMDAL_MUTEX_unlock(&mcc_mutex);
*cursor = iter;
return 0;
}
static krb5_error_code
mcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
{
struct mcache_iter *iter = cursor;
krb5_error_code ret;
krb5_mcache *m;
if (iter->cache == NULL)
return KRB5_CC_END;
HEIMDAL_MUTEX_lock(&mcc_mutex);
m = iter->cache;
if (m->next)
m->next->refcnt++;
iter->cache = m->next;
HEIMDAL_MUTEX_unlock(&mcc_mutex);
ret = _krb5_cc_allocate(context, &krb5_mcc_ops, id);
if (ret)
return ret;
(*id)->data.data = m;
(*id)->data.length = sizeof(*m);
return 0;
}
static krb5_error_code
mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
{
struct mcache_iter *iter = cursor;
if (iter->cache)
mcc_close_internal(iter->cache);
iter->cache = NULL;
free(iter);
return 0;
}
const krb5_cc_ops krb5_mcc_ops = {
"MEMORY",
mcc_get_name,
mcc_resolve,
mcc_gen_new,
mcc_initialize,
mcc_destroy,
mcc_close,
mcc_store_cred,
NULL, /* mcc_retrieve */
mcc_get_principal,
mcc_get_first,
mcc_get_next,
mcc_end_get,
mcc_remove_cred,
mcc_set_flags,
NULL,
mcc_get_cache_first,
mcc_get_cache_next,
mcc_end_cache_get
};
+85
View File
@@ -0,0 +1,85 @@
/*
* Copyright (c) 1997 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: misc.c,v 1.6 2006/06/06 14:57:47 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
_krb5_s4u2self_to_checksumdata(krb5_context context,
const PA_S4U2Self *self,
krb5_data *data)
{
krb5_error_code ret;
krb5_ssize_t ssize;
krb5_storage *sp;
size_t size;
int i;
sp = krb5_storage_emem();
if (sp == NULL) {
krb5_clear_error_string(context);
return ENOMEM;
}
ret = krb5_store_int32(sp, self->name.name_type);
if (ret)
goto out;
for (i = 0; i < self->name.name_string.len; i++) {
size = strlen(self->name.name_string.val[i]);
ssize = krb5_storage_write(sp, self->name.name_string.val[i], size);
if (ssize != size) {
ret = ENOMEM;
goto out;
}
}
size = strlen(self->realm);
ssize = krb5_storage_write(sp, self->realm, size);
if (ssize != size) {
ret = ENOMEM;
goto out;
}
size = strlen(self->auth);
ssize = krb5_storage_write(sp, self->auth, size);
if (ssize != size) {
ret = ENOMEM;
goto out;
}
ret = krb5_storage_to_data(sp, data);
krb5_storage_free(sp);
return ret;
out:
krb5_clear_error_string(context);
return ret;
}
+335
View File
@@ -0,0 +1,335 @@
/*
* Copyright (c) 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: mit_glue.c,v 1.9 2006/11/09 21:24:16 lha Exp $");
/*
* Glue for MIT API
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_make_checksum(krb5_context context,
krb5_cksumtype cksumtype,
const krb5_keyblock *key,
krb5_keyusage usage,
const krb5_data *input,
krb5_checksum *cksum)
{
krb5_error_code ret;
krb5_crypto crypto;
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret)
return ret;
ret = krb5_create_checksum(context, crypto, usage, cksumtype,
input->data, input->length, cksum);
krb5_crypto_destroy(context, crypto);
return ret ;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key,
krb5_keyusage usage, const krb5_data *data,
const krb5_checksum *cksum, krb5_boolean *valid)
{
krb5_error_code ret;
krb5_checksum data_cksum;
*valid = 0;
ret = krb5_c_make_checksum(context, cksum->cksumtype,
key, usage, data, &data_cksum);
if (ret)
return ret;
if (data_cksum.cksumtype == cksum->cksumtype
&& data_cksum.checksum.length == cksum->checksum.length
&& memcmp(data_cksum.checksum.data, cksum->checksum.data, cksum->checksum.length) == 0)
*valid = 1;
krb5_free_checksum_contents(context, &data_cksum);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_get_checksum(krb5_context context, const krb5_checksum *cksum,
krb5_cksumtype *type, krb5_data **data)
{
krb5_error_code ret;
if (type)
*type = cksum->cksumtype;
if (data) {
*data = malloc(sizeof(**data));
if (*data == NULL)
return ENOMEM;
ret = der_copy_octet_string(&cksum->checksum, *data);
if (ret) {
free(*data);
*data = NULL;
return ret;
}
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_set_checksum(krb5_context context, krb5_checksum *cksum,
krb5_cksumtype type, const krb5_data *data)
{
cksum->cksumtype = type;
return der_copy_octet_string(data, &cksum->checksum);
}
void KRB5_LIB_FUNCTION
krb5_free_checksum (krb5_context context, krb5_checksum *cksum)
{
krb5_checksum_free(context, cksum);
free(cksum);
}
void KRB5_LIB_FUNCTION
krb5_free_checksum_contents(krb5_context context, krb5_checksum *cksum)
{
krb5_checksum_free(context, cksum);
memset(cksum, 0, sizeof(*cksum));
}
void KRB5_LIB_FUNCTION
krb5_checksum_free(krb5_context context, krb5_checksum *cksum)
{
free_Checksum(cksum);
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_c_valid_enctype (krb5_enctype etype)
{
return krb5_enctype_valid(NULL, etype);
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_c_valid_cksumtype(krb5_cksumtype ctype)
{
return krb5_cksumtype_valid(NULL, ctype);
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype)
{
return krb5_checksum_is_collision_proof(NULL, ctype);
}
krb5_boolean KRB5_LIB_FUNCTION
krb5_c_is_keyed_cksum(krb5_cksumtype ctype)
{
return krb5_checksum_is_keyed(NULL, ctype);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_checksum (krb5_context context,
const krb5_checksum *old,
krb5_checksum **new)
{
*new = malloc(sizeof(**new));
if (*new == NULL)
return ENOMEM;
return copy_Checksum(old, *new);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_checksum_length (krb5_context context, krb5_cksumtype cksumtype,
size_t *length)
{
return krb5_checksumsize(context, cksumtype, length);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_block_size(krb5_context context,
krb5_enctype enctype,
size_t *blocksize)
{
krb5_error_code ret;
krb5_crypto crypto;
krb5_keyblock key;
ret = krb5_generate_random_keyblock(context, enctype, &key);
if (ret)
return ret;
ret = krb5_crypto_init(context, &key, 0, &crypto);
krb5_free_keyblock_contents(context, &key);
if (ret)
return ret;
ret = krb5_crypto_getblocksize(context, crypto, blocksize);
krb5_crypto_destroy(context, crypto);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_decrypt(krb5_context context,
const krb5_keyblock key,
krb5_keyusage usage,
const krb5_data *ivec,
krb5_enc_data *input,
krb5_data *output)
{
krb5_error_code ret;
krb5_crypto crypto;
ret = krb5_crypto_init(context, &key, input->enctype, &crypto);
if (ret)
return ret;
if (ivec) {
size_t blocksize;
ret = krb5_crypto_getblocksize(context, crypto, &blocksize);
if (ret) {
krb5_crypto_destroy(context, crypto);
return ret;
}
if (blocksize > ivec->length) {
krb5_crypto_destroy(context, crypto);
return KRB5_BAD_MSIZE;
}
}
ret = krb5_decrypt_ivec(context, crypto, usage,
input->ciphertext.data, input->ciphertext.length,
output,
ivec ? ivec->data : NULL);
krb5_crypto_destroy(context, crypto);
return ret ;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_encrypt(krb5_context context,
const krb5_keyblock *key,
krb5_keyusage usage,
const krb5_data *ivec,
const krb5_data *input,
krb5_enc_data *output)
{
krb5_error_code ret;
krb5_crypto crypto;
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret)
return ret;
if (ivec) {
size_t blocksize;
ret = krb5_crypto_getblocksize(context, crypto, &blocksize);
if (ret) {
krb5_crypto_destroy(context, crypto);
return ret;
}
if (blocksize > ivec->length) {
krb5_crypto_destroy(context, crypto);
return KRB5_BAD_MSIZE;
}
}
ret = krb5_encrypt_ivec(context, crypto, usage,
input->data, input->length,
&output->ciphertext,
ivec ? ivec->data : NULL);
output->kvno = 0;
krb5_crypto_getenctype(context, crypto, &output->enctype);
krb5_crypto_destroy(context, crypto);
return ret ;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_encrypt_length(krb5_context context,
krb5_enctype enctype,
size_t inputlen,
size_t *length)
{
krb5_error_code ret;
krb5_crypto crypto;
krb5_keyblock key;
ret = krb5_generate_random_keyblock(context, enctype, &key);
if (ret)
return ret;
ret = krb5_crypto_init(context, &key, 0, &crypto);
krb5_free_keyblock_contents(context, &key);
if (ret)
return ret;
*length = krb5_get_wrapped_length(context, crypto, inputlen);
krb5_crypto_destroy(context, crypto);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_enctype_compare(krb5_context context,
krb5_enctype e1,
krb5_enctype e2,
krb5_boolean *similar)
{
*similar = krb5_enctypes_compatible_keys(context, e1, e2);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_make_random_key(krb5_context context,
krb5_enctype enctype,
krb5_keyblock *random_key)
{
return krb5_generate_random_keyblock(context, enctype, random_key);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_c_keylength(krb5_context context,
krb5_enctype enctype,
size_t *len)
{
return krb5_enctype_keysize(context, enctype, len);
}
+92
View File
@@ -0,0 +1,92 @@
/*
* Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: mk_error.c,v 1.22 2005/06/16 21:16:40 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_error(krb5_context context,
krb5_error_code error_code,
const char *e_text,
const krb5_data *e_data,
const krb5_principal client,
const krb5_principal server,
time_t *client_time,
int *client_usec,
krb5_data *reply)
{
KRB_ERROR msg;
krb5_timestamp sec;
int32_t usec;
size_t len;
krb5_error_code ret = 0;
krb5_us_timeofday (context, &sec, &usec);
memset(&msg, 0, sizeof(msg));
msg.pvno = 5;
msg.msg_type = krb_error;
msg.stime = sec;
msg.susec = usec;
msg.ctime = client_time;
msg.cusec = client_usec;
/* Make sure we only send `protocol' error codes */
if(error_code < KRB5KDC_ERR_NONE || error_code >= KRB5_ERR_RCSID) {
if(e_text == NULL)
e_text = krb5_get_err_text(context, error_code);
error_code = KRB5KRB_ERR_GENERIC;
}
msg.error_code = error_code - KRB5KDC_ERR_NONE;
if (e_text)
msg.e_text = rk_UNCONST(&e_text);
if (e_data)
msg.e_data = rk_UNCONST(e_data);
if(server){
msg.realm = server->realm;
msg.sname = server->name;
}else{
msg.realm = "<unspecified realm>";
}
if(client){
msg.crealm = &client->realm;
msg.cname = &client->name;
}
ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret);
if (ret)
return ret;
if(reply->length != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
return 0;
}
+155
View File
@@ -0,0 +1,155 @@
/*
* Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: mk_priv.c,v 1.35 2006/02/01 12:39:26 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_priv(krb5_context context,
krb5_auth_context auth_context,
const krb5_data *userdata,
krb5_data *outbuf,
krb5_replay_data *outdata)
{
krb5_error_code ret;
KRB_PRIV s;
EncKrbPrivPart part;
u_char *buf = NULL;
size_t buf_size;
size_t len;
krb5_crypto crypto;
krb5_keyblock *key;
krb5_replay_data rdata;
if ((auth_context->flags &
(KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
outdata == NULL)
return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
if (auth_context->local_subkey)
key = auth_context->local_subkey;
else if (auth_context->remote_subkey)
key = auth_context->remote_subkey;
else
key = auth_context->keyblock;
memset(&rdata, 0, sizeof(rdata));
part.user_data = *userdata;
krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec);
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
part.timestamp = &rdata.timestamp;
part.usec = &rdata.usec;
} else {
part.timestamp = NULL;
part.usec = NULL;
}
if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) {
outdata->timestamp = rdata.timestamp;
outdata->usec = rdata.usec;
}
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
rdata.seq = auth_context->local_seqnumber;
part.seq_number = &rdata.seq;
} else
part.seq_number = NULL;
if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
outdata->seq = auth_context->local_seqnumber;
part.s_address = auth_context->local_address;
part.r_address = auth_context->remote_address;
krb5_data_zero (&s.enc_part.cipher);
ASN1_MALLOC_ENCODE(EncKrbPrivPart, buf, buf_size, &part, &len, ret);
if (ret)
goto fail;
if (buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
s.pvno = 5;
s.msg_type = krb_priv;
s.enc_part.etype = key->keytype;
s.enc_part.kvno = NULL;
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret) {
free (buf);
return ret;
}
ret = krb5_encrypt (context,
crypto,
KRB5_KU_KRB_PRIV,
buf + buf_size - len,
len,
&s.enc_part.cipher);
krb5_crypto_destroy(context, crypto);
if (ret) {
free(buf);
return ret;
}
free(buf);
ASN1_MALLOC_ENCODE(KRB_PRIV, buf, buf_size, &s, &len, ret);
if (ret)
goto fail;
if (buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
krb5_data_free (&s.enc_part.cipher);
ret = krb5_data_copy(outbuf, buf + buf_size - len, len);
if (ret) {
krb5_set_error_string (context, "malloc: out of memory");
free(buf);
return ENOMEM;
}
free (buf);
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
auth_context->local_seqnumber =
(auth_context->local_seqnumber + 1) & 0xFFFFFFFF;
return 0;
fail:
free (buf);
krb5_data_free (&s.enc_part.cipher);
return ret;
}
+126
View File
@@ -0,0 +1,126 @@
/*
* Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: mk_rep.c,v 1.26 2004/05/25 21:33:51 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_rep(krb5_context context,
krb5_auth_context auth_context,
krb5_data *outbuf)
{
krb5_error_code ret;
AP_REP ap;
EncAPRepPart body;
u_char *buf = NULL;
size_t buf_size;
size_t len;
krb5_crypto crypto;
ap.pvno = 5;
ap.msg_type = krb_ap_rep;
memset (&body, 0, sizeof(body));
body.ctime = auth_context->authenticator->ctime;
body.cusec = auth_context->authenticator->cusec;
if (auth_context->flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) {
if (auth_context->local_subkey == NULL) {
ret = krb5_auth_con_generatelocalsubkey(context,
auth_context,
auth_context->keyblock);
if(ret) {
krb5_set_error_string (context,
"krb5_mk_rep: generating subkey");
free_EncAPRepPart(&body);
return ret;
}
}
ret = krb5_copy_keyblock(context, auth_context->local_subkey,
&body.subkey);
if (ret) {
krb5_set_error_string (context,
"krb5_copy_keyblock: out of memory");
free_EncAPRepPart(&body);
return ENOMEM;
}
} else
body.subkey = NULL;
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
if(auth_context->local_seqnumber == 0)
krb5_generate_seq_number (context,
auth_context->keyblock,
&auth_context->local_seqnumber);
ALLOC(body.seq_number, 1);
if (body.seq_number == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
free_EncAPRepPart(&body);
return ENOMEM;
}
*(body.seq_number) = auth_context->local_seqnumber;
} else
body.seq_number = NULL;
ap.enc_part.etype = auth_context->keyblock->keytype;
ap.enc_part.kvno = NULL;
ASN1_MALLOC_ENCODE(EncAPRepPart, buf, buf_size, &body, &len, ret);
free_EncAPRepPart (&body);
if(ret)
return ret;
if (buf_size != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
ret = krb5_crypto_init(context, auth_context->keyblock,
0 /* ap.enc_part.etype */, &crypto);
if (ret) {
free (buf);
return ret;
}
ret = krb5_encrypt (context,
crypto,
KRB5_KU_AP_REQ_ENC_PART,
buf + buf_size - len,
len,
&ap.enc_part.cipher);
krb5_crypto_destroy(context, crypto);
free(buf);
if (ret)
return ret;
ASN1_MALLOC_ENCODE(AP_REP, outbuf->data, outbuf->length, &ap, &len, ret);
if (ret == 0 && outbuf->length != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
free_AP_REP (&ap);
return ret;
}
+116
View File
@@ -0,0 +1,116 @@
/*
* Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: mk_req.c,v 1.26 2004/05/25 21:34:11 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_req_exact(krb5_context context,
krb5_auth_context *auth_context,
const krb5_flags ap_req_options,
const krb5_principal server,
krb5_data *in_data,
krb5_ccache ccache,
krb5_data *outbuf)
{
krb5_error_code ret;
krb5_creds this_cred, *cred;
memset(&this_cred, 0, sizeof(this_cred));
ret = krb5_cc_get_principal(context, ccache, &this_cred.client);
if(ret)
return ret;
ret = krb5_copy_principal (context, server, &this_cred.server);
if (ret) {
krb5_free_cred_contents (context, &this_cred);
return ret;
}
this_cred.times.endtime = 0;
if (auth_context && *auth_context && (*auth_context)->keytype)
this_cred.session.keytype = (*auth_context)->keytype;
ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred);
krb5_free_cred_contents(context, &this_cred);
if (ret)
return ret;
ret = krb5_mk_req_extended (context,
auth_context,
ap_req_options,
in_data,
cred,
outbuf);
krb5_free_creds(context, cred);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_req(krb5_context context,
krb5_auth_context *auth_context,
const krb5_flags ap_req_options,
const char *service,
const char *hostname,
krb5_data *in_data,
krb5_ccache ccache,
krb5_data *outbuf)
{
krb5_error_code ret;
char **realms;
char *real_hostname;
krb5_principal server;
ret = krb5_expand_hostname_realms (context, hostname,
&real_hostname, &realms);
if (ret)
return ret;
ret = krb5_build_principal (context, &server,
strlen(*realms),
*realms,
service,
real_hostname,
NULL);
free (real_hostname);
krb5_free_host_realm (context, realms);
if (ret)
return ret;
ret = krb5_mk_req_exact (context, auth_context, ap_req_options,
server, in_data, ccache, outbuf);
krb5_free_principal (context, server);
return ret;
}
+163
View File
@@ -0,0 +1,163 @@
/*
* Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: mk_req_ext.c,v 1.32 2006/03/19 20:33:13 lha Exp $");
krb5_error_code
_krb5_mk_req_internal(krb5_context context,
krb5_auth_context *auth_context,
const krb5_flags ap_req_options,
krb5_data *in_data,
krb5_creds *in_creds,
krb5_data *outbuf,
krb5_key_usage checksum_usage,
krb5_key_usage encrypt_usage)
{
krb5_error_code ret;
krb5_data authenticator;
Checksum c;
Checksum *c_opt;
krb5_auth_context ac;
if(auth_context) {
if(*auth_context == NULL)
ret = krb5_auth_con_init(context, auth_context);
else
ret = 0;
ac = *auth_context;
} else
ret = krb5_auth_con_init(context, &ac);
if(ret)
return ret;
if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) {
ret = krb5_auth_con_generatelocalsubkey(context,
ac,
&in_creds->session);
if(ret)
goto out;
}
krb5_free_keyblock(context, ac->keyblock);
ret = krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock);
if (ret)
goto out;
/* it's unclear what type of checksum we can use. try the best one, except:
* a) if it's configured differently for the current realm, or
* b) if the session key is des-cbc-crc
*/
if (in_data) {
if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) {
/* this is to make DCE secd (and older MIT kdcs?) happy */
ret = krb5_create_checksum(context,
NULL,
0,
CKSUMTYPE_RSA_MD4,
in_data->data,
in_data->length,
&c);
} else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 ||
ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) {
/* this is to make MS kdc happy */
ret = krb5_create_checksum(context,
NULL,
0,
CKSUMTYPE_RSA_MD5,
in_data->data,
in_data->length,
&c);
} else {
krb5_crypto crypto;
ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto);
if (ret)
goto out;
ret = krb5_create_checksum(context,
crypto,
checksum_usage,
0,
in_data->data,
in_data->length,
&c);
krb5_crypto_destroy(context, crypto);
}
c_opt = &c;
} else {
c_opt = NULL;
}
if (ret)
goto out;
ret = krb5_build_authenticator (context,
ac,
ac->keyblock->keytype,
in_creds,
c_opt,
NULL,
&authenticator,
encrypt_usage);
if (c_opt)
free_Checksum (c_opt);
if (ret)
goto out;
ret = krb5_build_ap_req (context, ac->keyblock->keytype,
in_creds, ap_req_options, authenticator, outbuf);
out:
if(auth_context == NULL)
krb5_auth_con_free(context, ac);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_req_extended(krb5_context context,
krb5_auth_context *auth_context,
const krb5_flags ap_req_options,
krb5_data *in_data,
krb5_creds *in_creds,
krb5_data *outbuf)
{
return _krb5_mk_req_internal (context,
auth_context,
ap_req_options,
in_data,
in_creds,
outbuf,
KRB5_KU_AP_REQ_AUTH_CKSUM,
KRB5_KU_AP_REQ_AUTH);
}
+126
View File
@@ -0,0 +1,126 @@
/*
* Copyright (c) 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of KTH nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
#include "krb5_locl.h"
RCSID("$Id: n-fold.c,v 1.7 2004/05/25 21:35:31 lha Exp $");
static void
rr13(unsigned char *buf, size_t len)
{
unsigned char *tmp;
int bytes = (len + 7) / 8;
int i;
if(len == 0)
return;
{
const int bits = 13 % len;
const int lbit = len % 8;
tmp = malloc(bytes);
memcpy(tmp, buf, bytes);
if(lbit) {
/* pad final byte with inital bits */
tmp[bytes - 1] &= 0xff << (8 - lbit);
for(i = lbit; i < 8; i += len)
tmp[bytes - 1] |= buf[0] >> i;
}
for(i = 0; i < bytes; i++) {
int bb;
int b1, s1, b2, s2;
/* calculate first bit position of this byte */
bb = 8 * i - bits;
while(bb < 0)
bb += len;
/* byte offset and shift count */
b1 = bb / 8;
s1 = bb % 8;
if(bb + 8 > bytes * 8)
/* watch for wraparound */
s2 = (len + 8 - s1) % 8;
else
s2 = 8 - s1;
b2 = (b1 + 1) % bytes;
buf[i] = (tmp[b1] << s1) | (tmp[b2] >> s2);
}
free(tmp);
}
}
/* Add `b' to `a', both beeing one's complement numbers. */
static void
add1(unsigned char *a, unsigned char *b, size_t len)
{
int i;
int carry = 0;
for(i = len - 1; i >= 0; i--){
int x = a[i] + b[i] + carry;
carry = x > 0xff;
a[i] = x & 0xff;
}
for(i = len - 1; carry && i >= 0; i--){
int x = a[i] + carry;
carry = x > 0xff;
a[i] = x & 0xff;
}
}
void KRB5_LIB_FUNCTION
_krb5_n_fold(const void *str, size_t len, void *key, size_t size)
{
/* if len < size we need at most N * len bytes, ie < 2 * size;
if len > size we need at most 2 * len */
size_t maxlen = 2 * max(size, len);
size_t l = 0;
unsigned char *tmp = malloc(maxlen);
unsigned char *buf = malloc(len);
memcpy(buf, str, len);
memset(key, 0, size);
do {
memcpy(tmp + l, buf, len);
l += len;
rr13(buf, len * 8);
while(l >= size) {
add1(key, tmp, size);
l -= size;
if(l == 0)
break;
memmove(tmp, tmp + size, l);
}
} while(l != 0);
memset(buf, 0, len);
free(buf);
memset(tmp, 0, maxlen);
free(tmp);
}
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright (c) 1997 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: padata.c,v 1.5 2005/06/17 04:28:35 lha Exp $");
PA_DATA *
krb5_find_padata(PA_DATA *val, unsigned len, int type, int *idx)
{
for(; *idx < len; (*idx)++)
if(val[*idx].padata_type == type)
return val + *idx;
return NULL;
}
int KRB5_LIB_FUNCTION
krb5_padata_add(krb5_context context, METHOD_DATA *md,
int type, void *buf, size_t len)
{
PA_DATA *pa;
pa = realloc (md->val, (md->len + 1) * sizeof(*md->val));
if (pa == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
md->val = pa;
pa[md->len].padata_type = type;
pa[md->len].padata_value.length = len;
pa[md->len].padata_value.data = buf;
md->len++;
return 0;
}
File diff suppressed because it is too large Load Diff
+242
View File
@@ -0,0 +1,242 @@
/*
* Copyright (c) 2006 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: plugin.c,v 1.2 2006/11/12 21:39:43 lha Exp $");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include <dirent.h>
struct krb5_plugin {
void *symbol;
void *dsohandle;
struct krb5_plugin *next;
};
struct plugin {
enum plugin_type type;
void *name;
void *symbol;
struct plugin *next;
};
static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER;
static struct plugin *registered = NULL;
static const char *plugin_dir = LIBDIR "/plugin/krb5";
/*
*
*/
void *
_krb5_plugin_get_symbol(struct krb5_plugin *p)
{
return p->symbol;
}
struct krb5_plugin *
_krb5_plugin_get_next(struct krb5_plugin *p)
{
return p->next;
}
/*
*
*/
static krb5_error_code
loadlib(krb5_context context,
enum plugin_type type,
const char *name,
const char *lib,
struct krb5_plugin **e)
{
*e = calloc(1, sizeof(**e));
if (*e == NULL) {
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
(*e)->dsohandle = dlopen(lib, 0);
if ((*e)->dsohandle == NULL) {
free(*e);
krb5_set_error_string(context, "Failed to load %s: %s",
lib, dlerror());
return ENOMEM;
}
/* dlsym doesn't care about the type */
(*e)->symbol = dlsym((*e)->dsohandle, name);
if ((*e)->symbol == NULL) {
dlclose((*e)->dsohandle);
free(*e);
krb5_clear_error_string(context);
return ENOMEM;
}
return 0;
}
krb5_error_code
_krb5_plugin_register(krb5_context context,
enum plugin_type type,
const char *name,
void *symbol)
{
struct plugin *e;
e = calloc(1, sizeof(*e));
if (e == NULL) {
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
e->type = type;
e->name = strdup(name);
if (e->name == NULL) {
free(e);
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
e->symbol = symbol;
HEIMDAL_MUTEX_lock(&plugin_mutex);
e->next = registered;
registered = e;
HEIMDAL_MUTEX_unlock(&plugin_mutex);
return 0;
}
krb5_error_code
_krb5_plugin_find(krb5_context context,
enum plugin_type type,
const char *name,
struct krb5_plugin **list)
{
struct krb5_plugin *e;
struct plugin *p;
krb5_error_code ret;
char *sysdirs[2] = { NULL, NULL };
char **dirs = NULL, **di;
struct dirent *entry;
char *path;
DIR *d = NULL;
*list = NULL;
HEIMDAL_MUTEX_lock(&plugin_mutex);
for (p = registered; p != NULL; p = p->next) {
if (p->type != type || strcmp(p->name, name) != 0)
continue;
e = calloc(1, sizeof(*e));
if (e == NULL) {
HEIMDAL_MUTEX_unlock(&plugin_mutex);
krb5_set_error_string(context, "out of memory");
ret = ENOMEM;
goto out;
}
e->symbol = p->symbol;
e->dsohandle = NULL;
e->next = *list;
*list = e;
}
HEIMDAL_MUTEX_unlock(&plugin_mutex);
dirs = krb5_config_get_strings(context, NULL, "libdefaults",
"plugin_dir", NULL);
if (dirs == NULL) {
sysdirs[0] = rk_UNCONST(plugin_dir);
dirs = sysdirs;
}
for (di = dirs; *di != NULL; di++) {
d = opendir(*di);
if (d == NULL)
continue;
while ((entry = readdir(d)) != NULL) {
asprintf(&path, "%s/%s", *di, entry->d_name);
if (path == NULL) {
krb5_set_error_string(context, "out of memory");
ret = ENOMEM;
goto out;
}
ret = loadlib(context, type, name, path, &e);
free(path);
if (ret)
continue;
e->next = *list;
*list = e;
}
closedir(d);
}
if (dirs != sysdirs)
krb5_config_free_strings(dirs);
if (*list == NULL) {
krb5_set_error_string(context, "Did not find a plugin for %s", name);
return ENOENT;
}
return 0;
out:
if (dirs && dirs != sysdirs)
krb5_config_free_strings(dirs);
if (d)
closedir(d);
_krb5_plugin_free(*list);
*list = NULL;
return ret;
}
void
_krb5_plugin_free(struct krb5_plugin *list)
{
struct krb5_plugin *next;
while (list) {
next = list->next;
if (list->dsohandle)
dlclose(list->dsohandle);
free(list);
list = next;
}
}
File diff suppressed because it is too large Load Diff
+336
View File
@@ -0,0 +1,336 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: rd_cred.c,v 1.29 2006/10/06 17:04:47 lha Exp $");
static krb5_error_code
compare_addrs(krb5_context context,
krb5_address *a,
krb5_address *b,
const char *message)
{
char a_str[64], b_str[64];
size_t len;
if(krb5_address_compare (context, a, b))
return 0;
krb5_print_address (a, a_str, sizeof(a_str), &len);
krb5_print_address (b, b_str, sizeof(b_str), &len);
krb5_set_error_string(context, "%s: %s != %s", message, b_str, a_str);
return KRB5KRB_AP_ERR_BADADDR;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_cred(krb5_context context,
krb5_auth_context auth_context,
krb5_data *in_data,
krb5_creds ***ret_creds,
krb5_replay_data *outdata)
{
krb5_error_code ret;
size_t len;
KRB_CRED cred;
EncKrbCredPart enc_krb_cred_part;
krb5_data enc_krb_cred_part_data;
krb5_crypto crypto;
int i;
memset(&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
if ((auth_context->flags &
(KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
outdata == NULL)
return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
*ret_creds = NULL;
ret = decode_KRB_CRED(in_data->data, in_data->length,
&cred, &len);
if(ret)
return ret;
if (cred.pvno != 5) {
ret = KRB5KRB_AP_ERR_BADVERSION;
krb5_clear_error_string (context);
goto out;
}
if (cred.msg_type != krb_cred) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
krb5_clear_error_string (context);
goto out;
}
if (cred.enc_part.etype == ETYPE_NULL) {
/* DK: MIT GSS-API Compatibility */
enc_krb_cred_part_data.length = cred.enc_part.cipher.length;
enc_krb_cred_part_data.data = cred.enc_part.cipher.data;
} else {
/* Try both subkey and session key.
*
* RFC4120 claims we should use the session key, but Heimdal
* before 0.8 used the remote subkey if it was send in the
* auth_context.
*/
if (auth_context->remote_subkey) {
ret = krb5_crypto_init(context, auth_context->remote_subkey,
0, &crypto);
if (ret)
goto out;
ret = krb5_decrypt_EncryptedData(context,
crypto,
KRB5_KU_KRB_CRED,
&cred.enc_part,
&enc_krb_cred_part_data);
krb5_crypto_destroy(context, crypto);
}
/*
* If there was not subkey, or we failed using subkey,
* retry using the session key
*/
if (auth_context->remote_subkey == NULL || ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
{
ret = krb5_crypto_init(context, auth_context->keyblock,
0, &crypto);
if (ret)
goto out;
ret = krb5_decrypt_EncryptedData(context,
crypto,
KRB5_KU_KRB_CRED,
&cred.enc_part,
&enc_krb_cred_part_data);
krb5_crypto_destroy(context, crypto);
}
if (ret)
goto out;
}
ret = krb5_decode_EncKrbCredPart (context,
enc_krb_cred_part_data.data,
enc_krb_cred_part_data.length,
&enc_krb_cred_part,
&len);
if (ret)
goto out;
/* check sender address */
if (enc_krb_cred_part.s_address
&& auth_context->remote_address
&& auth_context->remote_port) {
krb5_address *a;
ret = krb5_make_addrport (context, &a,
auth_context->remote_address,
auth_context->remote_port);
if (ret)
goto out;
ret = compare_addrs(context, a, enc_krb_cred_part.s_address,
"sender address is wrong in received creds");
krb5_free_address(context, a);
free(a);
if(ret)
goto out;
}
/* check receiver address */
if (enc_krb_cred_part.r_address
&& auth_context->local_address) {
if(auth_context->local_port &&
enc_krb_cred_part.r_address->addr_type == KRB5_ADDRESS_ADDRPORT) {
krb5_address *a;
ret = krb5_make_addrport (context, &a,
auth_context->local_address,
auth_context->local_port);
if (ret)
goto out;
ret = compare_addrs(context, a, enc_krb_cred_part.r_address,
"receiver address is wrong in received creds");
krb5_free_address(context, a);
free(a);
if(ret)
goto out;
} else {
ret = compare_addrs(context, auth_context->local_address,
enc_krb_cred_part.r_address,
"receiver address is wrong in received creds");
if(ret)
goto out;
}
}
/* check timestamp */
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_timestamp sec;
krb5_timeofday (context, &sec);
if (enc_krb_cred_part.timestamp == NULL ||
enc_krb_cred_part.usec == NULL ||
abs(*enc_krb_cred_part.timestamp - sec)
> context->max_skew) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_SKEW;
goto out;
}
}
if ((auth_context->flags &
(KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) {
/* if these fields are not present in the cred-part, silently
return zero */
memset(outdata, 0, sizeof(*outdata));
if(enc_krb_cred_part.timestamp)
outdata->timestamp = *enc_krb_cred_part.timestamp;
if(enc_krb_cred_part.usec)
outdata->usec = *enc_krb_cred_part.usec;
if(enc_krb_cred_part.nonce)
outdata->seq = *enc_krb_cred_part.nonce;
}
/* Convert to NULL terminated list of creds */
*ret_creds = calloc(enc_krb_cred_part.ticket_info.len + 1,
sizeof(**ret_creds));
if (*ret_creds == NULL) {
ret = ENOMEM;
krb5_set_error_string (context, "malloc: out of memory");
goto out;
}
for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) {
KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i];
krb5_creds *creds;
creds = calloc(1, sizeof(*creds));
if(creds == NULL) {
ret = ENOMEM;
krb5_set_error_string (context, "malloc: out of memory");
goto out;
}
ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
&cred.tickets.val[i], &len, ret);
if (ret) {
free(creds);
goto out;
}
if(creds->ticket.length != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
copy_EncryptionKey (&kci->key, &creds->session);
if (kci->prealm && kci->pname)
_krb5_principalname2krb5_principal (context,
&creds->client,
*kci->pname,
*kci->prealm);
if (kci->flags)
creds->flags.b = *kci->flags;
if (kci->authtime)
creds->times.authtime = *kci->authtime;
if (kci->starttime)
creds->times.starttime = *kci->starttime;
if (kci->endtime)
creds->times.endtime = *kci->endtime;
if (kci->renew_till)
creds->times.renew_till = *kci->renew_till;
if (kci->srealm && kci->sname)
_krb5_principalname2krb5_principal (context,
&creds->server,
*kci->sname,
*kci->srealm);
if (kci->caddr)
krb5_copy_addresses (context,
kci->caddr,
&creds->addresses);
(*ret_creds)[i] = creds;
}
(*ret_creds)[i] = NULL;
free_KRB_CRED (&cred);
free_EncKrbCredPart(&enc_krb_cred_part);
return 0;
out:
free_EncKrbCredPart(&enc_krb_cred_part);
free_KRB_CRED (&cred);
if(*ret_creds) {
for(i = 0; (*ret_creds)[i]; i++)
krb5_free_creds(context, (*ret_creds)[i]);
free(*ret_creds);
*ret_creds = NULL;
}
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_cred2 (krb5_context context,
krb5_auth_context auth_context,
krb5_ccache ccache,
krb5_data *in_data)
{
krb5_error_code ret;
krb5_creds **creds;
int i;
ret = krb5_rd_cred(context, auth_context, in_data, &creds, NULL);
if(ret)
return ret;
/* Store the creds in the ccache */
for(i = 0; creds && creds[i]; i++) {
krb5_cc_store_cred(context, ccache, creds[i]);
krb5_free_creds(context, creds[i]);
}
free(creds);
return 0;
}
+121
View File
@@ -0,0 +1,121 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: rd_error.c,v 1.8 2005/05/18 04:21:57 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_error(krb5_context context,
krb5_data *msg,
KRB_ERROR *result)
{
size_t len;
krb5_error_code ret;
ret = decode_KRB_ERROR(msg->data, msg->length, result, &len);
if(ret)
return ret;
result->error_code += KRB5KDC_ERR_NONE;
return 0;
}
void KRB5_LIB_FUNCTION
krb5_free_error_contents (krb5_context context,
krb5_error *error)
{
free_KRB_ERROR(error);
memset(error, 0, sizeof(*error));
}
void KRB5_LIB_FUNCTION
krb5_free_error (krb5_context context,
krb5_error *error)
{
krb5_free_error_contents (context, error);
free (error);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_error_from_rd_error(krb5_context context,
const krb5_error *error,
const krb5_creds *creds)
{
krb5_error_code ret;
ret = error->error_code;
if (error->e_text != NULL) {
krb5_set_error_string(context, "%s", *error->e_text);
} else {
char clientname[256], servername[256];
if (creds != NULL) {
krb5_unparse_name_fixed(context, creds->client,
clientname, sizeof(clientname));
krb5_unparse_name_fixed(context, creds->server,
servername, sizeof(servername));
}
switch (ret) {
case KRB5KDC_ERR_NAME_EXP :
krb5_set_error_string(context, "Client %s%s%s expired",
creds ? "(" : "",
creds ? clientname : "",
creds ? ")" : "");
break;
case KRB5KDC_ERR_SERVICE_EXP :
krb5_set_error_string(context, "Server %s%s%s expired",
creds ? "(" : "",
creds ? servername : "",
creds ? ")" : "");
break;
case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN :
krb5_set_error_string(context, "Client %s%s%s unknown",
creds ? "(" : "",
creds ? clientname : "",
creds ? ")" : "");
break;
case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN :
krb5_set_error_string(context, "Server %s%s%s unknown",
creds ? "(" : "",
creds ? servername : "",
creds ? ")" : "");
break;
default :
krb5_clear_error_string(context);
break;
}
}
return ret;
}
+179
View File
@@ -0,0 +1,179 @@
/*
* Copyright (c) 1997-2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: rd_priv.c,v 1.33 2006/04/12 16:18:10 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_priv(krb5_context context,
krb5_auth_context auth_context,
const krb5_data *inbuf,
krb5_data *outbuf,
krb5_replay_data *outdata)
{
krb5_error_code ret;
KRB_PRIV priv;
EncKrbPrivPart part;
size_t len;
krb5_data plain;
krb5_keyblock *key;
krb5_crypto crypto;
if (outbuf)
krb5_data_zero(outbuf);
if ((auth_context->flags &
(KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
outdata == NULL)
return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
memset(&priv, 0, sizeof(priv));
ret = decode_KRB_PRIV (inbuf->data, inbuf->length, &priv, &len);
if (ret)
goto failure;
if (priv.pvno != 5) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_BADVERSION;
goto failure;
}
if (priv.msg_type != krb_priv) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_MSG_TYPE;
goto failure;
}
if (auth_context->remote_subkey)
key = auth_context->remote_subkey;
else if (auth_context->local_subkey)
key = auth_context->local_subkey;
else
key = auth_context->keyblock;
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret)
goto failure;
ret = krb5_decrypt_EncryptedData(context,
crypto,
KRB5_KU_KRB_PRIV,
&priv.enc_part,
&plain);
krb5_crypto_destroy(context, crypto);
if (ret)
goto failure;
ret = decode_EncKrbPrivPart (plain.data, plain.length, &part, &len);
krb5_data_free (&plain);
if (ret)
goto failure;
/* check sender address */
if (part.s_address
&& auth_context->remote_address
&& !krb5_address_compare (context,
auth_context->remote_address,
part.s_address)) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_BADADDR;
goto failure_part;
}
/* check receiver address */
if (part.r_address
&& auth_context->local_address
&& !krb5_address_compare (context,
auth_context->local_address,
part.r_address)) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_BADADDR;
goto failure_part;
}
/* check timestamp */
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_timestamp sec;
krb5_timeofday (context, &sec);
if (part.timestamp == NULL ||
part.usec == NULL ||
abs(*part.timestamp - sec) > context->max_skew) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_SKEW;
goto failure_part;
}
}
/* XXX - check replay cache */
/* check sequence number. since MIT krb5 cannot generate a sequence
number of zero but instead generates no sequence number, we accept that
*/
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
if ((part.seq_number == NULL
&& auth_context->remote_seqnumber != 0)
|| (part.seq_number != NULL
&& *part.seq_number != auth_context->remote_seqnumber)) {
krb5_clear_error_string (context);
ret = KRB5KRB_AP_ERR_BADORDER;
goto failure_part;
}
auth_context->remote_seqnumber++;
}
ret = krb5_data_copy (outbuf, part.user_data.data, part.user_data.length);
if (ret)
goto failure_part;
if ((auth_context->flags &
(KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) {
/* if these fields are not present in the priv-part, silently
return zero */
memset(outdata, 0, sizeof(*outdata));
if(part.timestamp)
outdata->timestamp = *part.timestamp;
if(part.usec)
outdata->usec = *part.usec;
if(part.seq_number)
outdata->seq = *part.seq_number;
}
failure_part:
free_EncKrbPrivPart (&part);
failure:
free_KRB_PRIV (&priv);
return ret;
}
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: rd_rep.c,v 1.26 2006/08/21 09:19:22 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_rep(krb5_context context,
krb5_auth_context auth_context,
const krb5_data *inbuf,
krb5_ap_rep_enc_part **repl)
{
krb5_error_code ret;
AP_REP ap_rep;
size_t len;
krb5_data data;
krb5_crypto crypto;
krb5_data_zero (&data);
ret = 0;
ret = decode_AP_REP(inbuf->data, inbuf->length, &ap_rep, &len);
if (ret)
return ret;
if (ap_rep.pvno != 5) {
ret = KRB5KRB_AP_ERR_BADVERSION;
krb5_clear_error_string (context);
goto out;
}
if (ap_rep.msg_type != krb_ap_rep) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
krb5_clear_error_string (context);
goto out;
}
ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
if (ret)
goto out;
ret = krb5_decrypt_EncryptedData (context,
crypto,
KRB5_KU_AP_REQ_ENC_PART,
&ap_rep.enc_part,
&data);
krb5_crypto_destroy(context, crypto);
if (ret)
goto out;
*repl = malloc(sizeof(**repl));
if (*repl == NULL) {
ret = ENOMEM;
krb5_set_error_string (context, "malloc: out of memory");
goto out;
}
ret = krb5_decode_EncAPRepPart(context,
data.data,
data.length,
*repl,
&len);
if (ret)
return ret;
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
if ((*repl)->ctime != auth_context->authenticator->ctime ||
(*repl)->cusec != auth_context->authenticator->cusec)
{
krb5_free_ap_rep_enc_part(context, *repl);
*repl = NULL;
ret = KRB5KRB_AP_ERR_MUT_FAIL;
krb5_clear_error_string (context);
goto out;
}
}
if ((*repl)->seq_number)
krb5_auth_con_setremoteseqnumber(context, auth_context,
*((*repl)->seq_number));
if ((*repl)->subkey)
krb5_auth_con_setremotesubkey(context, auth_context, (*repl)->subkey);
out:
krb5_data_free (&data);
free_AP_REP (&ap_rep);
return ret;
}
void KRB5_LIB_FUNCTION
krb5_free_ap_rep_enc_part (krb5_context context,
krb5_ap_rep_enc_part *val)
{
if (val) {
free_EncAPRepPart (val);
free (val);
}
}
+835
View File
@@ -0,0 +1,835 @@
/*
* Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <krb5_locl.h>
RCSID("$Id: rd_req.c,v 1.68 2006/11/07 17:11:31 lha Exp $");
static krb5_error_code
decrypt_tkt_enc_part (krb5_context context,
krb5_keyblock *key,
EncryptedData *enc_part,
EncTicketPart *decr_part)
{
krb5_error_code ret;
krb5_data plain;
size_t len;
krb5_crypto crypto;
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret)
return ret;
ret = krb5_decrypt_EncryptedData (context,
crypto,
KRB5_KU_TICKET,
enc_part,
&plain);
krb5_crypto_destroy(context, crypto);
if (ret)
return ret;
ret = krb5_decode_EncTicketPart(context, plain.data, plain.length,
decr_part, &len);
krb5_data_free (&plain);
return ret;
}
static krb5_error_code
decrypt_authenticator (krb5_context context,
EncryptionKey *key,
EncryptedData *enc_part,
Authenticator *authenticator,
krb5_key_usage usage)
{
krb5_error_code ret;
krb5_data plain;
size_t len;
krb5_crypto crypto;
ret = krb5_crypto_init(context, key, 0, &crypto);
if (ret)
return ret;
ret = krb5_decrypt_EncryptedData (context,
crypto,
usage /* KRB5_KU_AP_REQ_AUTH */,
enc_part,
&plain);
/* for backwards compatibility, also try the old usage */
if (ret && usage == KRB5_KU_TGS_REQ_AUTH)
ret = krb5_decrypt_EncryptedData (context,
crypto,
KRB5_KU_AP_REQ_AUTH,
enc_part,
&plain);
krb5_crypto_destroy(context, crypto);
if (ret)
return ret;
ret = krb5_decode_Authenticator(context, plain.data, plain.length,
authenticator, &len);
krb5_data_free (&plain);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decode_ap_req(krb5_context context,
const krb5_data *inbuf,
krb5_ap_req *ap_req)
{
krb5_error_code ret;
size_t len;
ret = decode_AP_REQ(inbuf->data, inbuf->length, ap_req, &len);
if (ret)
return ret;
if (ap_req->pvno != 5){
free_AP_REQ(ap_req);
krb5_clear_error_string (context);
return KRB5KRB_AP_ERR_BADVERSION;
}
if (ap_req->msg_type != krb_ap_req){
free_AP_REQ(ap_req);
krb5_clear_error_string (context);
return KRB5KRB_AP_ERR_MSG_TYPE;
}
if (ap_req->ticket.tkt_vno != 5){
free_AP_REQ(ap_req);
krb5_clear_error_string (context);
return KRB5KRB_AP_ERR_BADVERSION;
}
return 0;
}
static krb5_error_code
check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc)
{
char **realms;
int num_realms;
krb5_error_code ret;
/*
* Windows 2000 and 2003 uses this inside their TGT so its normaly
* not seen by others, however, samba4 joined with a Windows AD as
* a Domain Controller gets exposed to this.
*/
if(enc->transited.tr_type == 0 && enc->transited.contents.length == 0)
return 0;
if(enc->transited.tr_type != DOMAIN_X500_COMPRESS)
return KRB5KDC_ERR_TRTYPE_NOSUPP;
if(enc->transited.contents.length == 0)
return 0;
ret = krb5_domain_x500_decode(context, enc->transited.contents,
&realms, &num_realms,
enc->crealm,
ticket->realm);
if(ret)
return ret;
ret = krb5_check_transited(context, enc->crealm,
ticket->realm,
realms, num_realms, NULL);
free(realms);
return ret;
}
static krb5_error_code
find_etypelist(krb5_context context,
krb5_auth_context auth_context,
EtypeList *etypes)
{
krb5_error_code ret;
krb5_authdata *ad;
krb5_authdata adIfRelevant;
unsigned i;
adIfRelevant.len = 0;
etypes->len = 0;
etypes->val = NULL;
ad = auth_context->authenticator->authorization_data;
if (ad == NULL)
return 0;
for (i = 0; i < ad->len; i++) {
if (ad->val[i].ad_type == KRB5_AUTHDATA_IF_RELEVANT) {
ret = decode_AD_IF_RELEVANT(ad->val[i].ad_data.data,
ad->val[i].ad_data.length,
&adIfRelevant,
NULL);
if (ret)
return ret;
if (adIfRelevant.len == 1 &&
adIfRelevant.val[0].ad_type ==
KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION) {
break;
}
free_AD_IF_RELEVANT(&adIfRelevant);
adIfRelevant.len = 0;
}
}
if (adIfRelevant.len == 0)
return 0;
ret = decode_EtypeList(adIfRelevant.val[0].ad_data.data,
adIfRelevant.val[0].ad_data.length,
etypes,
NULL);
free_AD_IF_RELEVANT(&adIfRelevant);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_decrypt_ticket(krb5_context context,
Ticket *ticket,
krb5_keyblock *key,
EncTicketPart *out,
krb5_flags flags)
{
EncTicketPart t;
krb5_error_code ret;
ret = decrypt_tkt_enc_part (context, key, &ticket->enc_part, &t);
if (ret)
return ret;
{
krb5_timestamp now;
time_t start = t.authtime;
krb5_timeofday (context, &now);
if(t.starttime)
start = *t.starttime;
if(start - now > context->max_skew
|| (t.flags.invalid
&& !(flags & KRB5_VERIFY_AP_REQ_IGNORE_INVALID))) {
free_EncTicketPart(&t);
krb5_clear_error_string (context);
return KRB5KRB_AP_ERR_TKT_NYV;
}
if(now - t.endtime > context->max_skew) {
free_EncTicketPart(&t);
krb5_clear_error_string (context);
return KRB5KRB_AP_ERR_TKT_EXPIRED;
}
if(!t.flags.transited_policy_checked) {
ret = check_transited(context, ticket, &t);
if(ret) {
free_EncTicketPart(&t);
return ret;
}
}
}
if(out)
*out = t;
else
free_EncTicketPart(&t);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_verify_authenticator_checksum(krb5_context context,
krb5_auth_context ac,
void *data,
size_t len)
{
krb5_error_code ret;
krb5_keyblock *key;
krb5_authenticator authenticator;
krb5_crypto crypto;
ret = krb5_auth_con_getauthenticator (context,
ac,
&authenticator);
if(ret)
return ret;
if(authenticator->cksum == NULL) {
krb5_free_authenticator(context, &authenticator);
return -17;
}
ret = krb5_auth_con_getkey(context, ac, &key);
if(ret) {
krb5_free_authenticator(context, &authenticator);
return ret;
}
ret = krb5_crypto_init(context, key, 0, &crypto);
if(ret)
goto out;
ret = krb5_verify_checksum (context,
crypto,
KRB5_KU_AP_REQ_AUTH_CKSUM,
data,
len,
authenticator->cksum);
krb5_crypto_destroy(context, crypto);
out:
krb5_free_authenticator(context, &authenticator);
krb5_free_keyblock(context, key);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_verify_ap_req(krb5_context context,
krb5_auth_context *auth_context,
krb5_ap_req *ap_req,
krb5_const_principal server,
krb5_keyblock *keyblock,
krb5_flags flags,
krb5_flags *ap_req_options,
krb5_ticket **ticket)
{
return krb5_verify_ap_req2 (context,
auth_context,
ap_req,
server,
keyblock,
flags,
ap_req_options,
ticket,
KRB5_KU_AP_REQ_AUTH);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_verify_ap_req2(krb5_context context,
krb5_auth_context *auth_context,
krb5_ap_req *ap_req,
krb5_const_principal server,
krb5_keyblock *keyblock,
krb5_flags flags,
krb5_flags *ap_req_options,
krb5_ticket **ticket,
krb5_key_usage usage)
{
krb5_ticket *t;
krb5_auth_context ac;
krb5_error_code ret;
EtypeList etypes;
if (ticket)
*ticket = NULL;
if (auth_context && *auth_context) {
ac = *auth_context;
} else {
ret = krb5_auth_con_init (context, &ac);
if (ret)
return ret;
}
t = calloc(1, sizeof(*t));
if (t == NULL) {
ret = ENOMEM;
krb5_clear_error_string (context);
goto out;
}
if (ap_req->ap_options.use_session_key && ac->keyblock){
ret = krb5_decrypt_ticket(context, &ap_req->ticket,
ac->keyblock,
&t->ticket,
flags);
krb5_free_keyblock(context, ac->keyblock);
ac->keyblock = NULL;
}else
ret = krb5_decrypt_ticket(context, &ap_req->ticket,
keyblock,
&t->ticket,
flags);
if(ret)
goto out;
ret = _krb5_principalname2krb5_principal(context,
&t->server,
ap_req->ticket.sname,
ap_req->ticket.realm);
if (ret) goto out;
ret = _krb5_principalname2krb5_principal(context,
&t->client,
t->ticket.cname,
t->ticket.crealm);
if (ret) goto out;
/* save key */
ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock);
if (ret) goto out;
ret = decrypt_authenticator (context,
&t->ticket.key,
&ap_req->authenticator,
ac->authenticator,
usage);
if (ret)
goto out;
{
krb5_principal p1, p2;
krb5_boolean res;
_krb5_principalname2krb5_principal(context,
&p1,
ac->authenticator->cname,
ac->authenticator->crealm);
_krb5_principalname2krb5_principal(context,
&p2,
t->ticket.cname,
t->ticket.crealm);
res = krb5_principal_compare (context, p1, p2);
krb5_free_principal (context, p1);
krb5_free_principal (context, p2);
if (!res) {
ret = KRB5KRB_AP_ERR_BADMATCH;
krb5_clear_error_string (context);
goto out;
}
}
/* check addresses */
if (t->ticket.caddr
&& ac->remote_address
&& !krb5_address_search (context,
ac->remote_address,
t->ticket.caddr)) {
ret = KRB5KRB_AP_ERR_BADADDR;
krb5_clear_error_string (context);
goto out;
}
/* check timestamp in authenticator */
{
krb5_timestamp now;
krb5_timeofday (context, &now);
if (abs(ac->authenticator->ctime - now) > context->max_skew) {
ret = KRB5KRB_AP_ERR_SKEW;
krb5_clear_error_string (context);
goto out;
}
}
if (ac->authenticator->seq_number)
krb5_auth_con_setremoteseqnumber(context, ac,
*ac->authenticator->seq_number);
/* XXX - Xor sequence numbers */
if (ac->authenticator->subkey) {
ret = krb5_auth_con_setremotesubkey(context, ac,
ac->authenticator->subkey);
if (ret)
goto out;
}
ret = find_etypelist(context, ac, &etypes);
if (ret)
goto out;
ac->keytype = ETYPE_NULL;
if (etypes.val) {
int i;
for (i = 0; i < etypes.len; i++) {
if (krb5_enctype_valid(context, etypes.val[i]) == 0) {
ac->keytype = etypes.val[i];
break;
}
}
}
if (ap_req_options) {
*ap_req_options = 0;
if (ac->keytype != ETYPE_NULL)
*ap_req_options |= AP_OPTS_USE_SUBKEY;
if (ap_req->ap_options.use_session_key)
*ap_req_options |= AP_OPTS_USE_SESSION_KEY;
if (ap_req->ap_options.mutual_required)
*ap_req_options |= AP_OPTS_MUTUAL_REQUIRED;
}
if(ticket)
*ticket = t;
else
krb5_free_ticket (context, t);
if (auth_context) {
if (*auth_context == NULL)
*auth_context = ac;
} else
krb5_auth_con_free (context, ac);
free_EtypeList(&etypes);
return 0;
out:
if (t)
krb5_free_ticket (context, t);
if (auth_context == NULL || *auth_context == NULL)
krb5_auth_con_free (context, ac);
return ret;
}
/*
*
*/
struct krb5_rd_req_in_ctx {
krb5_keytab keytab;
krb5_keyblock *keyblock;
};
struct krb5_rd_req_out_ctx {
krb5_keyblock *keyblock;
krb5_flags ap_req_options;
krb5_ticket *ticket;
};
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_in_ctx_alloc(krb5_context context, krb5_rd_req_in_ctx *ctx)
{
*ctx = calloc(1, sizeof(**ctx));
if (*ctx == NULL) {
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_in_set_keytab(krb5_context context,
krb5_rd_req_in_ctx in,
krb5_keytab keytab)
{
in->keytab = keytab; /* XXX should make copy */
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_in_set_keyblock(krb5_context context,
krb5_rd_req_in_ctx in,
krb5_keyblock *keyblock)
{
in->keyblock = keyblock; /* XXX should make copy */
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_out_get_ap_req_options(krb5_context context,
krb5_rd_req_out_ctx out,
krb5_flags *ap_req_options)
{
*ap_req_options = out->ap_req_options;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_out_get_ticket(krb5_context context,
krb5_rd_req_out_ctx out,
krb5_ticket **ticket)
{
return krb5_copy_ticket(context, out->ticket, ticket);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_out_get_keyblock(krb5_context context,
krb5_rd_req_out_ctx out,
krb5_keyblock **keyblock)
{
return krb5_copy_keyblock(context, out->keyblock, keyblock);
}
void KRB5_LIB_FUNCTION
krb5_rd_req_in_ctx_free(krb5_context context, krb5_rd_req_in_ctx ctx)
{
free(ctx);
}
krb5_error_code KRB5_LIB_FUNCTION
_krb5_rd_req_out_ctx_alloc(krb5_context context, krb5_rd_req_out_ctx *ctx)
{
*ctx = calloc(1, sizeof(**ctx));
if (*ctx == NULL) {
krb5_set_error_string(context, "out of memory");
return ENOMEM;
}
return 0;
}
void KRB5_LIB_FUNCTION
krb5_rd_req_out_ctx_free(krb5_context context, krb5_rd_req_out_ctx ctx)
{
krb5_free_keyblock(context, ctx->keyblock);
free(ctx);
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req(krb5_context context,
krb5_auth_context *auth_context,
const krb5_data *inbuf,
krb5_const_principal server,
krb5_keytab keytab,
krb5_flags *ap_req_options,
krb5_ticket **ticket)
{
krb5_error_code ret;
krb5_rd_req_in_ctx in;
krb5_rd_req_out_ctx out;
ret = krb5_rd_req_in_ctx_alloc(context, &in);
if (ret)
return ret;
ret = krb5_rd_req_in_set_keytab(context, in, keytab);
if (ret) {
krb5_rd_req_in_ctx_free(context, in);
return ret;
}
ret = krb5_rd_req_ctx(context, auth_context, inbuf, server, in, &out);
krb5_rd_req_in_ctx_free(context, in);
if (ret)
return ret;
if (ap_req_options)
*ap_req_options = out->ap_req_options;
if (ticket) {
ret = krb5_copy_ticket(context, out->ticket, ticket);
if (ret)
goto out;
}
out:
krb5_rd_req_out_ctx_free(context, out);
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_with_keyblock(krb5_context context,
krb5_auth_context *auth_context,
const krb5_data *inbuf,
krb5_const_principal server,
krb5_keyblock *keyblock,
krb5_flags *ap_req_options,
krb5_ticket **ticket)
{
krb5_error_code ret;
krb5_rd_req_in_ctx in;
krb5_rd_req_out_ctx out;
ret = krb5_rd_req_in_ctx_alloc(context, &in);
if (ret)
return ret;
ret = krb5_rd_req_in_set_keyblock(context, in, keyblock);
if (ret) {
krb5_rd_req_in_ctx_free(context, in);
return ret;
}
ret = krb5_rd_req_ctx(context, auth_context, inbuf, server, in, &out);
krb5_rd_req_in_ctx_free(context, in);
if (ret)
return ret;
if (ap_req_options)
*ap_req_options = out->ap_req_options;
if (ticket) {
ret = krb5_copy_ticket(context, out->ticket, ticket);
if (ret)
goto out;
}
out:
krb5_rd_req_out_ctx_free(context, out);
return ret;
}
/*
*
*/
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;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_ctx(krb5_context context,
krb5_auth_context *auth_context,
const krb5_data *inbuf,
krb5_const_principal server,
krb5_rd_req_in_ctx inctx,
krb5_rd_req_out_ctx *outctx)
{
krb5_error_code ret;
krb5_ap_req ap_req;
krb5_principal service = NULL;
krb5_rd_req_out_ctx o = NULL;
ret = _krb5_rd_req_out_ctx_alloc(context, &o);
if (ret)
goto out;
if (*auth_context == NULL) {
ret = krb5_auth_con_init(context, auth_context);
if (ret)
goto out;
}
ret = krb5_decode_ap_req(context, inbuf, &ap_req);
if(ret)
goto out;
if(server == NULL){
ret = _krb5_principalname2krb5_principal(context,
&service,
ap_req.ticket.sname,
ap_req.ticket.realm);
if (ret)
goto out;
server = service;
}
if (ap_req.ap_options.use_session_key &&
(*auth_context)->keyblock == NULL) {
krb5_set_error_string(context, "krb5_rd_req: user to user auth "
"without session key given");
ret = KRB5KRB_AP_ERR_NOKEY;
goto out;
}
if((*auth_context)->keyblock){
ret = krb5_copy_keyblock(context,
(*auth_context)->keyblock,
&o->keyblock);
if (ret)
goto out;
} else if(inctx->keyblock){
ret = krb5_copy_keyblock(context,
inctx->keyblock,
&o->keyblock);
if (ret)
goto out;
} else {
krb5_keytab keytab = NULL;
if (inctx && inctx->keytab)
keytab = inctx->keytab;
ret = get_key_from_keytab(context,
auth_context,
&ap_req,
server,
keytab,
&o->keyblock);
if(ret)
goto out;
}
ret = krb5_verify_ap_req(context,
auth_context,
&ap_req,
server,
o->keyblock,
0,
&o->ap_req_options,
&o->ticket);
out:
if (ret || outctx == NULL) {
krb5_rd_req_out_ctx_free(context, o);
} else
*outctx = o;
free_AP_REQ(&ap_req);
if(service)
krb5_free_principal(context, service);
return ret;
}
+312
View File
@@ -0,0 +1,312 @@
/*
* Copyright (c) 1997-2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include <vis.h>
RCSID("$Id: replay.c,v 1.12 2006/04/10 17:13:49 lha Exp $");
struct krb5_rcache_data {
char *name;
};
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_resolve(krb5_context context,
krb5_rcache id,
const char *name)
{
id->name = strdup(name);
if(id->name == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return KRB5_RC_MALLOC;
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_resolve_type(krb5_context context,
krb5_rcache *id,
const char *type)
{
*id = NULL;
if(strcmp(type, "FILE")) {
krb5_set_error_string (context, "replay cache type %s not supported",
type);
return KRB5_RC_TYPE_NOTFOUND;
}
*id = calloc(1, sizeof(**id));
if(*id == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return KRB5_RC_MALLOC;
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_resolve_full(krb5_context context,
krb5_rcache *id,
const char *string_name)
{
krb5_error_code ret;
*id = NULL;
if(strncmp(string_name, "FILE:", 5)) {
krb5_set_error_string (context, "replay cache type %s not supported",
string_name);
return KRB5_RC_TYPE_NOTFOUND;
}
ret = krb5_rc_resolve_type(context, id, "FILE");
if(ret)
return ret;
ret = krb5_rc_resolve(context, *id, string_name + 5);
if (ret) {
krb5_rc_close(context, *id);
*id = NULL;
}
return ret;
}
const char* KRB5_LIB_FUNCTION
krb5_rc_default_name(krb5_context context)
{
return "FILE:/var/run/default_rcache";
}
const char* KRB5_LIB_FUNCTION
krb5_rc_default_type(krb5_context context)
{
return "FILE";
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_default(krb5_context context,
krb5_rcache *id)
{
return krb5_rc_resolve_full(context, id, krb5_rc_default_name(context));
}
struct rc_entry{
time_t stamp;
unsigned char data[16];
};
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_initialize(krb5_context context,
krb5_rcache id,
krb5_deltat auth_lifespan)
{
FILE *f = fopen(id->name, "w");
struct rc_entry tmp;
int ret;
if(f == NULL) {
ret = errno;
krb5_set_error_string (context, "open(%s): %s", id->name,
strerror(ret));
return ret;
}
tmp.stamp = auth_lifespan;
fwrite(&tmp, 1, sizeof(tmp), f);
fclose(f);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_recover(krb5_context context,
krb5_rcache id)
{
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_destroy(krb5_context context,
krb5_rcache id)
{
int ret;
if(remove(id->name) < 0) {
ret = errno;
krb5_set_error_string (context, "remove(%s): %s", id->name,
strerror(ret));
return ret;
}
return krb5_rc_close(context, id);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_close(krb5_context context,
krb5_rcache id)
{
free(id->name);
free(id);
return 0;
}
static void
checksum_authenticator(Authenticator *auth, void *data)
{
MD5_CTX md5;
int i;
MD5_Init (&md5);
MD5_Update (&md5, auth->crealm, strlen(auth->crealm));
for(i = 0; i < auth->cname.name_string.len; i++)
MD5_Update(&md5, auth->cname.name_string.val[i],
strlen(auth->cname.name_string.val[i]));
MD5_Update (&md5, &auth->ctime, sizeof(auth->ctime));
MD5_Update (&md5, &auth->cusec, sizeof(auth->cusec));
MD5_Final (data, &md5);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_store(krb5_context context,
krb5_rcache id,
krb5_donot_replay *rep)
{
struct rc_entry ent, tmp;
time_t t;
FILE *f;
int ret;
ent.stamp = time(NULL);
checksum_authenticator(rep, ent.data);
f = fopen(id->name, "r");
if(f == NULL) {
ret = errno;
krb5_set_error_string (context, "open(%s): %s", id->name,
strerror(ret));
return ret;
}
fread(&tmp, sizeof(ent), 1, f);
t = ent.stamp - tmp.stamp;
while(fread(&tmp, sizeof(ent), 1, f)){
if(tmp.stamp < t)
continue;
if(memcmp(tmp.data, ent.data, sizeof(ent.data)) == 0){
fclose(f);
krb5_clear_error_string (context);
return KRB5_RC_REPLAY;
}
}
if(ferror(f)){
ret = errno;
fclose(f);
krb5_set_error_string (context, "%s: %s", id->name, strerror(ret));
return ret;
}
fclose(f);
f = fopen(id->name, "a");
if(f == NULL) {
krb5_set_error_string (context, "open(%s): %s", id->name,
strerror(errno));
return KRB5_RC_IO_UNKNOWN;
}
fwrite(&ent, 1, sizeof(ent), f);
fclose(f);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_expunge(krb5_context context,
krb5_rcache id)
{
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_rc_get_lifespan(krb5_context context,
krb5_rcache id,
krb5_deltat *auth_lifespan)
{
FILE *f = fopen(id->name, "r");
int r;
struct rc_entry ent;
r = fread(&ent, sizeof(ent), 1, f);
fclose(f);
if(r){
*auth_lifespan = ent.stamp;
return 0;
}
krb5_clear_error_string (context);
return KRB5_RC_IO_UNKNOWN;
}
const char* KRB5_LIB_FUNCTION
krb5_rc_get_name(krb5_context context,
krb5_rcache id)
{
return id->name;
}
const char* KRB5_LIB_FUNCTION
krb5_rc_get_type(krb5_context context,
krb5_rcache id)
{
return "FILE";
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_server_rcache(krb5_context context,
const krb5_data *piece,
krb5_rcache *id)
{
krb5_rcache rcache;
krb5_error_code ret;
char *tmp = malloc(4 * piece->length + 1);
char *name;
if(tmp == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL);
#ifdef HAVE_GETEUID
asprintf(&name, "FILE:rc_%s_%u", tmp, (unsigned)geteuid());
#else
asprintf(&name, "FILE:rc_%s", tmp);
#endif
free(tmp);
if(name == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
ret = krb5_rc_resolve_full(context, &rcache, name);
free(name);
if(ret)
return ret;
*id = rcache;
return ret;
}
+459
View File
@@ -0,0 +1,459 @@
/*
* Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: send_to_kdc.c,v 1.60 2006/10/20 18:42:01 lha Exp $");
struct send_to_kdc {
krb5_send_to_kdc_func func;
void *data;
};
/*
* send the data in `req' on the socket `fd' (which is datagram iff udp)
* waiting `tmout' for a reply and returning the reply in `rep'.
* iff limit read up to this many bytes
* returns 0 and data in `rep' if succesful, otherwise -1
*/
static int
recv_loop (int fd,
time_t tmout,
int udp,
size_t limit,
krb5_data *rep)
{
fd_set fdset;
struct timeval timeout;
int ret;
int nbytes;
if (fd >= FD_SETSIZE) {
return -1;
}
krb5_data_zero(rep);
do {
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
timeout.tv_sec = tmout;
timeout.tv_usec = 0;
ret = select (fd + 1, &fdset, NULL, NULL, &timeout);
if (ret < 0) {
if (errno == EINTR)
continue;
return -1;
} else if (ret == 0) {
return 0;
} else {
void *tmp;
if (ioctl (fd, FIONREAD, &nbytes) < 0) {
krb5_data_free (rep);
return -1;
}
if(nbytes <= 0)
return 0;
if (limit)
nbytes = min(nbytes, limit - rep->length);
tmp = realloc (rep->data, rep->length + nbytes);
if (tmp == NULL) {
krb5_data_free (rep);
return -1;
}
rep->data = tmp;
ret = recv (fd, (char*)tmp + rep->length, nbytes, 0);
if (ret < 0) {
krb5_data_free (rep);
return -1;
}
rep->length += ret;
}
} while(!udp && (limit == 0 || rep->length < limit));
return 0;
}
/*
* Send kerberos requests and receive a reply on a udp or any other kind
* of a datagram socket. See `recv_loop'.
*/
static int
send_and_recv_udp(int fd,
time_t tmout,
const krb5_data *req,
krb5_data *rep)
{
if (send (fd, req->data, req->length, 0) < 0)
return -1;
return recv_loop(fd, tmout, 1, 0, rep);
}
/*
* `send_and_recv' for a TCP (or any other stream) socket.
* Since there are no record limits on a stream socket the protocol here
* is to prepend the request with 4 bytes of its length and the reply
* is similarly encoded.
*/
static int
send_and_recv_tcp(int fd,
time_t tmout,
const krb5_data *req,
krb5_data *rep)
{
unsigned char len[4];
unsigned long rep_len;
krb5_data len_data;
_krb5_put_int(len, req->length, 4);
if(net_write(fd, len, sizeof(len)) < 0)
return -1;
if(net_write(fd, req->data, req->length) < 0)
return -1;
if (recv_loop (fd, tmout, 0, 4, &len_data) < 0)
return -1;
if (len_data.length != 4) {
krb5_data_free (&len_data);
return -1;
}
_krb5_get_int(len_data.data, &rep_len, 4);
krb5_data_free (&len_data);
if (recv_loop (fd, tmout, 0, rep_len, rep) < 0)
return -1;
if(rep->length != rep_len) {
krb5_data_free (rep);
return -1;
}
return 0;
}
int
_krb5_send_and_recv_tcp(int fd,
time_t tmout,
const krb5_data *req,
krb5_data *rep)
{
return send_and_recv_tcp(fd, tmout, req, rep);
}
/*
* `send_and_recv' tailored for the HTTP protocol.
*/
static int
send_and_recv_http(int fd,
time_t tmout,
const char *prefix,
const krb5_data *req,
krb5_data *rep)
{
char *request;
char *str;
int ret;
int len = base64_encode(req->data, req->length, &str);
if(len < 0)
return -1;
asprintf(&request, "GET %s%s HTTP/1.0\r\n\r\n", prefix, str);
free(str);
if (request == NULL)
return -1;
ret = net_write (fd, request, strlen(request));
free (request);
if (ret < 0)
return ret;
ret = recv_loop(fd, tmout, 0, 0, rep);
if(ret)
return ret;
{
unsigned long rep_len;
char *s, *p;
s = realloc(rep->data, rep->length + 1);
if (s == NULL) {
krb5_data_free (rep);
return -1;
}
s[rep->length] = 0;
p = strstr(s, "\r\n\r\n");
if(p == NULL) {
krb5_data_zero(rep);
free(s);
return -1;
}
p += 4;
rep->data = s;
rep->length -= p - s;
if(rep->length < 4) { /* remove length */
krb5_data_zero(rep);
free(s);
return -1;
}
rep->length -= 4;
_krb5_get_int(p, &rep_len, 4);
if (rep_len != rep->length) {
krb5_data_zero(rep);
free(s);
return -1;
}
memmove(rep->data, p + 4, rep->length);
}
return 0;
}
static int
init_port(const char *s, int fallback)
{
if (s) {
int tmp;
sscanf (s, "%d", &tmp);
return htons(tmp);
} else
return fallback;
}
/*
* Return 0 if succesful, otherwise 1
*/
static int
send_via_proxy (krb5_context context,
const krb5_krbhst_info *hi,
const krb5_data *send_data,
krb5_data *receive)
{
char *proxy2 = strdup(context->http_proxy);
char *proxy = proxy2;
char *prefix;
char *colon;
struct addrinfo hints;
struct addrinfo *ai, *a;
int ret;
int s = -1;
char portstr[NI_MAXSERV];
if (proxy == NULL)
return ENOMEM;
if (strncmp (proxy, "http://", 7) == 0)
proxy += 7;
colon = strchr(proxy, ':');
if(colon != NULL)
*colon++ = '\0';
memset (&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf (portstr, sizeof(portstr), "%d",
ntohs(init_port (colon, htons(80))));
ret = getaddrinfo (proxy, portstr, &hints, &ai);
free (proxy2);
if (ret)
return krb5_eai_to_heim_errno(ret, errno);
for (a = ai; a != NULL; a = a->ai_next) {
s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
if (s < 0)
continue;
if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
close (s);
continue;
}
break;
}
if (a == NULL) {
freeaddrinfo (ai);
return 1;
}
freeaddrinfo (ai);
asprintf(&prefix, "http://%s/", hi->hostname);
if(prefix == NULL) {
close(s);
return 1;
}
ret = send_and_recv_http(s, context->kdc_timeout,
prefix, send_data, receive);
close (s);
free(prefix);
if(ret == 0 && receive->length != 0)
return 0;
return 1;
}
/*
* Send the data `send' to one host from `handle` and get back the reply
* in `receive'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_sendto (krb5_context context,
const krb5_data *send_data,
krb5_krbhst_handle handle,
krb5_data *receive)
{
krb5_error_code ret;
int fd;
int i;
for (i = 0; i < context->max_retries; ++i) {
krb5_krbhst_info *hi;
while (krb5_krbhst_next(context, handle, &hi) == 0) {
struct addrinfo *ai, *a;
if (context->send_to_kdc) {
struct send_to_kdc *s = context->send_to_kdc;
ret = (*s->func)(context, s->data,
hi, send_data, receive);
if (ret == 0 && receive->length != 0)
goto out;
continue;
}
if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) {
if (send_via_proxy (context, hi, send_data, receive) == 0) {
ret = 0;
goto out;
}
continue;
}
ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
if (ret)
continue;
for (a = ai; a != NULL; a = a->ai_next) {
fd = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
if (fd < 0)
continue;
if (connect (fd, a->ai_addr, a->ai_addrlen) < 0) {
close (fd);
continue;
}
switch (hi->proto) {
case KRB5_KRBHST_HTTP :
ret = send_and_recv_http(fd, context->kdc_timeout,
"", send_data, receive);
break;
case KRB5_KRBHST_TCP :
ret = send_and_recv_tcp (fd, context->kdc_timeout,
send_data, receive);
break;
case KRB5_KRBHST_UDP :
ret = send_and_recv_udp (fd, context->kdc_timeout,
send_data, receive);
break;
}
close (fd);
if(ret == 0 && receive->length != 0)
goto out;
}
}
krb5_krbhst_reset(context, handle);
}
krb5_clear_error_string (context);
ret = KRB5_KDC_UNREACH;
out:
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_sendto_kdc(krb5_context context,
const krb5_data *send_data,
const krb5_realm *realm,
krb5_data *receive)
{
return krb5_sendto_kdc_flags(context, send_data, realm, receive, 0);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_sendto_kdc_flags(krb5_context context,
const krb5_data *send_data,
const krb5_realm *realm,
krb5_data *receive,
int flags)
{
krb5_error_code ret;
krb5_krbhst_handle handle;
int type;
if ((flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc)
type = KRB5_KRBHST_ADMIN;
else
type = KRB5_KRBHST_KDC;
if (send_data->length > context->large_msg_size)
flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
ret = krb5_krbhst_init_flags(context, *realm, type, flags, &handle);
if (ret)
return ret;
ret = krb5_sendto(context, send_data, handle, receive);
krb5_krbhst_free(context, handle);
if (ret == KRB5_KDC_UNREACH)
krb5_set_error_string(context,
"unable to reach any KDC in realm %s", *realm);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_send_to_kdc_func(krb5_context context,
krb5_send_to_kdc_func func,
void *data)
{
free(context->send_to_kdc);
if (func == NULL) {
context->send_to_kdc = NULL;
return 0;
}
context->send_to_kdc = malloc(sizeof(*context->send_to_kdc));
if (context->send_to_kdc == NULL) {
krb5_set_error_string(context, "Out of memory");
return ENOMEM;
}
context->send_to_kdc->func = func;
context->send_to_kdc->data = data;
return 0;
}
@@ -0,0 +1,90 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: set_default_realm.c,v 1.14 2004/05/25 21:42:26 lha Exp $");
/*
* Convert the simple string `s' into a NULL-terminated and freshly allocated
* list in `list'. Return an error code.
*/
static krb5_error_code
string_to_list (krb5_context context, const char *s, krb5_realm **list)
{
*list = malloc (2 * sizeof(**list));
if (*list == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
(*list)[0] = strdup (s);
if ((*list)[0] == NULL) {
free (*list);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
(*list)[1] = NULL;
return 0;
}
/*
* Set the knowledge of the default realm(s) in `context'.
* If realm != NULL, that's the new default realm.
* Otherwise, the realm(s) are figured out from configuration or DNS.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_default_realm(krb5_context context,
const char *realm)
{
krb5_error_code ret = 0;
krb5_realm *realms = NULL;
if (realm == NULL) {
realms = krb5_config_get_strings (context, NULL,
"libdefaults",
"default_realm",
NULL);
if (realms == NULL)
ret = krb5_get_host_realm(context, NULL, &realms);
} else {
ret = string_to_list (context, realm, &realms);
}
if (ret)
return ret;
krb5_free_host_realm (context, context->default_realms);
context->default_realms = realms;
return 0;
}
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __store_int_h__
#define __store_int_h__
struct krb5_storage_data {
void *data;
ssize_t (*fetch)(struct krb5_storage_data*, void*, size_t);
ssize_t (*store)(struct krb5_storage_data*, const void*, size_t);
off_t (*seek)(struct krb5_storage_data*, off_t, int);
void (*free)(struct krb5_storage_data*);
krb5_flags flags;
int eof_code;
};
#endif /* __store_int_h__ */
File diff suppressed because it is too large Load Diff
+132
View File
@@ -0,0 +1,132 @@
/*
* Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include "store-int.h"
RCSID("$Id: store_emem.c,v 1.14 2004/05/25 21:43:29 lha Exp $");
typedef struct emem_storage{
unsigned char *base;
size_t size;
size_t len;
unsigned char *ptr;
}emem_storage;
static ssize_t
emem_fetch(krb5_storage *sp, void *data, size_t size)
{
emem_storage *s = (emem_storage*)sp->data;
if(s->base + s->len - s->ptr < size)
size = s->base + s->len - s->ptr;
memmove(data, s->ptr, size);
sp->seek(sp, size, SEEK_CUR);
return size;
}
static ssize_t
emem_store(krb5_storage *sp, const void *data, size_t size)
{
emem_storage *s = (emem_storage*)sp->data;
if(size > s->base + s->size - s->ptr){
void *base;
size_t sz, off;
off = s->ptr - s->base;
sz = off + size;
if (sz < 4096)
sz *= 2;
base = realloc(s->base, sz);
if(base == NULL)
return 0;
s->size = sz;
s->base = base;
s->ptr = (unsigned char*)base + off;
}
memmove(s->ptr, data, size);
sp->seek(sp, size, SEEK_CUR);
return size;
}
static off_t
emem_seek(krb5_storage *sp, off_t offset, int whence)
{
emem_storage *s = (emem_storage*)sp->data;
switch(whence){
case SEEK_SET:
if(offset > s->size)
offset = s->size;
if(offset < 0)
offset = 0;
s->ptr = s->base + offset;
if(offset > s->len)
s->len = offset;
break;
case SEEK_CUR:
sp->seek(sp,s->ptr - s->base + offset, SEEK_SET);
break;
case SEEK_END:
sp->seek(sp, s->len + offset, SEEK_SET);
break;
default:
errno = EINVAL;
return -1;
}
return s->ptr - s->base;
}
static void
emem_free(krb5_storage *sp)
{
emem_storage *s = sp->data;
memset(s->base, 0, s->len);
free(s->base);
}
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_emem(void)
{
krb5_storage *sp = malloc(sizeof(krb5_storage));
emem_storage *s = malloc(sizeof(*s));
sp->data = s;
sp->flags = 0;
sp->eof_code = HEIM_ERR_EOF;
s->size = 1024;
s->base = malloc(s->size);
s->len = 0;
s->ptr = s->base;
sp->fetch = emem_fetch;
sp->store = emem_store;
sp->seek = emem_seek;
sp->free = emem_free;
return sp;
}
+98
View File
@@ -0,0 +1,98 @@
/*
* Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include "store-int.h"
RCSID("$Id: store_fd.c,v 1.13 2006/06/30 21:23:19 lha Exp $");
typedef struct fd_storage {
int fd;
} fd_storage;
#define FD(S) (((fd_storage*)(S)->data)->fd)
static ssize_t
fd_fetch(krb5_storage * sp, void *data, size_t size)
{
return net_read(FD(sp), data, size);
}
static ssize_t
fd_store(krb5_storage * sp, const void *data, size_t size)
{
return net_write(FD(sp), data, size);
}
static off_t
fd_seek(krb5_storage * sp, off_t offset, int whence)
{
return lseek(FD(sp), offset, whence);
}
static void
fd_free(krb5_storage * sp)
{
close(FD(sp));
}
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_fd(int fd)
{
krb5_storage *sp;
fd = dup(fd);
if (fd < 0)
return NULL;
sp = malloc(sizeof(krb5_storage));
if (sp == NULL) {
close(fd);
return NULL;
}
sp->data = malloc(sizeof(fd_storage));
if (sp->data == NULL) {
close(fd);
free(sp);
return NULL;
}
sp->flags = 0;
sp->eof_code = HEIM_ERR_EOF;
FD(sp) = fd;
sp->fetch = fd_fetch;
sp->store = fd_store;
sp->seek = fd_seek;
sp->free = fd_free;
return sp;
}
+150
View File
@@ -0,0 +1,150 @@
/*
* Copyright (c) 1997 - 2000, 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include "store-int.h"
RCSID("$Id: store_mem.c,v 1.13 2006/11/07 23:02:53 lha Exp $");
typedef struct mem_storage{
unsigned char *base;
size_t size;
unsigned char *ptr;
}mem_storage;
static ssize_t
mem_fetch(krb5_storage *sp, void *data, size_t size)
{
mem_storage *s = (mem_storage*)sp->data;
if(size > s->base + s->size - s->ptr)
size = s->base + s->size - s->ptr;
memmove(data, s->ptr, size);
sp->seek(sp, size, SEEK_CUR);
return size;
}
static ssize_t
mem_store(krb5_storage *sp, const void *data, size_t size)
{
mem_storage *s = (mem_storage*)sp->data;
if(size > s->base + s->size - s->ptr)
size = s->base + s->size - s->ptr;
memmove(s->ptr, data, size);
sp->seek(sp, size, SEEK_CUR);
return size;
}
static ssize_t
mem_no_store(krb5_storage *sp, const void *data, size_t size)
{
return -1;
}
static off_t
mem_seek(krb5_storage *sp, off_t offset, int whence)
{
mem_storage *s = (mem_storage*)sp->data;
switch(whence){
case SEEK_SET:
if(offset > s->size)
offset = s->size;
if(offset < 0)
offset = 0;
s->ptr = s->base + offset;
break;
case SEEK_CUR:
return sp->seek(sp, s->ptr - s->base + offset, SEEK_SET);
case SEEK_END:
return sp->seek(sp, s->size + offset, SEEK_SET);
default:
errno = EINVAL;
return -1;
}
return s->ptr - s->base;
}
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_mem(void *buf, size_t len)
{
krb5_storage *sp = malloc(sizeof(krb5_storage));
mem_storage *s;
if(sp == NULL)
return NULL;
s = malloc(sizeof(*s));
if(s == NULL) {
free(sp);
return NULL;
}
sp->data = s;
sp->flags = 0;
sp->eof_code = HEIM_ERR_EOF;
s->base = buf;
s->size = len;
s->ptr = buf;
sp->fetch = mem_fetch;
sp->store = mem_store;
sp->seek = mem_seek;
sp->free = NULL;
return sp;
}
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_data(krb5_data *data)
{
return krb5_storage_from_mem(data->data, data->length);
}
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_readonly_mem(const void *buf, size_t len)
{
krb5_storage *sp = malloc(sizeof(krb5_storage));
mem_storage *s;
if(sp == NULL)
return NULL;
s = malloc(sizeof(*s));
if(s == NULL) {
free(sp);
return NULL;
}
sp->data = s;
sp->flags = 0;
sp->eof_code = HEIM_ERR_EOF;
s->base = rk_UNCONST(buf);
s->size = len;
s->ptr = rk_UNCONST(buf);
sp->fetch = mem_fetch;
sp->store = mem_no_store;
sp->seek = mem_seek;
sp->free = NULL;
return sp;
}
+280
View File
@@ -0,0 +1,280 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: ticket.c,v 1.15 2006/10/14 09:53:19 lha Exp $");
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_ticket(krb5_context context,
krb5_ticket *ticket)
{
free_EncTicketPart(&ticket->ticket);
krb5_free_principal(context, ticket->client);
krb5_free_principal(context, ticket->server);
free(ticket);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_ticket(krb5_context context,
const krb5_ticket *from,
krb5_ticket **to)
{
krb5_error_code ret;
krb5_ticket *tmp;
*to = NULL;
tmp = malloc(sizeof(*tmp));
if(tmp == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
free(tmp);
return ret;
}
ret = krb5_copy_principal(context, from->client, &tmp->client);
if(ret){
free_EncTicketPart(&tmp->ticket);
free(tmp);
return ret;
}
ret = krb5_copy_principal(context, from->server, &tmp->server);
if(ret){
krb5_free_principal(context, tmp->client);
free_EncTicketPart(&tmp->ticket);
free(tmp);
return ret;
}
*to = tmp;
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_ticket_get_client(krb5_context context,
const krb5_ticket *ticket,
krb5_principal *client)
{
return krb5_copy_principal(context, ticket->client, client);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_ticket_get_server(krb5_context context,
const krb5_ticket *ticket,
krb5_principal *server)
{
return krb5_copy_principal(context, ticket->server, server);
}
static int
find_type_in_ad(krb5_context context,
int type,
krb5_data *data,
krb5_boolean *found,
krb5_boolean failp,
krb5_keyblock *sessionkey,
const AuthorizationData *ad,
int level)
{
/* It is not an error if nothing in here, that is reported by *found */
/* Setting a default error causes found to be set to FALSE, on
* recursion to an second embedded authz data even if the first
* element contains the required type */
krb5_error_code ret = 0;
int i;
if (level > 9) {
krb5_set_error_string(context, "Authorization data nested deeper "
"then %d levels, stop searching", level);
ret = ENOENT; /* XXX */
goto out;
}
/*
* Only copy out the element the first time we get to it, we need
* to run over the whole authorization data fields to check if
* there are any container clases we need to care about.
*/
for (i = 0; i < ad->len; i++) {
if (!*found && ad->val[i].ad_type == type) {
ret = der_copy_octet_string(&ad->val[i].ad_data, data);
if (ret) {
krb5_set_error_string(context, "malloc - out of memory");
goto out;
}
*found = TRUE;
continue;
}
switch (ad->val[i].ad_type) {
case KRB5_AUTHDATA_IF_RELEVANT: {
AuthorizationData child;
ret = decode_AuthorizationData(ad->val[i].ad_data.data,
ad->val[i].ad_data.length,
&child,
NULL);
if (ret) {
krb5_set_error_string(context, "Failed to decode "
"IF_RELEVANT with %d", ret);
goto out;
}
ret = find_type_in_ad(context, type, data, found, 0, sessionkey,
&child, level + 1);
free_AuthorizationData(&child);
if (ret)
goto out;
break;
}
#if 0 /* XXX test */
case KRB5_AUTHDATA_KDC_ISSUED: {
AD_KDCIssued child;
ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
ad->val[i].ad_data.length,
&child,
NULL);
if (ret) {
krb5_set_error_string(context, "Failed to decode "
"AD_KDCIssued with %d", ret);
goto out;
}
if (failp) {
krb5_boolean valid;
krb5_data buf;
size_t len;
ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length,
&child.elements, &len, ret);
if (ret) {
free_AD_KDCIssued(&child);
krb5_clear_error_string(context);
goto out;
}
if(buf.length != len)
krb5_abortx(context, "internal error in ASN.1 encoder");
ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
&child.ad_checksum, &valid);
krb5_data_free(&buf);
if (ret) {
free_AD_KDCIssued(&child);
goto out;
}
if (!valid) {
krb5_clear_error_string(context);
ret = ENOENT;
free_AD_KDCIssued(&child);
goto out;
}
}
ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
&child.elements, level + 1);
free_AD_KDCIssued(&child);
if (ret)
goto out;
break;
}
#endif
case KRB5_AUTHDATA_AND_OR:
if (!failp)
break;
krb5_set_error_string(context, "Authorization data contains "
"AND-OR element that is unknown to the "
"application");
ret = ENOENT; /* XXX */
goto out;
default:
if (!failp)
break;
krb5_set_error_string(context, "Authorization data contains "
"unknown type (%d) ", ad->val[i].ad_type);
ret = ENOENT; /* XXX */
goto out;
}
}
out:
if (ret) {
if (*found) {
krb5_data_free(data);
*found = 0;
}
}
return ret;
}
int
_krb5_find_type_in_ad(krb5_context context,
int type,
krb5_data *data,
krb5_boolean *found,
krb5_keyblock *sessionkey,
const AuthorizationData *ad)
{
krb5_data_zero(data);
return find_type_in_ad(context, type, data, found, TRUE, sessionkey, ad, 0);
}
/*
* Extract the authorization data type of `type' from the
* 'ticket'. Store the field in `data'. This function is to use for
* kerberos applications.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_ticket_get_authorization_data_type(krb5_context context,
krb5_ticket *ticket,
int type,
krb5_data *data)
{
AuthorizationData *ad;
krb5_error_code ret;
krb5_boolean found = 0;
ad = ticket->ticket.authorization_data;
if (ticket->ticket.authorization_data == NULL) {
krb5_set_error_string(context, "Ticket have not authorization data");
return ENOENT; /* XXX */
}
ret = _krb5_find_type_in_ad(context, type, data, &found, &ticket->ticket.key,
ticket->ticket.authorization_data);
if (ret)
return ret;
if (!found) {
krb5_set_error_string(context, "Ticket have not authorization "
"data of type %d", type);
return ENOENT; /* XXX */
}
return 0;
}
+114
View File
@@ -0,0 +1,114 @@
/*
* Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: time.c,v 1.13 2004/10/13 17:57:11 lha Exp $");
/*
* Set the absolute time that the caller knows the kdc has so the
* kerberos library can calculate the relative diffrence beteen the
* KDC time and local system time.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_real_time (krb5_context context,
krb5_timestamp sec,
int32_t usec)
{
struct timeval tv;
gettimeofday(&tv, NULL);
context->kdc_sec_offset = sec - tv.tv_sec;
context->kdc_usec_offset = usec - tv.tv_usec;
if (context->kdc_usec_offset < 0) {
context->kdc_sec_offset--;
context->kdc_usec_offset += 1000000;
}
return 0;
}
/*
* return ``corrected'' time in `timeret'.
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_timeofday (krb5_context context,
krb5_timestamp *timeret)
{
*timeret = time(NULL) + context->kdc_sec_offset;
return 0;
}
/*
* like gettimeofday but with time correction to the KDC
*/
krb5_error_code KRB5_LIB_FUNCTION
krb5_us_timeofday (krb5_context context,
krb5_timestamp *sec,
int32_t *usec)
{
struct timeval tv;
gettimeofday (&tv, NULL);
*sec = tv.tv_sec + context->kdc_sec_offset;
*usec = tv.tv_usec; /* XXX */
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_format_time(krb5_context context, time_t t,
char *s, size_t len, krb5_boolean include_time)
{
struct tm *tm;
if(context->log_utc)
tm = gmtime (&t);
else
tm = localtime(&t);
if(tm == NULL ||
strftime(s, len, include_time ? context->time_fmt : context->date_fmt, tm) == 0)
snprintf(s, len, "%ld", (long)t);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_string_to_deltat(const char *string, krb5_deltat *deltat)
{
if((*deltat = parse_time(string, "s")) == -1)
return KRB5_DELTAT_BADFORMAT;
return 0;
}
+486
View File
@@ -0,0 +1,486 @@
/*
* Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: transited.c,v 1.18 2006/04/10 10:26:35 lha Exp $");
/* this is an attempt at one of the most horrible `compression'
schemes that has ever been invented; it's so amazingly brain-dead
that words can not describe it, and all this just to save a few
silly bytes */
struct tr_realm {
char *realm;
unsigned leading_space:1;
unsigned leading_slash:1;
unsigned trailing_dot:1;
struct tr_realm *next;
};
static void
free_realms(struct tr_realm *r)
{
struct tr_realm *p;
while(r){
p = r;
r = r->next;
free(p->realm);
free(p);
}
}
static int
make_path(krb5_context context, struct tr_realm *r,
const char *from, const char *to)
{
const char *p;
struct tr_realm *path = r->next;
struct tr_realm *tmp;
if(strlen(from) < strlen(to)){
const char *str;
str = from;
from = to;
to = str;
}
if(strcmp(from + strlen(from) - strlen(to), to) == 0){
p = from;
while(1){
p = strchr(p, '.');
if(p == NULL) {
krb5_clear_error_string (context);
return KRB5KDC_ERR_POLICY;
}
p++;
if(strcmp(p, to) == 0)
break;
tmp = calloc(1, sizeof(*tmp));
tmp->next = path;
path = tmp;
path->realm = strdup(p);
if(path->realm == NULL){
r->next = path; /* XXX */
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;;
}
}
}else if(strncmp(from, to, strlen(to)) == 0){
p = from + strlen(from);
while(1){
while(p >= from && *p != '/') p--;
if(p == from) {
r->next = path; /* XXX */
return KRB5KDC_ERR_POLICY;
}
if(strncmp(to, from, p - from) == 0)
break;
tmp = calloc(1, sizeof(*tmp));
tmp->next = path;
path = tmp;
path->realm = malloc(p - from + 1);
if(path->realm == NULL){
r->next = path; /* XXX */
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
memcpy(path->realm, from, p - from);
path->realm[p - from] = '\0';
p--;
}
} else {
krb5_clear_error_string (context);
return KRB5KDC_ERR_POLICY;
}
r->next = path;
return 0;
}
static int
make_paths(krb5_context context,
struct tr_realm *realms, const char *client_realm,
const char *server_realm)
{
struct tr_realm *r;
int ret;
const char *prev_realm = client_realm;
const char *next_realm = NULL;
for(r = realms; r; r = r->next){
/* it *might* be that you can have more than one empty
component in a row, at least that's how I interpret the
"," exception in 1510 */
if(r->realm[0] == '\0'){
while(r->next && r->next->realm[0] == '\0')
r = r->next;
if(r->next)
next_realm = r->next->realm;
else
next_realm = server_realm;
ret = make_path(context, r, prev_realm, next_realm);
if(ret){
free_realms(realms);
return ret;
}
}
prev_realm = r->realm;
}
return 0;
}
static int
expand_realms(krb5_context context,
struct tr_realm *realms, const char *client_realm)
{
struct tr_realm *r;
const char *prev_realm = NULL;
for(r = realms; r; r = r->next){
if(r->trailing_dot){
char *tmp;
size_t len;
if(prev_realm == NULL)
prev_realm = client_realm;
len = strlen(r->realm) + strlen(prev_realm) + 1;
tmp = realloc(r->realm, len);
if(tmp == NULL){
free_realms(realms);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
r->realm = tmp;
strlcat(r->realm, prev_realm, len);
}else if(r->leading_slash && !r->leading_space && prev_realm){
/* yet another exception: if you use x500-names, the
leading realm doesn't have to be "quoted" with a space */
char *tmp;
size_t len = strlen(r->realm) + strlen(prev_realm) + 1;
tmp = malloc(len);
if(tmp == NULL){
free_realms(realms);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
strlcpy(tmp, prev_realm, len);
strlcat(tmp, r->realm, len);
free(r->realm);
r->realm = tmp;
}
prev_realm = r->realm;
}
return 0;
}
static struct tr_realm *
make_realm(char *realm)
{
struct tr_realm *r;
char *p, *q;
int quote = 0;
r = calloc(1, sizeof(*r));
if(r == NULL){
free(realm);
return NULL;
}
r->realm = realm;
for(p = q = r->realm; *p; p++){
if(p == r->realm && *p == ' '){
r->leading_space = 1;
continue;
}
if(q == r->realm && *p == '/')
r->leading_slash = 1;
if(quote){
*q++ = *p;
quote = 0;
continue;
}
if(*p == '\\'){
quote = 1;
continue;
}
if(p[0] == '.' && p[1] == '\0')
r->trailing_dot = 1;
*q++ = *p;
}
*q = '\0';
return r;
}
static struct tr_realm*
append_realm(struct tr_realm *head, struct tr_realm *r)
{
struct tr_realm *p;
if(head == NULL){
r->next = NULL;
return r;
}
p = head;
while(p->next) p = p->next;
p->next = r;
return head;
}
static int
decode_realms(krb5_context context,
const char *tr, int length, struct tr_realm **realms)
{
struct tr_realm *r = NULL;
char *tmp;
int quote = 0;
const char *start = tr;
int i;
for(i = 0; i < length; i++){
if(quote){
quote = 0;
continue;
}
if(tr[i] == '\\'){
quote = 1;
continue;
}
if(tr[i] == ','){
tmp = malloc(tr + i - start + 1);
memcpy(tmp, start, tr + i - start);
tmp[tr + i - start] = '\0';
r = make_realm(tmp);
if(r == NULL){
free_realms(*realms);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
*realms = append_realm(*realms, r);
start = tr + i + 1;
}
}
tmp = malloc(tr + i - start + 1);
memcpy(tmp, start, tr + i - start);
tmp[tr + i - start] = '\0';
r = make_realm(tmp);
if(r == NULL){
free_realms(*realms);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
*realms = append_realm(*realms, r);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_domain_x500_decode(krb5_context context,
krb5_data tr, char ***realms, int *num_realms,
const char *client_realm, const char *server_realm)
{
struct tr_realm *r = NULL;
struct tr_realm *p, **q;
int ret;
if(tr.length == 0) {
*realms = NULL;
*num_realms = 0;
return 0;
}
/* split string in components */
ret = decode_realms(context, tr.data, tr.length, &r);
if(ret)
return ret;
/* apply prefix rule */
ret = expand_realms(context, r, client_realm);
if(ret)
return ret;
ret = make_paths(context, r, client_realm, server_realm);
if(ret)
return ret;
/* remove empty components and count realms */
q = &r;
*num_realms = 0;
for(p = r; p; ){
if(p->realm[0] == '\0'){
free(p->realm);
*q = p->next;
free(p);
p = *q;
}else{
q = &p->next;
p = p->next;
(*num_realms)++;
}
}
if (*num_realms < 0 || *num_realms + 1 > UINT_MAX/sizeof(**realms))
return ERANGE;
{
char **R;
R = malloc((*num_realms + 1) * sizeof(*R));
if (R == NULL)
return ENOMEM;
*realms = R;
while(r){
*R++ = r->realm;
p = r->next;
free(r);
r = p;
}
}
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_domain_x500_encode(char **realms, int num_realms, krb5_data *encoding)
{
char *s = NULL;
int len = 0;
int i;
krb5_data_zero(encoding);
if (num_realms == 0)
return 0;
for(i = 0; i < num_realms; i++){
len += strlen(realms[i]);
if(realms[i][0] == '/')
len++;
}
len += num_realms - 1;
s = malloc(len + 1);
if (s == NULL)
return ENOMEM;
*s = '\0';
for(i = 0; i < num_realms; i++){
if(i && i < num_realms - 1)
strlcat(s, ",", len + 1);
if(realms[i][0] == '/')
strlcat(s, " ", len + 1);
strlcat(s, realms[i], len + 1);
}
encoding->data = s;
encoding->length = strlen(s);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_check_transited(krb5_context context,
krb5_const_realm client_realm,
krb5_const_realm server_realm,
krb5_realm *realms,
int num_realms,
int *bad_realm)
{
char **tr_realms;
char **p;
int i;
if(num_realms == 0)
return 0;
tr_realms = krb5_config_get_strings(context, NULL,
"capaths",
client_realm,
server_realm,
NULL);
for(i = 0; i < num_realms; i++) {
for(p = tr_realms; p && *p; p++) {
if(strcmp(*p, realms[i]) == 0)
break;
}
if(p == NULL || *p == NULL) {
krb5_config_free_strings(tr_realms);
krb5_set_error_string (context, "no transit through realm %s",
realms[i]);
if(bad_realm)
*bad_realm = i;
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
}
krb5_config_free_strings(tr_realms);
return 0;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_check_transited_realms(krb5_context context,
const char *const *realms,
int num_realms,
int *bad_realm)
{
int i;
int ret = 0;
char **bad_realms = krb5_config_get_strings(context, NULL,
"libdefaults",
"transited_realms_reject",
NULL);
if(bad_realms == NULL)
return 0;
for(i = 0; i < num_realms; i++) {
char **p;
for(p = bad_realms; *p; p++)
if(strcmp(*p, realms[i]) == 0) {
krb5_set_error_string (context, "no transit through realm %s",
*p);
ret = KRB5KRB_AP_ERR_ILL_CR_TKT;
if(bad_realm)
*bad_realm = i;
break;
}
}
krb5_config_free_strings(bad_realms);
return ret;
}
#if 0
int
main(int argc, char **argv)
{
krb5_data x;
char **r;
int num, i;
x.data = argv[1];
x.length = strlen(x.data);
if(domain_expand(x, &r, &num, argv[2], argv[3]))
exit(1);
for(i = 0; i < num; i++)
printf("%s\n", r[i]);
return 0;
}
#endif
+923
View File
@@ -0,0 +1,923 @@
/*
* Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: v4_glue.c,v 1.5 2006/05/05 09:31:00 lha Exp $");
#include "krb5-v4compat.h"
/*
*
*/
#define RCHECK(r,func,label) \
do { (r) = func ; if (r) goto label; } while(0);
/* include this here, to avoid dependencies on libkrb */
static const int _tkt_lifetimes[TKTLIFENUMFIXED] = {
38400, 41055, 43894, 46929, 50174, 53643, 57352, 61318,
65558, 70091, 74937, 80119, 85658, 91581, 97914, 104684,
111922, 119661, 127935, 136781, 146239, 156350, 167161, 178720,
191077, 204289, 218415, 233517, 249664, 266926, 285383, 305116,
326213, 348769, 372885, 398668, 426234, 455705, 487215, 520904,
556921, 595430, 636601, 680618, 727680, 777995, 831789, 889303,
950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247,
1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000
};
int KRB5_LIB_FUNCTION
_krb5_krb_time_to_life(time_t start, time_t end)
{
int i;
time_t life = end - start;
if (life > MAXTKTLIFETIME || life <= 0)
return 0;
#if 0
if (krb_no_long_lifetimes)
return (life + 5*60 - 1)/(5*60);
#endif
if (end >= NEVERDATE)
return TKTLIFENOEXPIRE;
if (life < _tkt_lifetimes[0])
return (life + 5*60 - 1)/(5*60);
for (i=0; i<TKTLIFENUMFIXED; i++)
if (life <= _tkt_lifetimes[i])
return i + TKTLIFEMINFIXED;
return 0;
}
time_t KRB5_LIB_FUNCTION
_krb5_krb_life_to_time(int start, int life_)
{
unsigned char life = (unsigned char) life_;
#if 0
if (krb_no_long_lifetimes)
return start + life*5*60;
#endif
if (life == TKTLIFENOEXPIRE)
return NEVERDATE;
if (life < TKTLIFEMINFIXED)
return start + life*5*60;
if (life > TKTLIFEMAXFIXED)
return start + MAXTKTLIFETIME;
return start + _tkt_lifetimes[life - TKTLIFEMINFIXED];
}
/*
* Get the name of the krb4 credentials cache, will use `tkfile' as
* the name if that is passed in. `cc' must be free()ed by caller,
*/
static krb5_error_code
get_krb4_cc_name(const char *tkfile, char **cc)
{
*cc = NULL;
if(tkfile == NULL) {
char *path;
if(!issuid()) {
path = getenv("KRBTKFILE");
if (path)
*cc = strdup(path);
}
if(*cc == NULL)
if (asprintf(cc, "%s%u", TKT_ROOT, (unsigned)getuid()) < 0)
return errno;
} else {
*cc = strdup(tkfile);
if (*cc == NULL)
return ENOMEM;
}
return 0;
}
/*
* Write a Kerberos 4 ticket file
*/
#define KRB5_TF_LCK_RETRY_COUNT 50
#define KRB5_TF_LCK_RETRY 1
static krb5_error_code
write_v4_cc(krb5_context context, const char *tkfile,
krb5_storage *sp, int append)
{
krb5_error_code ret;
struct stat sb;
krb5_data data;
char *path;
int fd, i;
ret = get_krb4_cc_name(tkfile, &path);
if (ret) {
krb5_set_error_string(context,
"krb5_krb_tf_setup: failed getting "
"the krb4 credentials cache name");
return ret;
}
fd = open(path, O_WRONLY|O_CREAT, 0600);
if (fd < 0) {
ret = errno;
krb5_set_error_string(context,
"krb5_krb_tf_setup: error opening file %s",
path);
free(path);
return ret;
}
if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) {
krb5_set_error_string(context,
"krb5_krb_tf_setup: tktfile %s is not a file",
path);
free(path);
close(fd);
return KRB5_FCC_PERM;
}
for (i = 0; i < KRB5_TF_LCK_RETRY_COUNT; i++) {
if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
sleep(KRB5_TF_LCK_RETRY);
} else
break;
}
if (i == KRB5_TF_LCK_RETRY_COUNT) {
krb5_set_error_string(context,
"krb5_krb_tf_setup: failed to lock %s",
path);
free(path);
close(fd);
return KRB5_FCC_PERM;
}
if (!append) {
ret = ftruncate(fd, 0);
if (ret < 0) {
flock(fd, LOCK_UN);
krb5_set_error_string(context,
"krb5_krb_tf_setup: failed to truncate %s",
path);
free(path);
close(fd);
return KRB5_FCC_PERM;
}
}
ret = lseek(fd, 0L, SEEK_END);
if (ret < 0) {
ret = errno;
flock(fd, LOCK_UN);
free(path);
close(fd);
return ret;
}
krb5_storage_to_data(sp, &data);
ret = write(fd, data.data, data.length);
if (ret != data.length)
ret = KRB5_CC_IO;
krb5_free_data_contents(context, &data);
flock(fd, LOCK_UN);
free(path);
close(fd);
return 0;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_tf_setup(krb5_context context,
struct credentials *v4creds,
const char *tkfile,
int append)
{
krb5_error_code ret;
krb5_storage *sp;
sp = krb5_storage_emem();
if (sp == NULL)
return ENOMEM;
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST);
krb5_storage_set_eof_code(sp, KRB5_CC_IO);
krb5_clear_error_string(context);
if (!append) {
RCHECK(ret, krb5_store_stringz(sp, v4creds->pname), error);
RCHECK(ret, krb5_store_stringz(sp, v4creds->pinst), error);
}
/* cred */
RCHECK(ret, krb5_store_stringz(sp, v4creds->service), error);
RCHECK(ret, krb5_store_stringz(sp, v4creds->instance), error);
RCHECK(ret, krb5_store_stringz(sp, v4creds->realm), error);
ret = krb5_storage_write(sp, v4creds->session, 8);
if (ret != 8) {
ret = KRB5_CC_IO;
goto error;
}
RCHECK(ret, krb5_store_int32(sp, v4creds->lifetime), error);
RCHECK(ret, krb5_store_int32(sp, v4creds->kvno), error);
RCHECK(ret, krb5_store_int32(sp, v4creds->ticket_st.length), error);
ret = krb5_storage_write(sp, v4creds->ticket_st.dat,
v4creds->ticket_st.length);
if (ret != v4creds->ticket_st.length) {
ret = KRB5_CC_IO;
goto error;
}
RCHECK(ret, krb5_store_int32(sp, v4creds->issue_date), error);
ret = write_v4_cc(context, tkfile, sp, append);
error:
krb5_storage_free(sp);
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_dest_tkt(krb5_context context, const char *tkfile)
{
krb5_error_code ret;
char *path;
ret = get_krb4_cc_name(tkfile, &path);
if (ret) {
krb5_set_error_string(context,
"krb5_krb_tf_setup: failed getting "
"the krb4 credentials cache name");
return ret;
}
if (unlink(path) < 0) {
ret = errno;
krb5_set_error_string(context,
"krb5_krb_dest_tkt failed removing the cache "
"with error %s", strerror(ret));
}
free(path);
return ret;
}
/*
*
*/
static krb5_error_code
decrypt_etext(krb5_context context, const krb5_keyblock *key,
const krb5_data *cdata, krb5_data *data)
{
krb5_error_code ret;
krb5_crypto crypto;
ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto);
if (ret)
return ret;
ret = krb5_decrypt(context, crypto, 0, cdata->data, cdata->length, data);
krb5_crypto_destroy(context, crypto);
return ret;
}
/*
*
*/
static const char eightzeros[8] = "\x00\x00\x00\x00\x00\x00\x00\x00";
static krb5_error_code
storage_to_etext(krb5_context context,
krb5_storage *sp,
const krb5_keyblock *key,
krb5_data *enc_data)
{
krb5_error_code ret;
krb5_crypto crypto;
krb5_ssize_t size;
krb5_data data;
/* multiple of eight bytes */
size = krb5_storage_seek(sp, 0, SEEK_END);
if (size < 0)
return EINVAL;
size = 8 - (size & 7);
ret = krb5_storage_write(sp, eightzeros, size);
if (ret != size)
return EINVAL;
ret = krb5_storage_to_data(sp, &data);
if (ret)
return ret;
ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto);
if (ret) {
krb5_data_free(&data);
return ret;
}
ret = krb5_encrypt(context, crypto, 0, data.data, data.length, enc_data);
krb5_data_free(&data);
krb5_crypto_destroy(context, crypto);
return ret;
}
/*
*
*/
static krb5_error_code
put_nir(krb5_storage *sp, const char *name,
const char *instance, const char *realm)
{
krb5_error_code ret;
RCHECK(ret, krb5_store_stringz(sp, name), error);
RCHECK(ret, krb5_store_stringz(sp, instance), error);
if (realm) {
RCHECK(ret, krb5_store_stringz(sp, realm), error);
}
error:
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_create_ticket(krb5_context context,
unsigned char flags,
const char *pname,
const char *pinstance,
const char *prealm,
int32_t paddress,
const krb5_keyblock *session,
int16_t life,
int32_t life_sec,
const char *sname,
const char *sinstance,
const krb5_keyblock *key,
krb5_data *enc_data)
{
krb5_error_code ret;
krb5_storage *sp;
krb5_data_zero(enc_data);
sp = krb5_storage_emem();
if (sp == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
RCHECK(ret, krb5_store_int8(sp, flags), error);
RCHECK(ret, put_nir(sp, pname, pinstance, prealm), error);
RCHECK(ret, krb5_store_int32(sp, ntohl(paddress)), error);
/* session key */
ret = krb5_storage_write(sp,
session->keyvalue.data,
session->keyvalue.length);
if (ret != session->keyvalue.length) {
ret = EINVAL;
goto error;
}
RCHECK(ret, krb5_store_int8(sp, life), error);
RCHECK(ret, krb5_store_int32(sp, life_sec), error);
RCHECK(ret, put_nir(sp, sname, sinstance, NULL), error);
ret = storage_to_etext(context, sp, key, enc_data);
error:
krb5_storage_free(sp);
if (ret)
krb5_set_error_string(context, "Failed to encode kerberos 4 ticket");
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_create_ciph(krb5_context context,
const krb5_keyblock *session,
const char *service,
const char *instance,
const char *realm,
uint32_t life,
unsigned char kvno,
const krb5_data *ticket,
uint32_t kdc_time,
const krb5_keyblock *key,
krb5_data *enc_data)
{
krb5_error_code ret;
krb5_storage *sp;
krb5_data_zero(enc_data);
sp = krb5_storage_emem();
if (sp == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
/* session key */
ret = krb5_storage_write(sp,
session->keyvalue.data,
session->keyvalue.length);
if (ret != session->keyvalue.length) {
ret = EINVAL;
goto error;
}
RCHECK(ret, put_nir(sp, service, instance, realm), error);
RCHECK(ret, krb5_store_int8(sp, life), error);
RCHECK(ret, krb5_store_int8(sp, kvno), error);
RCHECK(ret, krb5_store_int8(sp, ticket->length), error);
ret = krb5_storage_write(sp, ticket->data, ticket->length);
if (ret != ticket->length) {
ret = EINVAL;
goto error;
}
RCHECK(ret, krb5_store_int32(sp, kdc_time), error);
ret = storage_to_etext(context, sp, key, enc_data);
error:
krb5_storage_free(sp);
if (ret)
krb5_set_error_string(context, "Failed to encode kerberos 4 ticket");
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_create_auth_reply(krb5_context context,
const char *pname,
const char *pinst,
const char *prealm,
int32_t time_ws,
int n,
uint32_t x_date,
unsigned char kvno,
const krb5_data *cipher,
krb5_data *data)
{
krb5_error_code ret;
krb5_storage *sp;
krb5_data_zero(data);
sp = krb5_storage_emem();
if (sp == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error);
RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_KDC_REPLY), error);
RCHECK(ret, put_nir(sp, pname, pinst, prealm), error);
RCHECK(ret, krb5_store_int32(sp, time_ws), error);
RCHECK(ret, krb5_store_int8(sp, n), error);
RCHECK(ret, krb5_store_int32(sp, x_date), error);
RCHECK(ret, krb5_store_int8(sp, kvno), error);
RCHECK(ret, krb5_store_int16(sp, cipher->length), error);
ret = krb5_storage_write(sp, cipher->data, cipher->length);
if (ret != cipher->length) {
ret = EINVAL;
goto error;
}
ret = krb5_storage_to_data(sp, data);
error:
krb5_storage_free(sp);
if (ret)
krb5_set_error_string(context, "Failed to encode kerberos 4 ticket");
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_cr_err_reply(krb5_context context,
const char *name,
const char *inst,
const char *realm,
uint32_t time_ws,
uint32_t e,
const char *e_string,
krb5_data *data)
{
krb5_error_code ret;
krb5_storage *sp;
krb5_data_zero(data);
if (name == NULL) name = "";
if (inst == NULL) inst = "";
if (realm == NULL) realm = "";
if (e_string == NULL) e_string = "";
sp = krb5_storage_emem();
if (sp == NULL) {
krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error);
RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error);
RCHECK(ret, put_nir(sp, name, inst, realm), error);
RCHECK(ret, krb5_store_int32(sp, time_ws), error);
RCHECK(ret, krb5_store_int32(sp, e), error);
RCHECK(ret, krb5_store_stringz(sp, e_string), error);
ret = krb5_storage_to_data(sp, data);
error:
krb5_storage_free(sp);
if (ret)
krb5_set_error_string(context, "Failed to encode kerberos 4 error");
return 0;
}
static krb5_error_code
get_v4_stringz(krb5_storage *sp, char **str, size_t max_len)
{
krb5_error_code ret;
ret = krb5_ret_stringz(sp, str);
if (ret)
return ret;
if (strlen(*str) > max_len) {
free(*str);
*str = NULL;
return EINVAL;
}
return 0;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_decomp_ticket(krb5_context context,
const krb5_data *enc_ticket,
const krb5_keyblock *key,
const char *local_realm,
char **sname,
char **sinstance,
struct _krb5_krb_auth_data *ad)
{
krb5_error_code ret;
krb5_ssize_t size;
krb5_storage *sp = NULL;
krb5_data ticket;
unsigned char des_key[8];
memset(ad, 0, sizeof(*ad));
krb5_data_zero(&ticket);
*sname = NULL;
*sinstance = NULL;
RCHECK(ret, decrypt_etext(context, key, enc_ticket, &ticket), error);
sp = krb5_storage_from_data(&ticket);
if (sp == NULL) {
krb5_data_free(&ticket);
krb5_set_error_string(context, "alloc: out of memory");
return ENOMEM;
}
krb5_storage_set_eof_code(sp, EINVAL); /* XXX */
RCHECK(ret, krb5_ret_int8(sp, &ad->k_flags), error);
RCHECK(ret, get_v4_stringz(sp, &ad->pname, ANAME_SZ), error);
RCHECK(ret, get_v4_stringz(sp, &ad->pinst, INST_SZ), error);
RCHECK(ret, get_v4_stringz(sp, &ad->prealm, REALM_SZ), error);
RCHECK(ret, krb5_ret_uint32(sp, &ad->address), error);
size = krb5_storage_read(sp, des_key, sizeof(des_key));
if (size != sizeof(des_key)) {
ret = EINVAL; /* XXX */
goto error;
}
RCHECK(ret, krb5_ret_uint8(sp, &ad->life), error);
if (ad->k_flags & 1)
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
else
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
RCHECK(ret, krb5_ret_uint32(sp, &ad->time_sec), error);
RCHECK(ret, get_v4_stringz(sp, sname, ANAME_SZ), error);
RCHECK(ret, get_v4_stringz(sp, sinstance, INST_SZ), error);
ret = krb5_keyblock_init(context, ETYPE_DES_PCBC_NONE,
des_key, sizeof(des_key), &ad->session);
if (ret)
goto error;
if (strlen(ad->prealm) == 0) {
free(ad->prealm);
ad->prealm = strdup(local_realm);
if (ad->prealm == NULL) {
ret = ENOMEM;
goto error;
}
}
error:
memset(des_key, 0, sizeof(des_key));
if (sp)
krb5_storage_free(sp);
krb5_data_free(&ticket);
if (ret) {
if (*sname) {
free(*sname);
*sname = NULL;
}
if (*sinstance) {
free(*sinstance);
*sinstance = NULL;
}
_krb5_krb_free_auth_data(context, ad);
krb5_set_error_string(context, "Failed to decode v4 ticket");
}
return ret;
}
/*
*
*/
krb5_error_code KRB5_LIB_FUNCTION
_krb5_krb_rd_req(krb5_context context,
krb5_data *authent,
const char *service,
const char *instance,
const char *local_realm,
int32_t from_addr,
const krb5_keyblock *key,
struct _krb5_krb_auth_data *ad)
{
krb5_error_code ret;
krb5_storage *sp;
krb5_data ticket, eaut, aut;
krb5_ssize_t size;
int little_endian;
int8_t pvno;
int8_t type;
int8_t s_kvno;
uint8_t ticket_length;
uint8_t eaut_length;
uint8_t time_5ms;
char *realm = NULL;
char *sname = NULL;
char *sinstance = NULL;
char *r_realm = NULL;
char *r_name = NULL;
char *r_instance = NULL;
uint32_t r_time_sec; /* Coarse time from authenticator */
unsigned long delta_t; /* Time in authenticator - local time */
long tkt_age; /* Age of ticket */
struct timeval tv;
krb5_data_zero(&ticket);
krb5_data_zero(&eaut);
krb5_data_zero(&aut);
sp = krb5_storage_from_data(authent);
if (sp == NULL) {
krb5_set_error_string(context, "alloc: out of memory");
return ENOMEM;
}
krb5_storage_set_eof_code(sp, EINVAL); /* XXX */
ret = krb5_ret_int8(sp, &pvno);
if (ret)
goto error;
if (pvno != KRB_PROT_VERSION) {
ret = EINVAL; /* XXX */
goto error;
}
ret = krb5_ret_int8(sp, &type);
if (ret)
goto error;
little_endian = type & 1;
type &= ~1;
if(type != AUTH_MSG_APPL_REQUEST && type != AUTH_MSG_APPL_REQUEST_MUTUAL) {
ret = EINVAL; /* RD_AP_MSG_TYPE */
goto error;
}
RCHECK(ret, krb5_ret_int8(sp, &s_kvno), error);
RCHECK(ret, get_v4_stringz(sp, &realm, REALM_SZ), error);
RCHECK(ret, krb5_ret_uint8(sp, &ticket_length), error);
RCHECK(ret, krb5_ret_uint8(sp, &eaut_length), error);
RCHECK(ret, krb5_data_alloc(&ticket, ticket_length), error);
size = krb5_storage_read(sp, ticket.data, ticket.length);
if (size != ticket.length) {
ret = EINVAL;
goto error;
}
/* Decrypt and take apart ticket */
ret = _krb5_krb_decomp_ticket(context, &ticket, key, local_realm,
&sname, &sinstance, ad);
if (ret)
goto error;
RCHECK(ret, krb5_data_alloc(&eaut, eaut_length), error);
size = krb5_storage_read(sp, eaut.data, eaut.length);
if (size != eaut.length) {
ret = EINVAL;
goto error;
}
krb5_storage_free(sp);
sp = NULL;
ret = decrypt_etext(context, &ad->session, &eaut, &aut);
if (ret)
goto error;
sp = krb5_storage_from_data(&aut);
if (sp == NULL) {
krb5_set_error_string(context, "alloc: out of memory");
ret = ENOMEM;
goto error;
}
if (little_endian)
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
else
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
RCHECK(ret, get_v4_stringz(sp, &r_name, ANAME_SZ), error);
RCHECK(ret, get_v4_stringz(sp, &r_instance, INST_SZ), error);
RCHECK(ret, get_v4_stringz(sp, &r_realm, REALM_SZ), error);
RCHECK(ret, krb5_ret_uint32(sp, &ad->checksum), error);
RCHECK(ret, krb5_ret_uint8(sp, &time_5ms), error);
RCHECK(ret, krb5_ret_uint32(sp, &r_time_sec), error);
if (strcmp(ad->pname, r_name) != 0 ||
strcmp(ad->pinst, r_instance) != 0 ||
strcmp(ad->prealm, r_realm) != 0) {
ret = EINVAL; /* RD_AP_INCON */
goto error;
}
if (from_addr && from_addr != ad->address) {
ret = EINVAL; /* RD_AP_BADD */
goto error;
}
gettimeofday(&tv, NULL);
delta_t = abs((int)(tv.tv_sec - r_time_sec));
if (delta_t > CLOCK_SKEW) {
ret = EINVAL; /* RD_AP_TIME */
goto error;
}
/* Now check for expiration of ticket */
tkt_age = tv.tv_sec - ad->time_sec;
if ((tkt_age < 0) && (-tkt_age > CLOCK_SKEW)) {
ret = EINVAL; /* RD_AP_NYV */
goto error;
}
if (tv.tv_sec > _krb5_krb_life_to_time(ad->time_sec, ad->life)) {
ret = EINVAL; /* RD_AP_EXP */
goto error;
}
ret = 0;
error:
krb5_data_free(&ticket);
krb5_data_free(&eaut);
krb5_data_free(&aut);
if (realm)
free(realm);
if (sname)
free(sname);
if (sinstance)
free(sinstance);
if (r_name)
free(r_name);
if (r_instance)
free(r_instance);
if (r_realm)
free(r_realm);
if (sp)
krb5_storage_free(sp);
if (ret)
krb5_clear_error_string(context);
return ret;
}
/*
*
*/
void KRB5_LIB_FUNCTION
_krb5_krb_free_auth_data(krb5_context context, struct _krb5_krb_auth_data *ad)
{
if (ad->pname)
free(ad->pname);
if (ad->pinst)
free(ad->pinst);
if (ad->prealm)
free(ad->prealm);
krb5_free_keyblock_contents(context, &ad->session);
memset(ad, 0, sizeof(*ad));
}
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (c) 1997 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
RCSID("$Id: version.c,v 1.3 1999/12/02 17:05:13 joda Exp $");
/* this is just to get a version stamp in the library file */
#define heimdal_version __heimdal_version
#define heimdal_long_version __heimdal_long_version
#include "version.h"
+205
View File
@@ -0,0 +1,205 @@
/*
* Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "krb5_locl.h"
#include <err.h>
RCSID("$Id: warn.c,v 1.15 2004/05/25 21:46:26 lha Exp $");
static krb5_error_code _warnerr(krb5_context context, int do_errtext,
krb5_error_code code, int level, const char *fmt, va_list ap)
__attribute__((__format__(__printf__, 5, 0)));
static krb5_error_code
_warnerr(krb5_context context, int do_errtext,
krb5_error_code code, int level, const char *fmt, va_list ap)
{
char xfmt[7] = "";
const char *args[2], **arg;
char *msg = NULL;
char *err_str = NULL;
args[0] = args[1] = NULL;
arg = args;
if(fmt){
strlcat(xfmt, "%s", sizeof(xfmt));
if(do_errtext)
strlcat(xfmt, ": ", sizeof(xfmt));
vasprintf(&msg, fmt, ap);
if(msg == NULL)
return ENOMEM;
*arg++ = msg;
}
if(context && do_errtext){
const char *err_msg;
strlcat(xfmt, "%s", sizeof(xfmt));
err_str = krb5_get_error_string(context);
if (err_str != NULL) {
*arg++ = err_str;
} else {
err_msg = krb5_get_err_text(context, code);
if (err_msg)
*arg++ = err_msg;
else
*arg++ = "<unknown error>";
}
}
if(context && context->warn_dest)
krb5_log(context, context->warn_dest, level, xfmt, args[0], args[1]);
else
warnx(xfmt, args[0], args[1]);
free(msg);
free(err_str);
return 0;
}
#define FUNC(ETEXT, CODE, LEVEL) \
krb5_error_code ret; \
va_list ap; \
va_start(ap, fmt); \
ret = _warnerr(context, ETEXT, CODE, LEVEL, fmt, ap); \
va_end(ap);
#undef __attribute__
#define __attribute__(X)
krb5_error_code KRB5_LIB_FUNCTION
krb5_vwarn(krb5_context context, krb5_error_code code,
const char *fmt, va_list ap)
__attribute__ ((format (printf, 3, 0)))
{
return _warnerr(context, 1, code, 1, fmt, ap);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...)
__attribute__ ((format (printf, 3, 4)))
{
FUNC(1, code, 1);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_vwarnx(krb5_context context, const char *fmt, va_list ap)
__attribute__ ((format (printf, 2, 0)))
{
return _warnerr(context, 0, 0, 1, fmt, ap);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_warnx(krb5_context context, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)))
{
FUNC(0, 0, 1);
return ret;
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_verr(krb5_context context, int eval, krb5_error_code code,
const char *fmt, va_list ap)
__attribute__ ((noreturn, format (printf, 4, 0)))
{
_warnerr(context, 1, code, 0, fmt, ap);
exit(eval);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_err(krb5_context context, int eval, krb5_error_code code,
const char *fmt, ...)
__attribute__ ((noreturn, format (printf, 4, 5)))
{
FUNC(1, code, 0);
exit(eval);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap)
__attribute__ ((noreturn, format (printf, 3, 0)))
{
_warnerr(context, 0, 0, 0, fmt, ap);
exit(eval);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_errx(krb5_context context, int eval, const char *fmt, ...)
__attribute__ ((noreturn, format (printf, 3, 4)))
{
FUNC(0, 0, 0);
exit(eval);
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_vabort(krb5_context context, krb5_error_code code,
const char *fmt, va_list ap)
__attribute__ ((noreturn, format (printf, 3, 0)))
{
_warnerr(context, 1, code, 0, fmt, ap);
abort();
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_abort(krb5_context context, krb5_error_code code, const char *fmt, ...)
__attribute__ ((noreturn, format (printf, 3, 4)))
{
FUNC(1, code, 0);
abort();
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_vabortx(krb5_context context, const char *fmt, va_list ap)
__attribute__ ((noreturn, format (printf, 2, 0)))
{
_warnerr(context, 0, 0, 0, fmt, ap);
abort();
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_abortx(krb5_context context, const char *fmt, ...)
__attribute__ ((noreturn, format (printf, 2, 3)))
{
FUNC(0, 0, 0);
abort();
}
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac)
{
context->warn_dest = fac;
return 0;
}