remove krb4 support
This commit is contained in:
144
kdc/v4_dump.c
144
kdc/v4_dump.c
@@ -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 */
|
|
@@ -24,7 +24,6 @@ TESTS = \
|
|||||||
aes-test \
|
aes-test \
|
||||||
derived-key-test \
|
derived-key-test \
|
||||||
n-fold-test \
|
n-fold-test \
|
||||||
name-45-test \
|
|
||||||
parse-name-test \
|
parse-name-test \
|
||||||
store-test \
|
store-test \
|
||||||
string-to-key-test \
|
string-to-key-test \
|
||||||
@@ -220,7 +219,6 @@ dist_libkrb5_la_SOURCES = \
|
|||||||
ticket.c \
|
ticket.c \
|
||||||
time.c \
|
time.c \
|
||||||
transited.c \
|
transited.c \
|
||||||
v4_glue.c \
|
|
||||||
verify_init.c \
|
verify_init.c \
|
||||||
verify_user.c \
|
verify_user.c \
|
||||||
version.c \
|
version.c \
|
||||||
|
@@ -376,67 +376,6 @@ krb5_get_in_tkt_with_keytab (krb5_context context,
|
|||||||
ret_as_reply);
|
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'.
|
* Generate a new ccache of type `ops' in `id'.
|
||||||
*
|
*
|
||||||
|
@@ -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
|
|
@@ -1013,437 +1013,6 @@ krb5_principal_match(krb5_context context,
|
|||||||
return TRUE;
|
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
|
* Create a principal for the service running on hostname. If
|
||||||
* KRB5_NT_SRV_HST is used, the hostname is canonization using DNS (or
|
* KRB5_NT_SRV_HST is used, the hostname is canonization using DNS (or
|
||||||
|
@@ -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 */
|
|
@@ -41,9 +41,6 @@
|
|||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
extern const char *heimdal_version;
|
extern const char *heimdal_version;
|
||||||
#endif
|
#endif
|
||||||
#ifdef KRB4
|
|
||||||
extern const char *krb4_version;
|
|
||||||
#endif
|
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -62,12 +59,6 @@ main(int argc, char **argv)
|
|||||||
fprintf(f, "#define VERSIONLIST \"");
|
fprintf(f, "#define VERSIONLIST \"");
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
fprintf(f, "%s", heimdal_version);
|
fprintf(f, "%s", heimdal_version);
|
||||||
#endif
|
|
||||||
#ifdef KRB4
|
|
||||||
#ifdef KRB5
|
|
||||||
fprintf(f, ", ");
|
|
||||||
#endif
|
|
||||||
fprintf(f, "%s", krb4_version);
|
|
||||||
#endif
|
#endif
|
||||||
fprintf(f, "\"\n");
|
fprintf(f, "\"\n");
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
Reference in New Issue
Block a user