remove krb4 support

This commit is contained in:
Love Hornquist Astrand
2010-11-20 14:38:21 -08:00
parent aa750c33d1
commit fae3d127a2
7 changed files with 0 additions and 1909 deletions

View File

@@ -1,144 +0,0 @@
/*
* Copyright (c) 2000 - 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 "hprop.h"
#ifdef KRB4
static time_t
time_parse(const char *cp)
{
char wbuf[5];
struct tm tp;
int local;
memset(&tp, 0, sizeof(tp)); /* clear out the struct */
/* new format is YYYYMMDDHHMM UTC,
old format is YYMMDDHHMM local time */
if (strlen(cp) > 10) { /* new format */
strlcpy(wbuf, cp, sizeof(wbuf));
tp.tm_year = atoi(wbuf) - 1900;
cp += 4;
local = 0;
} else {
wbuf[0] = *cp++;
wbuf[1] = *cp++;
wbuf[2] = '\0';
tp.tm_year = atoi(wbuf);
if(tp.tm_year < 38)
tp.tm_year += 100;
local = 1;
}
wbuf[0] = *cp++;
wbuf[1] = *cp++;
wbuf[2] = 0;
tp.tm_mon = atoi(wbuf) - 1;
wbuf[0] = *cp++;
wbuf[1] = *cp++;
tp.tm_mday = atoi(wbuf);
wbuf[0] = *cp++;
wbuf[1] = *cp++;
tp.tm_hour = atoi(wbuf);
wbuf[0] = *cp++;
wbuf[1] = *cp++;
tp.tm_min = atoi(wbuf);
return(tm2time(tp, local));
}
/* convert a version 4 dump file */
int
v4_prop_dump(void *arg, const char *file)
{
char buf [1024];
FILE *f;
int lineno = 0;
f = fopen(file, "r");
if(f == NULL)
return errno;
while(fgets(buf, sizeof(buf), f)) {
int ret;
unsigned long key[2]; /* yes, long */
char exp_date[64], mod_date[64];
struct v4_principal pr;
int attributes;
memset(&pr, 0, sizeof(pr));
errno = 0;
lineno++;
ret = sscanf(buf, "%63s %63s %d %d %d %d %lx %lx %63s %63s %63s %63s",
pr.name, pr.instance,
&pr.max_life, &pr.mkvno, &pr.kvno,
&attributes,
&key[0], &key[1],
exp_date, mod_date,
pr.mod_name, pr.mod_instance);
if(ret != 12){
warnx("Line %d malformed (ignored)", lineno);
continue;
}
if(attributes != 0) {
warnx("Line %d (%s.%s) has non-zero attributes - skipping",
lineno, pr.name, pr.instance);
continue;
}
pr.key[0] = (key[0] >> 24) & 0xff;
pr.key[1] = (key[0] >> 16) & 0xff;
pr.key[2] = (key[0] >> 8) & 0xff;
pr.key[3] = (key[0] >> 0) & 0xff;
pr.key[4] = (key[1] >> 24) & 0xff;
pr.key[5] = (key[1] >> 16) & 0xff;
pr.key[6] = (key[1] >> 8) & 0xff;
pr.key[7] = (key[1] >> 0) & 0xff;
pr.exp_date = time_parse(exp_date);
pr.mod_date = time_parse(mod_date);
if (pr.instance[0] == '*')
pr.instance[0] = '\0';
if (pr.mod_name[0] == '*')
pr.mod_name[0] = '\0';
if (pr.mod_instance[0] == '*')
pr.mod_instance[0] = '\0';
v4_prop(arg, &pr);
memset(&pr, 0, sizeof(pr));
}
fclose(f);
return 0;
}
#endif /* KRB4 */

View File

@@ -24,7 +24,6 @@ TESTS = \
aes-test \
derived-key-test \
n-fold-test \
name-45-test \
parse-name-test \
store-test \
string-to-key-test \
@@ -220,7 +219,6 @@ dist_libkrb5_la_SOURCES = \
ticket.c \
time.c \
transited.c \
v4_glue.c \
verify_init.c \
verify_user.c \
version.c \

View File

@@ -376,67 +376,6 @@ krb5_get_in_tkt_with_keytab (krb5_context context,
ret_as_reply);
}
#ifdef KRB4
static krb5_boolean
convert_func(krb5_context conxtext, void *funcctx, krb5_principal principal)
{
krb5_boolean (*func)(krb5_context, krb5_principal) = funcctx;
return (*func)(conxtext, principal);
}
/**
* Deprecated: kerberos 4 is dead, let it die.
*
* @ingroup krb5_deprecated
*/
KRB5_DEPRECATED
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_425_conv_principal_ext(krb5_context context,
const char *name,
const char *instance,
const char *realm,
krb5_boolean (*func)(krb5_context, krb5_principal),
krb5_boolean resolve,
krb5_principal *principal)
{
return krb5_425_conv_principal_ext2(context,
name,
instance,
realm,
func ? convert_func : NULL,
func,
resolve,
principal);
}
/**
* Deprecated: kerberos 4 is dead, let it die.
*
* @ingroup krb5_deprecated
*/
KRB5_DEPRECATED
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_425_conv_principal(krb5_context context,
const char *name,
const char *instance,
const char *realm,
krb5_principal *princ)
{
krb5_boolean resolve = krb5_config_get_bool(context,
NULL,
"libdefaults",
"v4_instance_resolve",
NULL);
return krb5_425_conv_principal_ext(context, name, instance, realm,
NULL, resolve, princ);
}
#endif
/**
* Generate a new ccache of type `ops' in `id'.
*

View File

@@ -1,302 +0,0 @@
/*
* Copyright (c) 2002 - 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 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. */
#define KRB5_DEPRECATED
#include "krb5_locl.h"
#include <err.h>
#ifdef KRB4
enum { MAX_COMPONENTS = 3 };
static struct testcase {
const char *v4_name;
const char *v4_inst;
const char *v4_realm;
krb5_realm v5_realm;
unsigned ncomponents;
char *comp_val[MAX_COMPONENTS];
const char *config_file;
krb5_error_code ret; /* expected error code from 524 */
krb5_error_code ret2; /* expected error code from 425 */
} tests[] = {
{"", "", "", "", 1, {""}, NULL, 0, 0},
{"a", "", "", "", 1, {"a"}, NULL, 0, 0},
{"a", "b", "", "", 2, {"a", "b"}, NULL, 0, 0},
{"a", "b", "c", "c", 2, {"a", "b"}, NULL, 0, 0},
{"krbtgt", "FOO.SE", "FOO.SE", "FOO.SE", 2,
{"krbtgt", "FOO.SE"}, NULL, 0, 0},
{"foo", "bar2", "BAZ", "BAZ", 2,
{"foo", "bar2"}, NULL, 0, 0},
{"foo", "bar2", "BAZ", "BAZ", 2,
{"foo", "bar2"},
"[libdefaults]\n"
" v4_name_convert = {\n"
" host = {\n"
" foo = foo5\n"
" }\n"
"}\n",
HEIM_ERR_V4_PRINC_NO_CONV, 0},
{"foo", "bar2", "BAZ", "BAZ", 2,
{"foo5", "bar2.baz"},
"[realms]\n"
" BAZ = {\n"
" v4_name_convert = {\n"
" host = {\n"
" foo = foo5\n"
" }\n"
" }\n"
" v4_instance_convert = {\n"
" bar2 = bar2.baz\n"
" }\n"
" }\n",
0, 0},
{"rcmd", "foo", "realm", "realm", 2, {"host", "foo"}, NULL,
HEIM_ERR_V4_PRINC_NO_CONV, 0},
{"rcmd", "foo", "realm", "realm", 2, {"host", "foo.realm"},
"[realms]\n"
" realm = {\n"
" v4_instance_convert = {\n"
" foo = foo.realm\n"
" }\n"
" }\n",
0, 0},
{"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2,
{"pop", "mail0.nada.kth.se"}, "", HEIM_ERR_V4_PRINC_NO_CONV, 0},
{"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2,
{"pop", "mail0.nada.kth.se"},
"[realms]\n"
" NADA.KTH.SE = {\n"
" default_domain = nada.kth.se\n"
" }\n",
0, 0},
{"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2,
{"pop", "mail0.nada.kth.se"},
"[libdefaults]\n"
" v4_instance_resolve = true\n",
HEIM_ERR_V4_PRINC_NO_CONV, 0},
{"rcmd", "hokkigai", "NADA.KTH.SE", "NADA.KTH.SE", 2,
{"host", "hokkigai.pdc.kth.se"}, "", HEIM_ERR_V4_PRINC_NO_CONV, 0},
{"rcmd", "hokkigai", "NADA.KTH.SE", "NADA.KTH.SE", 2,
{"host", "hokkigai.pdc.kth.se"},
"[libdefaults]\n"
" v4_instance_resolve = true\n"
"[realms]\n"
" NADA.KTH.SE = {\n"
" v4_name_convert = {\n"
" host = {\n"
" rcmd = host\n"
" }\n"
" }\n"
" default_domain = pdc.kth.se\n"
" }\n",
0, 0},
{"0123456789012345678901234567890123456789",
"0123456789012345678901234567890123456789",
"0123456789012345678901234567890123456789",
"0123456789012345678901234567890123456789",
2, {"0123456789012345678901234567890123456789",
"0123456789012345678901234567890123456789"}, NULL,
0, KRB5_PARSE_MALFORMED},
{"012345678901234567890123456789012345678",
"012345678901234567890123456789012345678",
"012345678901234567890123456789012345678",
"012345678901234567890123456789012345678",
2, {"012345678901234567890123456789012345678",
"012345678901234567890123456789012345678"}, NULL,
0, 0},
{NULL, NULL, NULL, NULL, 0, {NULL}, NULL, 0}
};
int
main(int argc, char **argv)
{
struct testcase *t;
krb5_context context;
krb5_error_code ret;
char hostname[1024];
int val = 0;
setprogname(argv[0]);
gethostname(hostname, sizeof(hostname));
if (!(strstr(hostname, "kth.se") != NULL || strstr(hostname, "su.se") != NULL))
return 0;
for (t = tests; t->v4_name; ++t) {
krb5_principal princ;
int i;
char name[40], inst[40], realm[40];
char printable_princ[256];
ret = krb5_init_context (&context);
if (ret)
errx (1, "krb5_init_context failed: %d", ret);
if (t->config_file != NULL) {
char template[] = "/tmp/krb5-conf-XXXXXX";
int fd = mkstemp(template);
char *files[2];
if (fd < 0)
krb5_err (context, 1, errno, "mkstemp %s", template);
if (write (fd, t->config_file, strlen(t->config_file))
!= strlen(t->config_file))
krb5_err (context, 1, errno, "write %s", template);
close (fd);
files[0] = template;
files[1] = NULL;
ret = krb5_set_config_files (context, files);
unlink (template);
if (ret)
krb5_err (context, 1, ret, "krb5_set_config_files");
}
ret = krb5_425_conv_principal (context,
t->v4_name,
t->v4_inst,
t->v4_realm,
&princ);
if (ret) {
if (ret != t->ret) {
krb5_warn (context, ret,
"krb5_425_conv_principal %s.%s@%s",
t->v4_name, t->v4_inst, t->v4_realm);
val = 1;
}
} else {
if (t->ret) {
char *s;
krb5_unparse_name(context, princ, &s);
krb5_warnx (context,
"krb5_425_conv_principal %s.%s@%s "
"passed unexpected: %s",
t->v4_name, t->v4_inst, t->v4_realm, s);
free(s);
val = 1;
krb5_free_context(context);
continue;
}
}
if (ret) {
krb5_free_context(context);
continue;
}
if (strcmp (t->v5_realm, princ->realm) != 0) {
printf ("wrong realm (\"%s\" should be \"%s\")"
" for \"%s.%s@%s\"\n",
princ->realm, t->v5_realm,
t->v4_name,
t->v4_inst,
t->v4_realm);
val = 1;
}
if (t->ncomponents != princ->name.name_string.len) {
printf ("wrong number of components (%u should be %u)"
" for \"%s.%s@%s\"\n",
princ->name.name_string.len, t->ncomponents,
t->v4_name,
t->v4_inst,
t->v4_realm);
val = 1;
} else {
for (i = 0; i < t->ncomponents; ++i) {
if (strcmp(t->comp_val[i],
princ->name.name_string.val[i]) != 0) {
printf ("bad component %d (\"%s\" should be \"%s\")"
" for \"%s.%s@%s\"\n",
i,
princ->name.name_string.val[i],
t->comp_val[i],
t->v4_name,
t->v4_inst,
t->v4_realm);
val = 1;
}
}
}
ret = krb5_524_conv_principal (context, princ,
name, inst, realm);
if (krb5_unparse_name_fixed(context, princ,
printable_princ, sizeof(printable_princ)))
strlcpy(printable_princ, "unknown principal",
sizeof(printable_princ));
if (ret) {
if (ret != t->ret2) {
krb5_warn (context, ret,
"krb5_524_conv_principal %s", printable_princ);
val = 1;
}
} else {
if (t->ret2) {
krb5_warnx (context,
"krb5_524_conv_principal %s "
"passed unexpected", printable_princ);
val = 1;
krb5_free_context(context);
continue;
}
}
if (ret) {
krb5_free_principal (context, princ);
krb5_free_context(context);
continue;
}
krb5_free_principal (context, princ);
krb5_free_context(context);
}
return val;
}
#else /* stub for !KRB4 */
int main(int argc, char *argv[]) {
return 77;
}
#endif

View File

@@ -1013,437 +1013,6 @@ krb5_principal_match(krb5_context context,
return TRUE;
}
#if defined(KRB4) || !defined(HEIMDAL_SMALLER)
static struct v4_name_convert {
const char *from;
const char *to;
} default_v4_name_convert[] = {
{ "ftp", "ftp" },
{ "hprop", "hprop" },
{ "pop", "pop" },
{ "imap", "imap" },
{ "rcmd", "host" },
{ "smtp", "smtp" },
{ NULL, NULL }
};
#endif
#ifdef KRB4
/*
* return the converted instance name of `name' in `realm'.
* look in the configuration file and then in the default set above.
* return NULL if no conversion is appropriate.
*/
static const char*
get_name_conversion(krb5_context context, const char *realm, const char *name)
{
struct v4_name_convert *q;
const char *p;
p = krb5_config_get_string(context, NULL, "realms", realm,
"v4_name_convert", "host", name, NULL);
if(p == NULL)
p = krb5_config_get_string(context, NULL, "libdefaults",
"v4_name_convert", "host", name, NULL);
if(p)
return p;
/* XXX should be possible to override default list */
p = krb5_config_get_string(context, NULL,
"realms",
realm,
"v4_name_convert",
"plain",
name,
NULL);
if(p)
return NULL;
p = krb5_config_get_string(context, NULL,
"libdefaults",
"v4_name_convert",
"plain",
name,
NULL);
if(p)
return NULL;
for(q = default_v4_name_convert; q->from; q++)
if(strcmp(q->from, name) == 0)
return q->to;
return NULL;
}
/*
* convert the v4 principal `name.instance@realm' to a v5 principal in `princ'.
* if `resolve', use DNS.
* if `func', use that function for validating the conversion
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_425_conv_principal_ext2(krb5_context context,
const char *name,
const char *instance,
const char *realm,
krb5_boolean (*func)(krb5_context,
void *, krb5_principal),
void *funcctx,
krb5_boolean resolve,
krb5_principal *princ)
{
const char *p;
krb5_error_code ret;
krb5_principal pr;
char host[MAXHOSTNAMELEN];
char local_hostname[MAXHOSTNAMELEN];
/* do the following: if the name is found in the
`v4_name_convert:host' part, is assumed to be a `host' type
principal, and the instance is looked up in the
`v4_instance_convert' part. if not found there the name is
(optionally) looked up as a hostname, and if that doesn't yield
anything, the `default_domain' is appended to the instance
*/
if(instance == NULL)
goto no_host;
if(instance[0] == 0){
instance = NULL;
goto no_host;
}
p = get_name_conversion(context, realm, name);
if(p == NULL)
goto no_host;
name = p;
p = krb5_config_get_string(context, NULL, "realms", realm,
"v4_instance_convert", instance, NULL);
if(p){
instance = p;
ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
if (ret)
return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
}
krb5_free_principal(context, pr);
*princ = NULL;
krb5_clear_error_message (context);
return HEIM_ERR_V4_PRINC_NO_CONV;
}
if(resolve){
krb5_boolean passed = FALSE;
char *inst = NULL;
#ifdef USE_RESOLVER
struct rk_dns_reply *r;
r = rk_dns_lookup(instance, "aaaa");
if (r) {
if (r->head && r->head->type == rk_ns_t_aaaa) {
inst = strdup(r->head->domain);
passed = TRUE;
}
rk_dns_free_data(r);
} else {
r = rk_dns_lookup(instance, "a");
if (r) {
if(r->head && r->head->type == rk_ns_t_a) {
inst = strdup(r->head->domain);
passed = TRUE;
}
rk_dns_free_data(r);
}
}
#else
struct addrinfo hints, *ai;
memset (&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
ret = getaddrinfo(instance, NULL, &hints, &ai);
if (ret == 0) {
const struct addrinfo *a;
for (a = ai; a != NULL; a = a->ai_next) {
if (a->ai_canonname != NULL) {
inst = strdup (a->ai_canonname);
passed = TRUE;
break;
}
}
freeaddrinfo (ai);
}
#endif
if (passed) {
if (inst == NULL) {
krb5_set_error_message(context, ENOMEM,
N_("malloc: out of memory", ""));
return ENOMEM;
}
strlwr(inst);
ret = krb5_make_principal(context, &pr, realm, name, inst,
NULL);
free (inst);
if(ret == 0) {
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
}
krb5_free_principal(context, pr);
}
}
}
if(func != NULL) {
snprintf(host, sizeof(host), "%s.%s", instance, realm);
strlwr(host);
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
if (ret)
return ret;
if((*func)(context, funcctx, pr)){
*princ = pr;
return 0;
}
krb5_free_principal(context, pr);
}
/*
* if the instance is the first component of the local hostname,
* the converted host should be the long hostname.
*/
if (func == NULL &&
gethostname (local_hostname, sizeof(local_hostname)) == 0 &&
strncmp(instance, local_hostname, strlen(instance)) == 0 &&
local_hostname[strlen(instance)] == '.') {
strlcpy(host, local_hostname, sizeof(host));
goto local_host;
}
{
char **domains, **d;
domains = krb5_config_get_strings(context, NULL, "realms", realm,
"v4_domains", NULL);
for(d = domains; d && *d; d++){
snprintf(host, sizeof(host), "%s.%s", instance, *d);
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
if (ret) {
krb5_config_free_strings(domains);
return ret;
}
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
krb5_config_free_strings(domains);
return 0;
}
krb5_free_principal(context, pr);
}
krb5_config_free_strings(domains);
}
p = krb5_config_get_string(context, NULL, "realms", realm,
"default_domain", NULL);
if(p == NULL){
/* this should be an error, just faking a name is not good */
krb5_clear_error_message (context);
return HEIM_ERR_V4_PRINC_NO_CONV;
}
if (*p == '.')
++p;
snprintf(host, sizeof(host), "%s.%s", instance, p);
local_host:
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
if (ret)
return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
}
krb5_free_principal(context, pr);
krb5_clear_error_message (context);
return HEIM_ERR_V4_PRINC_NO_CONV;
no_host:
p = krb5_config_get_string(context, NULL,
"realms",
realm,
"v4_name_convert",
"plain",
name,
NULL);
if(p == NULL)
p = krb5_config_get_string(context, NULL,
"libdefaults",
"v4_name_convert",
"plain",
name,
NULL);
if(p)
name = p;
ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
if (ret)
return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
}
krb5_free_principal(context, pr);
krb5_clear_error_message (context);
return HEIM_ERR_V4_PRINC_NO_CONV;
}
#endif /* KRB4 */
#ifndef HEIMDAL_SMALLER
static int
check_list(const krb5_config_binding *l, const char *name, const char **out)
{
while(l){
if (l->type != krb5_config_string)
continue;
if(strcmp(name, l->u.string) == 0) {
*out = l->name;
return 1;
}
l = l->next;
}
return 0;
}
static int
name_convert(krb5_context context, const char *name, const char *realm,
const char **out)
{
const krb5_config_binding *l;
l = krb5_config_get_list (context,
NULL,
"realms",
realm,
"v4_name_convert",
"host",
NULL);
if(l && check_list(l, name, out))
return KRB5_NT_SRV_HST;
l = krb5_config_get_list (context,
NULL,
"libdefaults",
"v4_name_convert",
"host",
NULL);
if(l && check_list(l, name, out))
return KRB5_NT_SRV_HST;
l = krb5_config_get_list (context,
NULL,
"realms",
realm,
"v4_name_convert",
"plain",
NULL);
if(l && check_list(l, name, out))
return KRB5_NT_UNKNOWN;
l = krb5_config_get_list (context,
NULL,
"libdefaults",
"v4_name_convert",
"host",
NULL);
if(l && check_list(l, name, out))
return KRB5_NT_UNKNOWN;
/* didn't find it in config file, try built-in list */
#ifdef KRB4
{
struct v4_name_convert *q;
for(q = default_v4_name_convert; q->from; q++) {
if(strcmp(name, q->to) == 0) {
*out = q->from;
return KRB5_NT_SRV_HST;
}
}
}
#endif
return -1;
}
/*
* convert the v5 principal in `principal' into a v4 corresponding one
* in `name, instance, realm'
* this is limited interface since there's no length given for these
* three parameters. They have to be 40 bytes each (ANAME_SZ).
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_524_conv_principal(krb5_context context,
const krb5_principal principal,
char *name,
char *instance,
char *realm)
{
const char *n, *i, *r;
char tmpinst[40];
int type = princ_type(principal);
const int aname_sz = 40;
r = principal->realm;
switch(principal->name.name_string.len){
case 1:
n = principal->name.name_string.val[0];
i = "";
break;
case 2:
n = principal->name.name_string.val[0];
i = principal->name.name_string.val[1];
break;
default:
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
N_("cannot convert a %d "
"component principal", ""),
principal->name.name_string.len);
return KRB5_PARSE_MALFORMED;
}
{
const char *tmp;
int t = name_convert(context, n, r, &tmp);
if(t >= 0) {
type = t;
n = tmp;
}
}
if(type == KRB5_NT_SRV_HST){
char *p;
strlcpy (tmpinst, i, sizeof(tmpinst));
p = strchr(tmpinst, '.');
if(p)
*p = 0;
i = tmpinst;
}
if (strlcpy (name, n, aname_sz) >= aname_sz) {
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
N_("too long name component to convert", ""));
return KRB5_PARSE_MALFORMED;
}
if (strlcpy (instance, i, aname_sz) >= aname_sz) {
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
N_("too long instance component to convert", ""));
return KRB5_PARSE_MALFORMED;
}
if (strlcpy (realm, r, aname_sz) >= aname_sz) {
krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
N_("too long realm component to convert", ""));
return KRB5_PARSE_MALFORMED;
}
return 0;
}
#endif /* !HEIMDAL_SMALLER */
/**
* Create a principal for the service running on hostname. If
* KRB5_NT_SRV_HST is used, the hostname is canonization using DNS (or

View File

@@ -1,960 +0,0 @@
/*
* 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 "krb5-v4compat.h"
#ifndef HEIMDAL_SMALLER
/*
*
*/
#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
};
KRB5_LIB_FUNCTION int KRB5_LIB_CALL
_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;
}
KRB5_LIB_FUNCTION time_t KRB5_LIB_CALL
_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);
}
#ifdef HAVE_GETUID
if(*cc == NULL)
if (asprintf(cc, "%s%u", TKT_ROOT, (unsigned)getuid()) < 0 || *cc == NULL)
return errno;
#elif defined(KRB5_USE_PATH_TOKENS)
if(*cc == NULL)
if (_krb5_expand_path_tokens(NULL, TKT_ROOT "%{uid}", cc))
return ENOMEM;
#endif
} 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_message(context, ret,
N_("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_message(context, ret,
N_("Failed opening krb4 credential cache "
"%s: %s", "path, error"),
path, strerror(ret));
free(path);
return ret;
}
rk_cloexec(fd);
if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) {
krb5_set_error_message(context, ret,
N_("krb4 credential cache %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_message(context, KRB5_FCC_PERM,
N_("Failed to lock credentail cache %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_message(context, KRB5_FCC_PERM,
N_("Failed to truncate krb4 cc %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;
else
ret = 0;
krb5_data_free(&data);
flock(fd, LOCK_UN);
free(path);
close(fd);
return ret;
}
/*
*
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_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_message(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_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_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_message(context, ret,
N_("Failed getting the krb4 credentials "
"cache name", ""));
return ret;
}
if (unlink(path) < 0) {
ret = errno;
krb5_set_error_message(context, ret,
N_("Failed removing the cache %s "
"with error %s", "path, error"),
path, 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, don't round up */
size = krb5_storage_seek(sp, 0, SEEK_END);
if (size < 0)
return KRB4ET_RD_AP_UNDEC;
size = ((size+7) & ~7) - size;
ret = krb5_storage_write(sp, eightzeros, size);
if (ret != size)
return KRB4ET_RD_AP_UNDEC;
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_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_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_message(context, ENOMEM, N_("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 = KRB4ET_INTK_PROT;
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_message(context, ret,
N_("Failed to encode kerberos 4 ticket", ""));
return ret;
}
/*
*
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_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_message(context, ENOMEM, N_("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 = KRB4ET_INTK_PROT;
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 = KRB4ET_INTK_PROT;
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_message(context, ret,
N_("Failed to encode kerberos 4 ticket", ""));
return ret;
}
/*
*
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_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_message(context, ENOMEM, N_("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 = KRB4ET_INTK_PROT;
goto error;
}
ret = krb5_storage_to_data(sp, data);
error:
krb5_storage_free(sp);
if (ret)
krb5_set_error_message(context, ret,
N_("Failed to encode kerberos 4 ticket", ""));
return ret;
}
/*
*
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_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_message(context, ENOMEM, N_("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);
/* If it is a Kerberos 4 error-code, remove the et BASE */
if (e >= ERROR_TABLE_BASE_krb && e <= ERROR_TABLE_BASE_krb + 255)
e -= ERROR_TABLE_BASE_krb;
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_message(context, ret, "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 KRB4ET_INTK_PROT;
}
return 0;
}
/*
*
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_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_message(context, ENOMEM, "alloc: out of memory");
return ENOMEM;
}
krb5_storage_set_eof_code(sp, KRB4ET_INTK_PROT);
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 = KRB4ET_INTK_PROT;
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_message(context, ret, "Failed to decode v4 ticket");
}
return ret;
}
/*
*
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
_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_message(context, ENOMEM, N_("malloc: out of memory", ""));
return ENOMEM;
}
krb5_storage_set_eof_code(sp, KRB4ET_INTK_PROT);
ret = krb5_ret_int8(sp, &pvno);
if (ret) {
krb5_set_error_message(context, ret, N_("Failed reading v4 pvno", ""));
goto error;
}
if (pvno != KRB_PROT_VERSION) {
ret = KRB4ET_RD_AP_VERSION;
krb5_set_error_message(context, ret, N_("Failed v4 pvno not 4", ""));
goto error;
}
ret = krb5_ret_int8(sp, &type);
if (ret) {
krb5_set_error_message(context, ret, N_("Failed readin v4 type", ""));
goto error;
}
little_endian = type & 1;
type &= ~1;
if(type != AUTH_MSG_APPL_REQUEST && type != AUTH_MSG_APPL_REQUEST_MUTUAL) {
ret = KRB4ET_RD_AP_MSG_TYPE;
krb5_set_error_message(context, ret,
N_("Not a valid v4 request 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 = KRB4ET_INTK_PROT;
krb5_set_error_message(context, ret, N_("Failed reading v4 ticket", ""));
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 = KRB4ET_INTK_PROT;
krb5_set_error_message(context, ret,
N_("Failed reading v4 authenticator", ""));
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) {
ret = ENOMEM;
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
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 = KRB4ET_RD_AP_INCON;
krb5_set_error_message(context, ret, N_("v4 principal mismatch", ""));
goto error;
}
if (from_addr && ad->address && from_addr != ad->address) {
ret = KRB4ET_RD_AP_BADD;
krb5_set_error_message(context, ret,
N_("v4 bad address in ticket", ""));
goto error;
}
gettimeofday(&tv, NULL);
delta_t = abs((int)(tv.tv_sec - r_time_sec));
if (delta_t > CLOCK_SKEW) {
ret = KRB4ET_RD_AP_TIME;
krb5_set_error_message(context, ret, N_("v4 clock skew", ""));
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 = KRB4ET_RD_AP_NYV;
krb5_set_error_message(context, ret,
N_("v4 clock skew for expiration", ""));
goto error;
}
if (tv.tv_sec > _krb5_krb_life_to_time(ad->time_sec, ad->life)) {
ret = KRB4ET_RD_AP_EXP;
krb5_set_error_message(context, ret, N_("v4 ticket expired", ""));
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_message(context);
return ret;
}
/*
*
*/
KRB5_LIB_FUNCTION void KRB5_LIB_CALL
_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));
}
#endif /* HEIMDAL_SMALLER */

View File

@@ -41,9 +41,6 @@
#ifdef KRB5
extern const char *heimdal_version;
#endif
#ifdef KRB4
extern const char *krb4_version;
#endif
#include <version.h>
int
@@ -62,12 +59,6 @@ main(int argc, char **argv)
fprintf(f, "#define VERSIONLIST \"");
#ifdef KRB5
fprintf(f, "%s", heimdal_version);
#endif
#ifdef KRB4
#ifdef KRB5
fprintf(f, ", ");
#endif
fprintf(f, "%s", krb4_version);
#endif
fprintf(f, "\"\n");
fclose(f);