wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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, ©);
|
||||
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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Executable
+175
@@ -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 */
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
@@ -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 */
|
||||
};
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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__ */
|
||||
@@ -0,0 +1,988 @@
|
||||
/*
|
||||
* Copyright (c) 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"
|
||||
#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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
Executable
+335
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Executable
+1903
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user