summaryrefslogtreecommitdiff
path: root/kerberosV
diff options
context:
space:
mode:
authorBjorn Sandell <biorn@cvs.openbsd.org>2006-10-06 07:09:11 +0000
committerBjorn Sandell <biorn@cvs.openbsd.org>2006-10-06 07:09:11 +0000
commit59320a567993df86c2a916ba46a3e498a1dc7ddc (patch)
tree6ddcdcef51aa1db57a995f8daced0a2111d46e5e /kerberosV
parent2b7f5f9782552858d18e8cb2db17c4f83fce8287 (diff)
Coverity fixes backported from the heimdal cvs.
ok beck@, No problem deraadt@
Diffstat (limited to 'kerberosV')
-rw-r--r--kerberosV/src/kadmin/random_password.c23
-rw-r--r--kerberosV/src/kdc/524.c28
-rw-r--r--kerberosV/src/kdc/hprop.c4
-rw-r--r--kerberosV/src/kdc/mit_dump.c11
-rw-r--r--kerberosV/src/kdc/string2key.c11
-rw-r--r--kerberosV/src/kpasswd/kpasswdd.c5
-rw-r--r--kerberosV/src/lib/asn1/hash.c19
-rw-r--r--kerberosV/src/lib/kadm5/init_c.c168
-rw-r--r--kerberosV/src/lib/kadm5/log.c227
-rw-r--r--kerberosV/src/lib/krb5/addr_families.c9
-rw-r--r--kerberosV/src/lib/krb5/build_auth.c263
-rw-r--r--kerberosV/src/lib/krb5/crypto.c4
-rw-r--r--kerberosV/src/lib/krb5/keytab_any.c31
-rw-r--r--kerberosV/src/lib/krb5/keytab_file.c326
-rw-r--r--kerberosV/src/lib/krb5/keytab_krb4.c240
-rw-r--r--kerberosV/src/lib/krb5/log.c2
-rw-r--r--kerberosV/src/lib/krb5/mk_req_ext.c57
-rw-r--r--kerberosV/src/lib/krb5/principal.c266
-rw-r--r--kerberosV/src/lib/krb5/rd_req.c4
-rw-r--r--kerberosV/src/lib/krb5/store.c412
-rw-r--r--kerberosV/src/lib/krb5/transited.c4
21 files changed, 1522 insertions, 592 deletions
diff --git a/kerberosV/src/kadmin/random_password.c b/kerberosV/src/kadmin/random_password.c
index e836f54c432..3f9c6033d7d 100644
--- a/kerberosV/src/kadmin/random_password.c
+++ b/kerberosV/src/kadmin/random_password.c
@@ -33,7 +33,7 @@
#include "kadmin_locl.h"
-RCSID("$KTH: random_password.c,v 1.3 1999/12/02 17:04:58 joda Exp $");
+RCSID("$KTH: random_password.c,v 1.4 2001/02/15 04:20:53 assar Exp $");
/* This file defines some a function that generates a random password,
that can be used when creating a large amount of principals (such
@@ -57,9 +57,9 @@ random_password(char *pw, size_t len)
{
#ifdef OTP_STYLE
{
- des_cblock newkey;
+ OtpKey newkey;
- des_new_random_key(&newkey);
+ krb5_generate_random_block(&newkey, sizeof(newkey));
otp_print_stddict (newkey, pw, len);
strlwr(pw);
}
@@ -80,11 +80,11 @@ random_password(char *pw, size_t len)
#ifndef OTP_STYLE
/* return a random value in range 0-127 */
static int
-RND(des_cblock *key, int *left)
+RND(unsigned char *key, int keylen, int *left)
{
if(*left == 0){
- des_new_random_key(key);
- *left = 8;
+ krb5_generate_random_block(key, keylen);
+ *left = keylen;
}
(*left)--;
return ((unsigned char*)key)[*left];
@@ -120,7 +120,7 @@ generate_password(char **pw, int num_classes, ...)
} *classes;
va_list ap;
int len, i;
- des_cblock rbuf; /* random buffer */
+ unsigned char rbuf[8]; /* random buffer */
int rleft = 0;
classes = malloc(num_classes * sizeof(*classes));
@@ -134,15 +134,18 @@ generate_password(char **pw, int num_classes, ...)
}
va_end(ap);
*pw = malloc(len + 1);
- if(*pw == NULL)
+ if(*pw == NULL) {
+ free(classes);
return;
+ }
for(i = 0; i < len; i++) {
int j;
- int x = RND(&rbuf, &rleft) % (len - i);
+ int x = RND(rbuf, sizeof(rbuf), &rleft) % (len - i);
int t = 0;
for(j = 0; j < num_classes; j++) {
if(x < t + classes[j].freq) {
- (*pw)[i] = classes[j].str[RND(&rbuf, &rleft) % classes[j].len];
+ (*pw)[i] = classes[j].str[RND(rbuf, sizeof(rbuf), &rleft)
+ % classes[j].len];
classes[j].freq--;
break;
}
diff --git a/kerberosV/src/kdc/524.c b/kerberosV/src/kdc/524.c
index 74b7d25f417..d62f932e37f 100644
--- a/kerberosV/src/kdc/524.c
+++ b/kerberosV/src/kdc/524.c
@@ -348,19 +348,21 @@ out:
/* make reply */
memset(buf, 0, sizeof(buf));
sp = krb5_storage_from_mem(buf, sizeof(buf));
- krb5_store_int32(sp, ret);
- if(ret == 0){
- krb5_store_int32(sp, kvno);
- krb5_store_data(sp, ticket.cipher);
- /* Aargh! This is coded as a KTEXT_ST. */
- krb5_storage_seek(sp, MAX_KTXT_LEN - ticket.cipher.length, SEEK_CUR);
- krb5_store_int32(sp, 0); /* mbz */
- free_EncryptedData(&ticket);
- }
- ret = krb5_storage_to_data(sp, reply);
- reply->length = krb5_storage_seek(sp, 0, SEEK_CUR);
- krb5_storage_free(sp);
-
+ if (sp) {
+ krb5_store_int32(sp, ret);
+ if(ret == 0){
+ krb5_store_int32(sp, kvno);
+ krb5_store_data(sp, ticket.cipher);
+ /* Aargh! This is coded as a KTEXT_ST. */
+ krb5_storage_seek(sp, MAX_KTXT_LEN - ticket.cipher.length, SEEK_CUR);
+ krb5_store_int32(sp, 0); /* mbz */
+ free_EncryptedData(&ticket);
+ }
+ ret = krb5_storage_to_data(sp, reply);
+ reply->length = krb5_storage_seek(sp, 0, SEEK_CUR);
+ krb5_storage_free(sp);
+ } else
+ krb5_data_zero(reply);
if(spn)
free(spn);
if(server)
diff --git a/kerberosV/src/kdc/hprop.c b/kerberosV/src/kdc/hprop.c
index bd48a5ae98b..1ddc85e116f 100644
--- a/kerberosV/src/kdc/hprop.c
+++ b/kerberosV/src/kdc/hprop.c
@@ -749,7 +749,7 @@ main(int argc, char **argv)
HDB *db = NULL;
int optind = 0;
- int type = 0;
+ int type;
if(getarg(args, num_args, argc, argv, &optind))
usage(1);
@@ -788,8 +788,6 @@ main(int argc, char **argv)
"only one of `--encrypt' and `--decrypt' is meaningful");
if(source_type != NULL) {
- if(type != 0)
- krb5_errx(context, 1, "more than one database type specified");
type = parse_source_type(source_type);
if(type == 0)
krb5_errx(context, 1, "unknown source type `%s'", source_type);
diff --git a/kerberosV/src/kdc/mit_dump.c b/kerberosV/src/kdc/mit_dump.c
index f2670c3c732..623333aeaf0 100644
--- a/kerberosV/src/kdc/mit_dump.c
+++ b/kerberosV/src/kdc/mit_dump.c
@@ -33,7 +33,7 @@
#include "hprop.h"
-RCSID("$KTH: mit_dump.c,v 1.3 2000/08/09 09:57:37 joda Exp $");
+RCSID("$KTH: mit_dump.c,v 1.5 2005/06/02 09:55:43 lha Exp $");
/*
can have any number of princ stanzas.
@@ -310,14 +310,14 @@ mit_prop_dump(void *arg, const char *file)
tl_type = getint(&p); /* data type */
tl_length = getint(&p); /* data length */
-#define KRB5_TL_LAST_PWD_CHANGE 1
-#define KRB5_TL_MOD_PRINC 2
+#define mit_KRB5_TL_LAST_PWD_CHANGE 1
+#define mit_KRB5_TL_MOD_PRINC 2
switch(tl_type) {
- case KRB5_TL_MOD_PRINC:
+ case mit_KRB5_TL_MOD_PRINC:
buf = malloc(tl_length);
getdata(&p, buf, tl_length); /* data itself */
val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- ret = krb5_parse_name(pd->context, buf + 4, &princ);
+ ret = krb5_parse_name(pd->context, (char *)buf + 4, &princ);
free(buf);
ALLOC(ent.modified_by);
ent.modified_by->time = val;
@@ -366,5 +366,6 @@ mit_prop_dump(void *arg, const char *file)
q = nexttoken(&p); /* extra data */
v5_prop(pd->context, NULL, &ent, arg);
}
+ fclose(f);
return 0;
}
diff --git a/kerberosV/src/kdc/string2key.c b/kerberosV/src/kdc/string2key.c
index 077b1525918..ecd0d8e9020 100644
--- a/kerberosV/src/kdc/string2key.c
+++ b/kerberosV/src/kdc/string2key.c
@@ -74,17 +74,24 @@ tokey(krb5_context context,
krb5_salt salt,
const char *label)
{
+ krb5_error_code ret;
int i;
krb5_keyblock key;
char *e;
- krb5_string_to_key_salt(context, enctype, password, salt, &key);
- krb5_enctype_to_string(context, enctype, &e);
+
+ ret = krb5_string_to_key_salt(context, enctype, password, salt, &key);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_string_to_key_salt");
+ ret = krb5_enctype_to_string(context, enctype, &e);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_enctype_to_string");
printf(label, e);
printf(": ");
for(i = 0; i < key.keyvalue.length; i++)
printf("%02x", ((unsigned char*)key.keyvalue.data)[i]);
printf("\n");
krb5_free_keyblock_contents(context, &key);
+ free(e);
}
int
diff --git a/kerberosV/src/kpasswd/kpasswdd.c b/kerberosV/src/kpasswd/kpasswdd.c
index 9b8c7c40925..deb28e7bcc1 100644
--- a/kerberosV/src/kpasswd/kpasswdd.c
+++ b/kerberosV/src/kpasswd/kpasswdd.c
@@ -687,6 +687,11 @@ doit (krb5_keytab keytab, int port)
buf, ret);
}
}
+
+ for (i = 0; i < n; ++i)
+ close(sockets[i]);
+ free(sockets);
+
krb5_free_addresses (context, &addrs);
krb5_free_host_realm (context, realms);
krb5_free_context (context);
diff --git a/kerberosV/src/lib/asn1/hash.c b/kerberosV/src/lib/asn1/hash.c
index b63baa5e964..9e29a7e9fcc 100644
--- a/kerberosV/src/lib/asn1/hash.c
+++ b/kerberosV/src/lib/asn1/hash.c
@@ -37,7 +37,7 @@
#include "gen_locl.h"
-RCSID("$KTH: hash.c,v 1.8 1999/12/02 17:05:02 joda Exp $");
+RCSID("$KTH: hash.c,v 1.9 2005/01/08 22:55:26 lha Exp $");
static Hashentry *_search(Hashtab * htab, /* The hash table */
void *ptr); /* And key */
@@ -53,17 +53,16 @@ hashtabnew(int sz,
assert(sz > 0);
htab = (Hashtab *) malloc(sizeof(Hashtab) + (sz - 1) * sizeof(Hashentry *));
+ if (htab == NULL)
+ return NULL;
+
for (i = 0; i < sz; ++i)
htab->tab[i] = NULL;
- if (htab == NULL) {
- return NULL;
- } else {
- htab->cmp = cmp;
- htab->hash = hash;
- htab->sz = sz;
- return htab;
- }
+ htab->cmp = cmp;
+ htab->hash = hash;
+ htab->sz = sz;
+ return htab;
}
/* Intern search function */
@@ -183,7 +182,7 @@ hashcaseadd(const char *s)
assert(s);
for (i = 0; *s; ++s)
- i += toupper(*s);
+ i += toupper((unsigned char)*s);
return i;
}
diff --git a/kerberosV/src/lib/kadm5/init_c.c b/kerberosV/src/lib/kadm5/init_c.c
index 9de500ee18c..8b519a1dcef 100644
--- a/kerberosV/src/lib/kadm5/init_c.c
+++ b/kerberosV/src/lib/kadm5/init_c.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -37,7 +37,7 @@
#include <netinet/in.h>
#include <netdb.h>
-RCSID("$KTH: init_c.c,v 1.40 2000/12/31 08:00:23 assar Exp $");
+RCSID("$KTH: init_c.c,v 1.51 2005/05/13 10:57:13 lha Exp $");
static void
set_funcs(kadm5_client_context *c)
@@ -72,24 +72,37 @@ _kadm5_c_init_context(kadm5_client_context **ctx,
krb5_add_et_list (context, initialize_kadm5_error_table_r);
set_funcs(*ctx);
(*ctx)->context = context;
- if(params->mask & KADM5_CONFIG_REALM)
+ if(params->mask & KADM5_CONFIG_REALM) {
+ ret = 0;
(*ctx)->realm = strdup(params->realm);
- else
- krb5_get_default_realm((*ctx)->context, &(*ctx)->realm);
+ if ((*ctx)->realm == NULL)
+ ret = ENOMEM;
+ } else
+ ret = krb5_get_default_realm((*ctx)->context, &(*ctx)->realm);
+ if (ret) {
+ free(*ctx);
+ return ret;
+ }
if(params->mask & KADM5_CONFIG_ADMIN_SERVER)
(*ctx)->admin_server = strdup(params->admin_server);
else {
char **hostlist;
ret = krb5_get_krb_admin_hst (context, &(*ctx)->realm, &hostlist);
- if (ret)
+ if (ret) {
+ free((*ctx)->realm);
+ free(*ctx);
return ret;
+ }
(*ctx)->admin_server = strdup(*hostlist);
krb5_free_krbhst (context, hostlist);
}
- if ((*ctx)->admin_server == NULL)
+ if ((*ctx)->admin_server == NULL) {
+ free((*ctx)->realm);
+ free(*ctx);
return ENOMEM;
+ }
colon = strchr ((*ctx)->admin_server, ':');
if (colon != NULL)
*colon++ = '\0';
@@ -141,12 +154,21 @@ get_new_cache(krb5_context context,
{
krb5_error_code ret;
krb5_creds cred;
- krb5_get_init_creds_opt opt;
+ krb5_get_init_creds_opt *opt;
krb5_ccache id;
- krb5_get_init_creds_opt_init (&opt);
- krb5_get_init_creds_opt_set_forwardable (&opt, FALSE);
- krb5_get_init_creds_opt_set_proxiable (&opt, FALSE);
+ ret = krb5_get_init_creds_opt_alloc (context, &opt);
+ if (ret)
+ return ret;
+
+ krb5_get_init_creds_opt_set_default_flags(context, "kadmin",
+ krb5_principal_get_realm(context,
+ client),
+ opt);
+
+
+ krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
+ krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
if(password == NULL && prompter == NULL) {
krb5_keytab kt;
@@ -154,15 +176,17 @@ get_new_cache(krb5_context context,
ret = krb5_kt_default(context, &kt);
else
ret = krb5_kt_resolve(context, keytab, &kt);
- if(ret)
+ if(ret) {
+ krb5_get_init_creds_opt_free(opt);
return ret;
+ }
ret = krb5_get_init_creds_keytab (context,
&cred,
client,
kt,
0,
server_name,
- &opt);
+ opt);
krb5_kt_close(context, kt);
} else {
ret = krb5_get_init_creds_password (context,
@@ -173,8 +197,9 @@ get_new_cache(krb5_context context,
NULL,
0,
server_name,
- &opt);
+ opt);
}
+ krb5_get_init_creds_opt_free(opt);
switch(ret){
case 0:
break;
@@ -194,20 +219,20 @@ get_new_cache(krb5_context context,
ret = krb5_cc_store_cred (context, id, &cred);
if (ret)
return ret;
- krb5_free_creds_contents (context, &cred);
+ krb5_free_cred_contents (context, &cred);
*ret_cache = id;
return 0;
}
-static krb5_error_code
-get_cred_cache(krb5_context context,
- const char *client_name,
- const char *server_name,
- const char *password,
- krb5_prompter_fct prompter,
- const char *keytab,
- krb5_ccache ccache,
- krb5_ccache *ret_cache)
+krb5_error_code
+_kadm5_c_get_cred_cache(krb5_context context,
+ const char *client_name,
+ const char *server_name,
+ const char *password,
+ krb5_prompter_fct prompter,
+ const char *keytab,
+ krb5_ccache ccache,
+ krb5_ccache *ret_cache)
{
krb5_error_code ret;
krb5_ccache id = NULL;
@@ -233,12 +258,47 @@ get_cred_cache(krb5_context context,
if(ret) {
krb5_cc_close(context, id);
id = NULL;
+ } else {
+ const char *name, *inst;
+ krb5_principal tmp;
+ name = krb5_principal_get_comp_string(context,
+ default_client, 0);
+ inst = krb5_principal_get_comp_string(context,
+ default_client, 1);
+ if(inst == NULL || strcmp(inst, "admin") != 0) {
+ ret = krb5_make_principal(context, &tmp, NULL,
+ name, "admin", NULL);
+ if(ret != 0) {
+ krb5_free_principal(context, default_client);
+ if (client)
+ krb5_free_principal(context, client);
+ krb5_cc_close(context, id);
+ return ret;
+ }
+ krb5_free_principal(context, default_client);
+ default_client = tmp;
+ krb5_cc_close(context, id);
+ id = NULL;
+ }
}
}
-
- if(client == NULL)
+
+ if (client != NULL) {
+ /* A client was specified by the caller. */
+ if (default_client != NULL) {
+ krb5_free_principal(context, default_client);
+ default_client = NULL;
+ }
+ }
+ else if (default_client != NULL)
+ /* No client was specified by the caller, but we have a
+ * client from the default credentials cache.
+ */
client = default_client;
- if(client == NULL) {
+ else {
+ /* No client was specified by the caller and we cannot determine
+ * the client from a credentials cache.
+ */
const char *user;
user = get_default_username ();
@@ -249,19 +309,19 @@ get_cred_cache(krb5_context context,
NULL, user, "admin", NULL);
if(ret)
return ret;
- }
- if(client != default_client) {
- krb5_free_principal(context, default_client);
- default_client = NULL;
if (id != NULL) {
krb5_cc_close(context, id);
id = NULL;
}
}
- } else if(ccache != NULL)
+ } else if(ccache != NULL) {
id = ccache;
-
+ ret = krb5_cc_get_principal(context, id, &client);
+ if(ret)
+ return ret;
+ }
+
if(id && (default_client == NULL ||
krb5_principal_compare(context, client, default_client))) {
ret = get_kadm_ticket(context, id, client, server_name);
@@ -277,7 +337,7 @@ get_cred_cache(krb5_context context,
return -1;
}
/* get creds via AS request */
- if(id)
+ if(id && (id != ccache))
krb5_cc_close(context, id);
if (client != default_client)
krb5_free_principal(context, default_client);
@@ -300,6 +360,7 @@ kadm_connect(kadm5_client_context *ctx)
int error;
char portstr[NI_MAXSERV];
char *hostname, *slash;
+ char *service_name;
krb5_context context = ctx->context;
memset (&hints, 0, sizeof(hints));
@@ -333,16 +394,31 @@ kadm_connect(kadm5_client_context *ctx)
krb5_warnx (context, "failed to contact %s", hostname);
return KADM5_FAILURE;
}
- ret = get_cred_cache(context, ctx->client_name, ctx->service_name,
- NULL, ctx->prompter, ctx->keytab,
- ctx->ccache, &cc);
+ ret = _kadm5_c_get_cred_cache(context,
+ ctx->client_name,
+ ctx->service_name,
+ NULL, ctx->prompter, ctx->keytab,
+ ctx->ccache, &cc);
if(ret) {
freeaddrinfo (ai);
close(s);
return ret;
}
- ret = krb5_parse_name(context, KADM5_ADMIN_SERVICE, &server);
+
+ if (ctx->realm)
+ asprintf(&service_name, "%s@%s", KADM5_ADMIN_SERVICE, ctx->realm);
+ else
+ asprintf(&service_name, "%s", KADM5_ADMIN_SERVICE);
+
+ if (service_name == NULL) {
+ freeaddrinfo (ai);
+ close(s);
+ return ENOMEM;
+ }
+
+ ret = krb5_parse_name(context, service_name, &server);
+ free(service_name);
if(ret) {
freeaddrinfo (ai);
if(ctx->ccache == NULL)
@@ -358,7 +434,13 @@ kadm_connect(kadm5_client_context *ctx)
NULL, NULL, cc, NULL, NULL, NULL);
if(ret == 0) {
krb5_data params;
- ret = _kadm5_marshal_params(context, ctx->realm_params, &params);
+ kadm5_config_params p;
+ memset(&p, 0, sizeof(p));
+ if(ctx->realm) {
+ p.mask |= KADM5_CONFIG_REALM;
+ p.realm = ctx->realm;
+ }
+ ret = _kadm5_marshal_params(context, &p, &params);
ret = krb5_write_priv_message(context, ctx->ac, &s, &params);
krb5_data_free(&params);
@@ -436,8 +518,10 @@ kadm5_c_init_with_context(krb5_context context,
return ret;
if(password != NULL && *password != '\0') {
- ret = get_cred_cache(context, client_name, service_name,
- password, prompter, keytab, ccache, &cc);
+ ret = _kadm5_c_get_cred_cache(context,
+ client_name,
+ service_name,
+ password, prompter, keytab, ccache, &cc);
if(ret)
return ret; /* XXX */
ccache = cc;
@@ -455,7 +539,7 @@ kadm5_c_init_with_context(krb5_context context,
ctx->prompter = prompter;
ctx->keytab = keytab;
ctx->ccache = ccache;
- ctx->realm_params = realm_params;
+ /* maybe we should copy the params here */
ctx->sock = -1;
*server_handle = ctx;
diff --git a/kerberosV/src/lib/kadm5/log.c b/kerberosV/src/lib/kadm5/log.c
index 5ca040ab82c..24a517e8946 100644
--- a/kerberosV/src/lib/kadm5/log.c
+++ b/kerberosV/src/lib/kadm5/log.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "kadm5_locl.h"
-RCSID("$KTH: log.c,v 1.18 2000/07/24 04:32:17 assar Exp $");
+RCSID("$KTH: log.c,v 1.21 2003/09/19 00:24:05 lha Exp $");
/*
* A log record consists of:
@@ -64,7 +64,7 @@ kadm5_log_get_version_fd (int fd,
return 0;
}
sp = krb5_storage_from_fd (fd);
- sp->seek(sp, -4, SEEK_CUR);
+ krb5_storage_seek(sp, -4, SEEK_CUR);
krb5_ret_int32 (sp, &old_version);
*ver = old_version;
krb5_storage_free(sp);
@@ -237,7 +237,7 @@ kadm5_log_create (kadm5_server_context *context,
return ret;
}
krb5_store_int32 (sp, value.length);
- sp->store(sp, value.data, value.length);
+ krb5_storage_write(sp, value.data, value.length);
krb5_store_int32 (sp, value.length);
krb5_data_free (&value);
ret = kadm5_log_postamble (log_context, sp);
@@ -268,13 +268,15 @@ kadm5_log_replay_create (kadm5_server_context *context,
krb5_data data;
hdb_entry ent;
- krb5_data_alloc (&data, len);
- sp->fetch (sp, data.data, len);
+ ret = krb5_data_alloc (&data, len);
+ if (ret)
+ return ret;
+ krb5_storage_read (sp, data.data, len);
ret = hdb_value2entry (context->context, &data, &ent);
krb5_data_free(&data);
if (ret)
return ret;
- ret = context->db->store(context->context, context->db, 0, &ent);
+ ret = context->db->hdb_store(context->context, context->db, 0, &ent);
hdb_free_entry (context->context, &ent);
return ret;
}
@@ -294,33 +296,36 @@ kadm5_log_delete (kadm5_server_context *context,
kadm5_log_context *log_context = &context->log_context;
sp = krb5_storage_emem();
+ if (sp == NULL)
+ return ENOMEM;
ret = kadm5_log_preamble (context, sp, kadm_delete);
- if (ret) {
- krb5_storage_free(sp);
- return ret;
- }
- krb5_store_int32 (sp, 0);
- off = sp->seek (sp, 0, SEEK_CUR);
- krb5_store_principal (sp, princ);
- len = sp->seek (sp, 0, SEEK_CUR) - off;
- sp->seek(sp, -(len + 4), SEEK_CUR);
- krb5_store_int32 (sp, len);
- sp->seek(sp, len, SEEK_CUR);
- krb5_store_int32 (sp, len);
- if (ret) {
- krb5_storage_free (sp);
- return ret;
- }
+ if (ret)
+ goto out;
+ ret = krb5_store_int32 (sp, 0);
+ if (ret)
+ goto out;
+ off = krb5_storage_seek (sp, 0, SEEK_CUR);
+ ret = krb5_store_principal (sp, princ);
+ if (ret)
+ goto out;
+ len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
+ krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
+ ret = krb5_store_int32 (sp, len);
+ if (ret)
+ goto out;
+ krb5_storage_seek(sp, len, SEEK_CUR);
+ ret = krb5_store_int32 (sp, len);
+ if (ret)
+ goto out;
ret = kadm5_log_postamble (log_context, sp);
- if (ret) {
- krb5_storage_free (sp);
- return ret;
- }
+ if (ret)
+ goto out;
ret = kadm5_log_flush (log_context, sp);
- krb5_storage_free (sp);
if (ret)
- return ret;
+ goto out;
ret = kadm5_log_end (context);
+out:
+ krb5_storage_free (sp);
return ret;
}
@@ -339,7 +344,7 @@ kadm5_log_replay_delete (kadm5_server_context *context,
krb5_ret_principal (sp, &ent.principal);
- ret = context->db->remove(context->context, context->db, &ent);
+ ret = context->db->hdb_remove(context->context, context->db, &ent);
krb5_free_principal (context->context, ent.principal);
return ret;
}
@@ -360,43 +365,53 @@ kadm5_log_rename (kadm5_server_context *context,
krb5_data value;
kadm5_log_context *log_context = &context->log_context;
+ krb5_data_zero(&value);
+
sp = krb5_storage_emem();
ret = hdb_entry2value (context->context, ent, &value);
- if (ret) {
- krb5_storage_free(sp);
- return ret;
- }
+ if (ret)
+ goto failed;
+
ret = kadm5_log_preamble (context, sp, kadm_rename);
- if (ret) {
- krb5_storage_free(sp);
- krb5_data_free (&value);
- return ret;
- }
- krb5_store_int32 (sp, 0);
- off = sp->seek (sp, 0, SEEK_CUR);
- krb5_store_principal (sp, source);
- sp->store(sp, value.data, value.length);
- krb5_data_free (&value);
- len = sp->seek (sp, 0, SEEK_CUR) - off;
+ if (ret)
+ goto failed;
+
+ ret = krb5_store_int32 (sp, 0);
+ if (ret)
+ goto failed;
+ off = krb5_storage_seek (sp, 0, SEEK_CUR);
+ ret = krb5_store_principal (sp, source);
+ if (ret)
+ goto failed;
+
+ krb5_storage_write(sp, value.data, value.length);
+ len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
+
+ krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
+ ret = krb5_store_int32 (sp, len);
+ if (ret)
+ goto failed;
+
+ krb5_storage_seek(sp, len, SEEK_CUR);
+ ret = krb5_store_int32 (sp, len);
+ if (ret)
+ goto failed;
- sp->seek(sp, -(len + 4), SEEK_CUR);
- krb5_store_int32 (sp, len);
- sp->seek(sp, len, SEEK_CUR);
- krb5_store_int32 (sp, len);
- if (ret) {
- krb5_storage_free (sp);
- return ret;
- }
ret = kadm5_log_postamble (log_context, sp);
- if (ret) {
- krb5_storage_free (sp);
- return ret;
- }
+ if (ret)
+ goto failed;
+
ret = kadm5_log_flush (log_context, sp);
- krb5_storage_free (sp);
if (ret)
- return ret;
- ret = kadm5_log_end (context);
+ goto failed;
+ krb5_storage_free (sp);
+ krb5_data_free (&value);
+
+ return kadm5_log_end (context);
+
+failed:
+ krb5_data_free(&value);
+ krb5_storage_free(sp);
return ret;
}
@@ -417,26 +432,31 @@ kadm5_log_replay_rename (kadm5_server_context *context,
off_t off;
size_t princ_len, data_len;
- off = sp->seek(sp, 0, SEEK_CUR);
+ off = krb5_storage_seek(sp, 0, SEEK_CUR);
krb5_ret_principal (sp, &source);
- princ_len = sp->seek(sp, 0, SEEK_CUR) - off;
+ princ_len = krb5_storage_seek(sp, 0, SEEK_CUR) - off;
data_len = len - princ_len;
- krb5_data_alloc (&value, data_len);
- sp->fetch (sp, value.data, data_len);
+ ret = krb5_data_alloc (&value, data_len);
+ if (ret) {
+ krb5_free_principal (context->context, source);
+ return ret;
+ }
+ krb5_storage_read (sp, value.data, data_len);
ret = hdb_value2entry (context->context, &value, &target_ent);
krb5_data_free(&value);
if (ret) {
krb5_free_principal (context->context, source);
return ret;
}
- ret = context->db->store (context->context, context->db, 0, &target_ent);
+ ret = context->db->hdb_store (context->context, context->db,
+ 0, &target_ent);
hdb_free_entry (context->context, &target_ent);
if (ret) {
krb5_free_principal (context->context, source);
return ret;
}
source_ent.principal = source;
- ret = context->db->remove (context->context, context->db, &source_ent);
+ ret = context->db->hdb_remove (context->context, context->db, &source_ent);
krb5_free_principal (context->context, source);
return ret;
}
@@ -457,38 +477,41 @@ kadm5_log_modify (kadm5_server_context *context,
u_int32_t len;
kadm5_log_context *log_context = &context->log_context;
+ krb5_data_zero(&value);
+
sp = krb5_storage_emem();
ret = hdb_entry2value (context->context, ent, &value);
- if (ret) {
- krb5_storage_free(sp);
- return ret;
- }
+ if (ret)
+ goto failed;
+
ret = kadm5_log_preamble (context, sp, kadm_modify);
- if (ret) {
- krb5_data_free (&value);
- krb5_storage_free(sp);
- return ret;
- }
+ if (ret)
+ goto failed;
+
len = value.length + 4;
- krb5_store_int32 (sp, len);
- krb5_store_int32 (sp, mask);
- sp->store(sp, value.data, value.length);
- krb5_data_free (&value);
- krb5_store_int32 (sp, len);
- if (ret) {
- krb5_storage_free (sp);
- return ret;
- }
+ ret = krb5_store_int32 (sp, len);
+ if (ret)
+ goto failed;
+ ret = krb5_store_int32 (sp, mask);
+ if (ret)
+ goto failed;
+ krb5_storage_write (sp, value.data, value.length);
+
+ ret = krb5_store_int32 (sp, len);
+ if (ret)
+ goto failed;
ret = kadm5_log_postamble (log_context, sp);
- if (ret) {
- krb5_storage_free (sp);
- return ret;
- }
+ if (ret)
+ goto failed;
ret = kadm5_log_flush (log_context, sp);
- krb5_storage_free (sp);
if (ret)
- return ret;
- ret = kadm5_log_end (context);
+ goto failed;
+ krb5_data_free(&value);
+ krb5_storage_free (sp);
+ return kadm5_log_end (context);
+failed:
+ krb5_data_free(&value);
+ krb5_storage_free(sp);
return ret;
}
@@ -509,16 +532,18 @@ kadm5_log_replay_modify (kadm5_server_context *context,
krb5_ret_int32 (sp, &mask);
len -= 4;
- krb5_data_alloc (&value, len);
- sp->fetch (sp, value.data, len);
+ ret = krb5_data_alloc (&value, len);
+ if (ret)
+ return ret;
+ krb5_storage_read (sp, value.data, len);
ret = hdb_value2entry (context->context, &value, &log_ent);
krb5_data_free(&value);
if (ret)
return ret;
ent.principal = log_ent.principal;
log_ent.principal = NULL;
- ret = context->db->fetch(context->context, context->db,
- HDB_F_DECRYPT, &ent);
+ ret = context->db->hdb_fetch(context->context, context->db,
+ HDB_F_DECRYPT, &ent);
if (ret)
return ret;
if (mask & KADM5_PRINC_EXPIRE_TIME) {
@@ -610,8 +635,8 @@ kadm5_log_replay_modify (kadm5_server_context *context,
copy_Key(&log_ent.keys.val[i],
&ent.keys.val[i]);
}
- ret = context->db->store(context->context, context->db,
- HDB_F_REPLACE, &ent);
+ ret = context->db->hdb_store(context->context, context->db,
+ HDB_F_REPLACE, &ent);
hdb_free_entry (context->context, &ent);
hdb_free_entry (context->context, &log_ent);
return ret;
@@ -689,7 +714,7 @@ kadm5_log_foreach (kadm5_server_context *context,
krb5_ret_int32 (sp, &op);
krb5_ret_int32 (sp, &len);
(*func)(context, ver, timestamp, op, len, sp);
- sp->seek(sp, 8, SEEK_CUR);
+ krb5_storage_seek(sp, 8, SEEK_CUR);
}
return 0;
}
@@ -704,7 +729,7 @@ kadm5_log_goto_end (int fd)
krb5_storage *sp;
sp = krb5_storage_from_fd (fd);
- sp->seek(sp, 0, SEEK_END);
+ krb5_storage_seek(sp, 0, SEEK_END);
return sp;
}
@@ -722,13 +747,13 @@ kadm5_log_previous (krb5_storage *sp,
off_t off;
int32_t tmp;
- sp->seek(sp, -8, SEEK_CUR);
+ krb5_storage_seek(sp, -8, SEEK_CUR);
krb5_ret_int32 (sp, &tmp);
*len = tmp;
krb5_ret_int32 (sp, &tmp);
*ver = tmp;
off = 24 + *len;
- sp->seek(sp, -off, SEEK_CUR);
+ krb5_storage_seek(sp, -off, SEEK_CUR);
krb5_ret_int32 (sp, &tmp);
assert(tmp == *ver);
krb5_ret_int32 (sp, &tmp);
diff --git a/kerberosV/src/lib/krb5/addr_families.c b/kerberosV/src/lib/krb5/addr_families.c
index 22ccc63af4f..8daeb6a911a 100644
--- a/kerberosV/src/lib/krb5/addr_families.c
+++ b/kerberosV/src/lib/krb5/addr_families.c
@@ -928,11 +928,18 @@ krb5_parse_address(krb5_context context,
int error;
int save_errno;
+ addresses->len = 0;
+ addresses->val = NULL;
+
for(i = 0; i < num_addrs; i++) {
if(at[i].parse_addr) {
krb5_address addr;
if((*at[i].parse_addr)(context, string, &addr) == 0) {
ALLOC_SEQ(addresses, 1);
+ if (addresses->val == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
addresses->val[0] = addr;
return 0;
}
@@ -1045,6 +1052,8 @@ krb5_free_addresses(krb5_context context,
for(i = 0; i < addresses->len; i++)
krb5_free_address(context, &addresses->val[i]);
free(addresses->val);
+ addresses->len = 0;
+ addresses->val = NULL;
return 0;
}
diff --git a/kerberosV/src/lib/krb5/build_auth.c b/kerberosV/src/lib/krb5/build_auth.c
index dd30de45cf7..a5571c01957 100644
--- a/kerberosV/src/lib/krb5/build_auth.c
+++ b/kerberosV/src/lib/krb5/build_auth.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,9 +33,73 @@
#include <krb5_locl.h>
-RCSID("$KTH: build_auth.c,v 1.34 2000/11/15 06:58:51 assar Exp $");
+RCSID("$KTH: build_auth.c,v 1.42 2005/01/05 02:34:53 lukeh Exp $");
-krb5_error_code
+static krb5_error_code
+make_etypelist(krb5_context context,
+ krb5_authdata **auth_data)
+{
+ EtypeList etypes;
+ krb5_error_code ret;
+ krb5_authdata ad;
+ u_char *buf;
+ size_t len;
+ size_t buf_size;
+
+ ret = krb5_init_etype(context, &etypes.len, &etypes.val, NULL);
+ if (ret)
+ return ret;
+
+ ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret);
+ if (ret) {
+ free_EtypeList(&etypes);
+ return ret;
+ }
+ if(buf_size != len)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+ free_EtypeList(&etypes);
+
+ ALLOC_SEQ(&ad, 1);
+ if (ad.val == NULL) {
+ free(buf);
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
+
+ ad.val[0].ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION;
+ ad.val[0].ad_data.length = len;
+ ad.val[0].ad_data.data = buf;
+
+ ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret);
+ if (ret) {
+ free_AuthorizationData(&ad);
+ return ret;
+ }
+ if(buf_size != len)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+ free_AuthorizationData(&ad);
+
+ ALLOC(*auth_data, 1);
+ if (*auth_data == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
+
+ ALLOC_SEQ(*auth_data, 1);
+ if ((*auth_data)->val == NULL) {
+ free(buf);
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
+
+ (*auth_data)->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
+ (*auth_data)->val[0].ad_data.length = len;
+ (*auth_data)->val[0].ad_data.data = buf;
+
+ return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
krb5_build_authenticator (krb5_context context,
krb5_auth_context auth_context,
krb5_enctype enctype,
@@ -45,115 +109,94 @@ krb5_build_authenticator (krb5_context context,
krb5_data *result,
krb5_key_usage usage)
{
- Authenticator *auth;
- u_char *buf = NULL;
- size_t buf_size;
- size_t len;
- krb5_error_code ret;
- krb5_crypto crypto;
-
- auth = malloc(sizeof(*auth));
- if (auth == NULL)
- return ENOMEM;
-
- memset (auth, 0, sizeof(*auth));
- auth->authenticator_vno = 5;
- copy_Realm(&cred->client->realm, &auth->crealm);
- copy_PrincipalName(&cred->client->name, &auth->cname);
-
- {
- int32_t sec, usec;
-
- krb5_us_timeofday (context, &sec, &usec);
- auth->ctime = sec;
- auth->cusec = usec;
- }
- ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey);
- if(ret)
- goto fail;
-
- if(auth->subkey == NULL) {
- krb5_generate_subkey (context, &cred->session, &auth->subkey);
- ret = krb5_auth_con_setlocalsubkey(context, auth_context, auth->subkey);
- if(ret)
- goto fail;
- }
-
- if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
- krb5_generate_seq_number (context,
- &cred->session,
- &auth_context->local_seqnumber);
- ALLOC(auth->seq_number, 1);
- *auth->seq_number = auth_context->local_seqnumber;
- } else
- auth->seq_number = NULL;
- auth->authorization_data = NULL;
- auth->cksum = cksum;
-
- /* XXX - Copy more to auth_context? */
-
- if (auth_context) {
+ Authenticator *auth;
+ u_char *buf = NULL;
+ size_t buf_size;
+ size_t len;
+ krb5_error_code ret;
+ krb5_crypto crypto;
+
+ auth = calloc(1, sizeof(*auth));
+ if (auth == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
+
+ auth->authenticator_vno = 5;
+ copy_Realm(&cred->client->realm, &auth->crealm);
+ copy_PrincipalName(&cred->client->name, &auth->cname);
+
+ krb5_us_timeofday (context, &auth->ctime, &auth->cusec);
+
+ ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey);
+ if(ret)
+ goto fail;
+
+ if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+ if(auth_context->local_seqnumber == 0)
+ krb5_generate_seq_number (context,
+ &cred->session,
+ &auth_context->local_seqnumber);
+ ALLOC(auth->seq_number, 1);
+ if(auth->seq_number == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ *auth->seq_number = auth_context->local_seqnumber;
+ } else
+ auth->seq_number = NULL;
+ auth->authorization_data = NULL;
+ auth->cksum = cksum;
+
+ if (cksum != NULL && cksum->cksumtype == CKSUMTYPE_GSSAPI) {
+ /*
+ * This is not GSS-API specific, we only enable it for
+ * GSS for now
+ */
+ ret = make_etypelist(context, &auth->authorization_data);
+ if (ret)
+ goto fail;
+ }
+
+ /* XXX - Copy more to auth_context? */
+
auth_context->authenticator->ctime = auth->ctime;
auth_context->authenticator->cusec = auth->cusec;
- }
-
- buf_size = 1024;
- buf = malloc (buf_size);
- if (buf == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- do {
- ret = krb5_encode_Authenticator (context,
- buf + buf_size - 1,
- buf_size,
- auth, &len);
- if (ret) {
- if (ret == ASN1_OVERFLOW) {
- u_char *tmp;
-
- buf_size *= 2;
- tmp = realloc (buf, buf_size);
- if (tmp == NULL) {
- ret = ENOMEM;
- goto fail;
- }
- buf = tmp;
- } else {
- goto fail;
- }
- }
- } while(ret == ASN1_OVERFLOW);
-
- ret = krb5_crypto_init(context, &cred->session, enctype, &crypto);
- if (ret)
- goto fail;
- ret = krb5_encrypt (context,
- crypto,
- usage /* KRB5_KU_AP_REQ_AUTH */,
- buf + buf_size - len,
- len,
- result);
- krb5_crypto_destroy(context, crypto);
-
- if (ret)
- goto fail;
-
- free (buf);
-
- if (auth_result)
- *auth_result = auth;
- else {
- /* Don't free the `cksum', it's allocated by the caller */
- auth->cksum = NULL;
+
+ ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret);
+ if (ret)
+ goto fail;
+ if(buf_size != len)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+
+ ret = krb5_crypto_init(context, &cred->session, enctype, &crypto);
+ if (ret)
+ goto fail;
+ ret = krb5_encrypt (context,
+ crypto,
+ usage /* KRB5_KU_AP_REQ_AUTH */,
+ buf + buf_size - len,
+ len,
+ result);
+ krb5_crypto_destroy(context, crypto);
+
+ if (ret)
+ goto fail;
+
+ free (buf);
+
+ if (auth_result)
+ *auth_result = auth;
+ else {
+ /* Don't free the `cksum', it's allocated by the caller */
+ auth->cksum = NULL;
+ free_Authenticator (auth);
+ free (auth);
+ }
+ return ret;
+ fail:
free_Authenticator (auth);
free (auth);
- }
- return ret;
-fail:
- free_Authenticator (auth);
- free (auth);
- free (buf);
- return ret;
+ free (buf);
+ return ret;
}
diff --git a/kerberosV/src/lib/krb5/crypto.c b/kerberosV/src/lib/krb5/crypto.c
index ad584732827..dab6aa79956 100644
--- a/kerberosV/src/lib/krb5/crypto.c
+++ b/kerberosV/src/lib/krb5/crypto.c
@@ -4176,7 +4176,7 @@ krb5_string_to_key_derived(krb5_context context,
struct encryption_type *et = _find_enctype(etype);
krb5_error_code ret;
struct key_data kd;
- size_t keylen = et->keytype->bits / 8;
+ size_t keylen;
u_char *tmp;
if(et == NULL) {
@@ -4184,6 +4184,8 @@ krb5_string_to_key_derived(krb5_context context,
etype);
return KRB5_PROG_ETYPE_NOSUPP;
}
+ keylen = et->keytype->bits / 8;
+
ALLOC(kd.key, 1);
if(kd.key == NULL) {
krb5_set_error_string (context, "malloc: out of memory");
diff --git a/kerberosV/src/lib/krb5/keytab_any.c b/kerberosV/src/lib/krb5/keytab_any.c
index f7512d5327f..f627ab6ca15 100644
--- a/kerberosV/src/lib/krb5/keytab_any.c
+++ b/kerberosV/src/lib/krb5/keytab_any.c
@@ -162,23 +162,22 @@ any_next_entry (krb5_context context,
ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor);
if (ret == 0)
return 0;
- else if (ret == KRB5_KT_END) {
- ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor);
- if (ret2)
- return ret2;
- while ((ed->a = ed->a->next) != NULL) {
- ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
- if (ret2 == 0)
- break;
- }
- if (ed->a == NULL) {
- krb5_clear_error_string (context);
- return KRB5_KT_END;
- }
- } else
+ else if (ret != KRB5_KT_END)
return ret;
- } while (ret == KRB5_KT_END);
- return ret;
+
+ ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor);
+ if (ret2)
+ return ret2;
+ while ((ed->a = ed->a->next) != NULL) {
+ ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
+ if (ret2 == 0)
+ break;
+ }
+ if (ed->a == NULL) {
+ krb5_clear_error_string (context);
+ return KRB5_KT_END;
+ }
+ } while (1);
}
static krb5_error_code
diff --git a/kerberosV/src/lib/krb5/keytab_file.c b/kerberosV/src/lib/krb5/keytab_file.c
index 0af6e17254c..b491523ea8b 100644
--- a/kerberosV/src/lib/krb5/keytab_file.c
+++ b/kerberosV/src/lib/krb5/keytab_file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,20 +33,25 @@
#include "krb5_locl.h"
-RCSID("$KTH: keytab_file.c,v 1.6 2000/01/02 00:20:22 assar Exp $");
+RCSID("$KTH: keytab_file.c,v 1.18 2005/05/31 21:50:43 lha Exp $");
#define KRB5_KT_VNO_1 1
#define KRB5_KT_VNO_2 2
#define KRB5_KT_VNO KRB5_KT_VNO_2
+#define KRB5_KT_FL_JAVA 1
+
+
/* file operations -------------------------------------------- */
struct fkt_data {
char *filename;
+ int flags;
};
static krb5_error_code
-krb5_kt_ret_data(krb5_storage *sp,
+krb5_kt_ret_data(krb5_context context,
+ krb5_storage *sp,
krb5_data *data)
{
int ret;
@@ -56,17 +61,20 @@ krb5_kt_ret_data(krb5_storage *sp,
return ret;
data->length = size;
data->data = malloc(size);
- if (data->data == NULL)
+ if (data->data == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
- ret = sp->fetch(sp, data->data, size);
+ }
+ ret = krb5_storage_read(sp, data->data, size);
if(ret != size)
return (ret < 0)? errno : KRB5_KT_END;
return 0;
}
static krb5_error_code
-krb5_kt_ret_string(krb5_storage *sp,
- general_string *data)
+krb5_kt_ret_string(krb5_context context,
+ krb5_storage *sp,
+ heim_general_string *data)
{
int ret;
int16_t size;
@@ -74,9 +82,11 @@ krb5_kt_ret_string(krb5_storage *sp,
if(ret)
return ret;
*data = malloc(size + 1);
- if (*data == NULL)
+ if (*data == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
- ret = sp->fetch(sp, *data, size);
+ }
+ ret = krb5_storage_read(sp, *data, size);
(*data)[size] = '\0';
if(ret != size)
return (ret < 0)? errno : KRB5_KT_END;
@@ -84,14 +94,15 @@ krb5_kt_ret_string(krb5_storage *sp,
}
static krb5_error_code
-krb5_kt_store_data(krb5_storage *sp,
+krb5_kt_store_data(krb5_context context,
+ krb5_storage *sp,
krb5_data data)
{
int ret;
ret = krb5_store_int16(sp, data.length);
if(ret < 0)
return ret;
- ret = sp->store(sp, data.data, data.length);
+ ret = krb5_storage_write(sp, data.data, data.length);
if(ret != data.length){
if(ret < 0)
return errno;
@@ -102,14 +113,14 @@ krb5_kt_store_data(krb5_storage *sp,
static krb5_error_code
krb5_kt_store_string(krb5_storage *sp,
- general_string data)
+ heim_general_string data)
{
int ret;
size_t len = strlen(data);
ret = krb5_store_int16(sp, len);
if(ret < 0)
return ret;
- ret = sp->store(sp, data, len);
+ ret = krb5_storage_write(sp, data, len);
if(ret != len){
if(ret < 0)
return errno;
@@ -119,7 +130,7 @@ krb5_kt_store_string(krb5_storage *sp,
}
static krb5_error_code
-krb5_kt_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
+krb5_kt_ret_keyblock(krb5_context context, krb5_storage *sp, krb5_keyblock *p)
{
int ret;
int16_t tmp;
@@ -127,51 +138,68 @@ krb5_kt_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
ret = krb5_ret_int16(sp, &tmp); /* keytype + etype */
if(ret) return ret;
p->keytype = tmp;
- ret = krb5_kt_ret_data(sp, &p->keyvalue);
+ ret = krb5_kt_ret_data(context, sp, &p->keyvalue);
return ret;
}
static krb5_error_code
-krb5_kt_store_keyblock(krb5_storage *sp,
+krb5_kt_store_keyblock(krb5_context context,
+ krb5_storage *sp,
krb5_keyblock *p)
{
int ret;
ret = krb5_store_int16(sp, p->keytype); /* keytype + etype */
if(ret) return ret;
- ret = krb5_kt_store_data(sp, p->keyvalue);
+ ret = krb5_kt_store_data(context, sp, p->keyvalue);
return ret;
}
static krb5_error_code
-krb5_kt_ret_principal(krb5_storage *sp,
+krb5_kt_ret_principal(krb5_context context,
+ krb5_storage *sp,
krb5_principal *princ)
{
int i;
int ret;
krb5_principal p;
- int16_t tmp;
+ int16_t len;
ALLOC(p, 1);
- if(p == NULL)
+ if(p == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
- ret = krb5_ret_int16(sp, &tmp);
+ ret = krb5_ret_int16(sp, &len);
+ if(ret) {
+ krb5_set_error_string(context,
+ "Failed decoding length of keytab principal");
+ goto out;
+ }
+ if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
+ len--;
+ if (len < 0) {
+ krb5_set_error_string(context,
+ "Keytab principal contains invalid length");
+ ret = KRB5_KT_END;
+ goto out;
+ }
+ ret = krb5_kt_ret_string(context, sp, &p->realm);
if(ret)
- return ret;
- if (sp->flags & KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)
- tmp--;
- p->name.name_string.len = tmp;
- ret = krb5_kt_ret_string(sp, &p->realm);
- if(ret) return ret;
- p->name.name_string.val = calloc(p->name.name_string.len,
- sizeof(*p->name.name_string.val));
- if(p->name.name_string.val == NULL)
- return ENOMEM;
+ goto out;
+ p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val));
+ if(p->name.name_string.val == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
+ ret = ENOMEM;
+ goto out;
+ }
+ p->name.name_string.len = len;
for(i = 0; i < p->name.name_string.len; i++){
- ret = krb5_kt_ret_string(sp, p->name.name_string.val + i);
- if(ret) return ret;
+ ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i);
+ if(ret)
+ goto out;
}
if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
p->name.name_type = KRB5_NT_UNKNOWN;
@@ -180,14 +208,18 @@ krb5_kt_ret_principal(krb5_storage *sp,
ret = krb5_ret_int32(sp, &tmp32);
p->name.name_type = tmp32;
if (ret)
- return ret;
+ goto out;
}
*princ = p;
return 0;
+out:
+ krb5_free_principal(context, p);
+ return ret;
}
static krb5_error_code
-krb5_kt_store_principal(krb5_storage *sp,
+krb5_kt_store_principal(krb5_context context,
+ krb5_storage *sp,
krb5_principal p)
{
int i;
@@ -202,7 +234,8 @@ krb5_kt_store_principal(krb5_storage *sp,
if(ret) return ret;
for(i = 0; i < p->name.name_string.len; i++){
ret = krb5_kt_store_string(sp, p->name.name_string.val[i]);
- if(ret) return ret;
+ if(ret)
+ return ret;
}
if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
ret = krb5_store_int32(sp, p->name.name_type);
@@ -217,19 +250,37 @@ static krb5_error_code
fkt_resolve(krb5_context context, const char *name, krb5_keytab id)
{
struct fkt_data *d;
+
d = malloc(sizeof(*d));
- if(d == NULL)
+ if(d == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
d->filename = strdup(name);
if(d->filename == NULL) {
free(d);
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
+ d->flags = 0;
id->data = d;
return 0;
}
static krb5_error_code
+fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id)
+{
+ krb5_error_code ret;
+
+ ret = fkt_resolve(context, name, id);
+ if (ret == 0) {
+ struct fkt_data *d = id->data;
+ d->flags |= KRB5_KT_FL_JAVA;
+ }
+ return ret;
+}
+
+static krb5_error_code
fkt_close(krb5_context context, krb5_keytab id)
{
struct fkt_data *d = id->data;
@@ -263,8 +314,8 @@ storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
case KRB5_KT_VNO_2:
break;
default:
- krb5_abortx(context,
- "storage_set_flags called with bad vno (%x)", vno);
+ krb5_warnx(context,
+ "storage_set_flags called with bad vno (%d)", vno);
}
krb5_storage_set_flags(sp, flags);
}
@@ -273,6 +324,7 @@ static krb5_error_code
fkt_start_seq_get_int(krb5_context context,
krb5_keytab id,
int flags,
+ int exclusive,
krb5_kt_cursor *c)
{
int8_t pvno, tag;
@@ -280,24 +332,40 @@ fkt_start_seq_get_int(krb5_context context,
struct fkt_data *d = id->data;
c->fd = open (d->filename, flags);
- if (c->fd < 0)
- return errno;
+ if (c->fd < 0) {
+ ret = errno;
+ krb5_set_error_string(context, "%s: %s", d->filename,
+ strerror(ret));
+ return ret;
+ }
+ ret = _krb5_xlock(context, c->fd, exclusive, d->filename);
+ if (ret) {
+ close(c->fd);
+ return ret;
+ }
c->sp = krb5_storage_from_fd(c->fd);
+ krb5_storage_set_eof_code(c->sp, KRB5_KT_END);
ret = krb5_ret_int8(c->sp, &pvno);
if(ret) {
krb5_storage_free(c->sp);
+ _krb5_xunlock(context, c->fd);
close(c->fd);
+ krb5_clear_error_string(context);
return ret;
}
if(pvno != 5) {
krb5_storage_free(c->sp);
+ _krb5_xunlock(context, c->fd);
close(c->fd);
+ krb5_clear_error_string (context);
return KRB5_KEYTAB_BADVNO;
}
ret = krb5_ret_int8(c->sp, &tag);
if (ret) {
krb5_storage_free(c->sp);
+ _krb5_xunlock(context, c->fd);
close(c->fd);
+ krb5_clear_error_string(context);
return ret;
}
id->version = tag;
@@ -310,7 +378,7 @@ fkt_start_seq_get(krb5_context context,
krb5_keytab id,
krb5_kt_cursor *c)
{
- return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, c);
+ return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, 0, c);
}
static krb5_error_code
@@ -325,18 +393,18 @@ fkt_next_entry_int(krb5_context context,
int ret;
int8_t tmp8;
int32_t tmp32;
- off_t pos;
+ off_t pos, curpos;
- pos = cursor->sp->seek(cursor->sp, 0, SEEK_CUR);
+ pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
loop:
ret = krb5_ret_int32(cursor->sp, &len);
if (ret)
return ret;
if(len < 0) {
- pos = cursor->sp->seek(cursor->sp, -len, SEEK_CUR);
+ pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR);
goto loop;
}
- ret = krb5_kt_ret_principal (cursor->sp, &entry->principal);
+ ret = krb5_kt_ret_principal (context, cursor->sp, &entry->principal);
if (ret)
goto out;
ret = krb5_ret_int32(cursor->sp, &tmp32);
@@ -347,13 +415,23 @@ loop:
if (ret)
goto out;
entry->vno = tmp8;
- ret = krb5_kt_ret_keyblock (cursor->sp, &entry->keyblock);
+ ret = krb5_kt_ret_keyblock (context, cursor->sp, &entry->keyblock);
if (ret)
goto out;
+ /* there might be a 32 bit kvno here
+ * if it's zero, assume that the 8bit one was right,
+ * otherwise trust the new value */
+ curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
+ if(len + 4 + pos - curpos == 4) {
+ ret = krb5_ret_int32(cursor->sp, &tmp32);
+ if (ret == 0 && tmp32 != 0) {
+ entry->vno = tmp32;
+ }
+ }
if(start) *start = pos;
if(end) *end = *start + 4 + len;
out:
- cursor->sp->seek(cursor->sp, pos + 4 + len, SEEK_SET);
+ krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET);
return ret;
}
@@ -372,11 +450,26 @@ fkt_end_seq_get(krb5_context context,
krb5_kt_cursor *cursor)
{
krb5_storage_free(cursor->sp);
+ _krb5_xunlock(context, cursor->fd);
close(cursor->fd);
return 0;
}
static krb5_error_code
+fkt_setup_keytab(krb5_context context,
+ krb5_keytab id,
+ krb5_storage *sp)
+{
+ krb5_error_code ret;
+ ret = krb5_store_int8(sp, 5);
+ if(ret)
+ return ret;
+ if(id->version == 0)
+ id->version = KRB5_KT_VNO;
+ return krb5_store_int8 (sp, id->version);
+}
+
+static krb5_error_code
fkt_add_entry(krb5_context context,
krb5_keytab id,
krb5_keytab_entry *entry)
@@ -390,47 +483,61 @@ fkt_add_entry(krb5_context context,
fd = open (d->filename, O_RDWR | O_BINARY);
if (fd < 0) {
- fd = open (d->filename, O_RDWR | O_CREAT | O_BINARY, 0600);
- if (fd < 0)
- return errno;
- sp = krb5_storage_from_fd(fd);
- ret = krb5_store_int8(sp, 5);
- if(ret) {
- krb5_storage_free(sp);
- close(fd);
+ fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
+ if (fd < 0) {
+ ret = errno;
+ krb5_set_error_string(context, "open(%s): %s", d->filename,
+ strerror(ret));
return ret;
}
- if(id->version == 0)
- id->version = KRB5_KT_VNO;
- ret = krb5_store_int8 (sp, id->version);
+ ret = _krb5_xlock(context, fd, 1, d->filename);
if (ret) {
- krb5_storage_free(sp);
close(fd);
return ret;
}
- storage_set_flags(context, sp, id->version);
- } else {
- int8_t pvno, tag;
sp = krb5_storage_from_fd(fd);
- ret = krb5_ret_int8(sp, &pvno);
+ krb5_storage_set_eof_code(sp, KRB5_KT_END);
+ ret = fkt_setup_keytab(context, id, sp);
if(ret) {
- krb5_storage_free(sp);
- close(fd);
- return ret;
- }
- if(pvno != 5) {
- krb5_storage_free(sp);
- close(fd);
- return KRB5_KEYTAB_BADVNO;
+ goto out;
}
- ret = krb5_ret_int8 (sp, &tag);
+ storage_set_flags(context, sp, id->version);
+ } else {
+ int8_t pvno, tag;
+ ret = _krb5_xlock(context, fd, 1, d->filename);
if (ret) {
- krb5_storage_free(sp);
close(fd);
return ret;
}
- id->version = tag;
- storage_set_flags(context, sp, id->version);
+ sp = krb5_storage_from_fd(fd);
+ krb5_storage_set_eof_code(sp, KRB5_KT_END);
+ ret = krb5_ret_int8(sp, &pvno);
+ if(ret) {
+ /* we probably have a zero byte file, so try to set it up
+ properly */
+ ret = fkt_setup_keytab(context, id, sp);
+ if(ret) {
+ krb5_set_error_string(context, "%s: keytab is corrupted: %s",
+ d->filename, strerror(ret));
+ goto out;
+ }
+ storage_set_flags(context, sp, id->version);
+ } else {
+ if(pvno != 5) {
+ ret = KRB5_KEYTAB_BADVNO;
+ krb5_set_error_string(context, "%s: %s",
+ d->filename, strerror(ret));
+ goto out;
+ }
+ ret = krb5_ret_int8 (sp, &tag);
+ if (ret) {
+ krb5_set_error_string(context, "%s: reading tag: %s",
+ d->filename, strerror(ret));
+ goto out;
+ }
+ id->version = tag;
+ storage_set_flags(context, sp, id->version);
+ }
}
{
@@ -438,9 +545,10 @@ fkt_add_entry(krb5_context context,
emem = krb5_storage_emem();
if(emem == NULL) {
ret = ENOMEM;
+ krb5_set_error_string (context, "malloc: out of memory");
goto out;
}
- ret = krb5_kt_store_principal(emem, entry->principal);
+ ret = krb5_kt_store_principal(context, emem, entry->principal);
if(ret) {
krb5_storage_free(emem);
goto out;
@@ -450,16 +558,24 @@ fkt_add_entry(krb5_context context,
krb5_storage_free(emem);
goto out;
}
- ret = krb5_store_int8 (emem, entry->vno);
+ ret = krb5_store_int8 (emem, entry->vno % 256);
if(ret) {
krb5_storage_free(emem);
goto out;
}
- ret = krb5_kt_store_keyblock (emem, &entry->keyblock);
+ ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock);
if(ret) {
krb5_storage_free(emem);
goto out;
}
+ if ((d->flags & KRB5_KT_FL_JAVA) == 0) {
+ ret = krb5_store_int32 (emem, entry->vno);
+ if (ret) {
+ krb5_storage_free(emem);
+ goto out;
+ }
+ }
+
ret = krb5_storage_to_data(emem, &keytab);
krb5_storage_free(emem);
if(ret)
@@ -468,26 +584,27 @@ fkt_add_entry(krb5_context context,
while(1) {
ret = krb5_ret_int32(sp, &len);
- if(ret == KRB5_CC_END) {
+ if(ret == KRB5_KT_END) {
len = keytab.length;
break;
}
if(len < 0) {
len = -len;
if(len >= keytab.length) {
- sp->seek(sp, -4, SEEK_CUR);
+ krb5_storage_seek(sp, -4, SEEK_CUR);
break;
}
}
- sp->seek(sp, len, SEEK_CUR);
+ krb5_storage_seek(sp, len, SEEK_CUR);
}
ret = krb5_store_int32(sp, len);
- if(sp->store(sp, keytab.data, keytab.length) < 0)
+ if(krb5_storage_write(sp, keytab.data, keytab.length) < 0)
ret = errno;
memset(keytab.data, 0, keytab.length);
krb5_data_free(&keytab);
- out:
+ out:
krb5_storage_free(sp);
+ _krb5_xunlock(context, fd);
close(fd);
return ret;
}
@@ -501,8 +618,11 @@ fkt_remove_entry(krb5_context context,
krb5_kt_cursor cursor;
off_t pos_start, pos_end;
int found = 0;
+ krb5_error_code ret;
- fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, &cursor);
+ ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, 1, &cursor);
+ if(ret != 0)
+ goto out; /* return other error here? */
while(fkt_next_entry_int(context, id, &e, &cursor,
&pos_start, &pos_end) == 0) {
if(krb5_kt_compare(context, &e, entry->principal,
@@ -510,19 +630,23 @@ fkt_remove_entry(krb5_context context,
int32_t len;
unsigned char buf[128];
found = 1;
- cursor.sp->seek(cursor.sp, pos_start, SEEK_SET);
+ krb5_storage_seek(cursor.sp, pos_start, SEEK_SET);
len = pos_end - pos_start - 4;
krb5_store_int32(cursor.sp, -len);
memset(buf, 0, sizeof(buf));
while(len > 0) {
- cursor.sp->store(cursor.sp, buf, min(len, sizeof(buf)));
+ krb5_storage_write(cursor.sp, buf, min(len, sizeof(buf)));
len -= min(len, sizeof(buf));
}
}
+ krb5_kt_free_entry(context, &e);
}
krb5_kt_end_seq_get(context, id, &cursor);
- if (!found)
+ out:
+ if (!found) {
+ krb5_clear_error_string (context);
return KRB5_KT_NOTFOUND;
+ }
return 0;
}
@@ -538,3 +662,29 @@ const krb5_kt_ops krb5_fkt_ops = {
fkt_add_entry,
fkt_remove_entry
};
+
+const krb5_kt_ops krb5_wrfkt_ops = {
+ "WRFILE",
+ fkt_resolve,
+ fkt_get_name,
+ fkt_close,
+ NULL, /* get */
+ fkt_start_seq_get,
+ fkt_next_entry,
+ fkt_end_seq_get,
+ fkt_add_entry,
+ fkt_remove_entry
+};
+
+const krb5_kt_ops krb5_javakt_ops = {
+ "JAVA14",
+ fkt_resolve_java14,
+ fkt_get_name,
+ fkt_close,
+ NULL, /* get */
+ fkt_start_seq_get,
+ fkt_next_entry,
+ fkt_end_seq_get,
+ fkt_add_entry,
+ fkt_remove_entry
+};
diff --git a/kerberosV/src/lib/krb5/keytab_krb4.c b/kerberosV/src/lib/krb5/keytab_krb4.c
index 76d6f777826..5efeb8826af 100644
--- a/kerberosV/src/lib/krb5/keytab_krb4.c
+++ b/kerberosV/src/lib/krb5/keytab_krb4.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$KTH: keytab_krb4.c,v 1.6 2000/12/15 17:10:40 joda Exp $");
+RCSID("$KTH: keytab_krb4.c,v 1.13 2005/05/19 04:13:18 lha Exp $");
struct krb4_kt_data {
char *filename;
@@ -45,11 +45,14 @@ krb4_kt_resolve(krb5_context context, const char *name, krb5_keytab id)
struct krb4_kt_data *d;
d = malloc (sizeof(*d));
- if (d == NULL)
+ if (d == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
d->filename = strdup (name);
if (d->filename == NULL) {
free(d);
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
id->data = d;
@@ -84,6 +87,31 @@ struct krb4_cursor_extra_data {
int num;
};
+static int
+open_flock(const char *filename, int flags, int mode)
+{
+ int lock_mode;
+ int tries = 0;
+ int fd = open(filename, flags, mode);
+ if(fd < 0)
+ return fd;
+ if((flags & O_ACCMODE) == O_RDONLY)
+ lock_mode = LOCK_SH | LOCK_NB;
+ else
+ lock_mode = LOCK_EX | LOCK_NB;
+ while(flock(fd, lock_mode) < 0) {
+ if(++tries < 5) {
+ sleep(1);
+ } else {
+ close(fd);
+ return -1;
+ }
+ }
+ return fd;
+}
+
+
+
static krb5_error_code
krb4_kt_start_seq_get_int (krb5_context context,
krb5_keytab id,
@@ -92,19 +120,31 @@ krb4_kt_start_seq_get_int (krb5_context context,
{
struct krb4_kt_data *d = id->data;
struct krb4_cursor_extra_data *ed;
+ int ret;
ed = malloc (sizeof(*ed));
- if (ed == NULL)
+ if (ed == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
ed->entry.principal = NULL;
ed->num = -1;
c->data = ed;
- c->fd = open (d->filename, flags);
+ c->fd = open_flock (d->filename, flags, 0);
if (c->fd < 0) {
+ ret = errno;
free (ed);
- return errno;
+ krb5_set_error_string(context, "open(%s): %s", d->filename,
+ strerror(ret));
+ return ret;
}
c->sp = krb5_storage_from_fd(c->fd);
+ if(c->sp == NULL) {
+ close(c->fd);
+ free(ed);
+ return ENOMEM;
+ }
+ krb5_storage_set_eof_code(c->sp, KRB5_KT_END);
return 0;
}
@@ -122,10 +162,10 @@ read_v4_entry (krb5_context context,
krb5_kt_cursor *c,
struct krb4_cursor_extra_data *ed)
{
+ unsigned char des_key[8];
krb5_error_code ret;
char *service, *instance, *realm;
int8_t kvno;
- des_cblock key;
ret = krb5_ret_stringz(c->sp, &service);
if (ret)
@@ -153,7 +193,7 @@ read_v4_entry (krb5_context context,
krb5_free_principal (context, ed->entry.principal);
return ret;
}
- ret = c->sp->fetch(c->sp, key, 8);
+ ret = krb5_storage_read(c->sp, des_key, sizeof(des_key));
if (ret < 0) {
krb5_free_principal(context, ed->entry.principal);
return ret;
@@ -164,7 +204,7 @@ read_v4_entry (krb5_context context,
}
ed->entry.vno = kvno;
ret = krb5_data_copy (&ed->entry.keyblock.keyvalue,
- key, 8);
+ des_key, sizeof(des_key));
if (ret)
return ret;
ed->entry.timestamp = time(NULL);
@@ -219,47 +259,168 @@ krb4_kt_end_seq_get (krb5_context context,
}
static krb5_error_code
-krb4_kt_add_entry (krb5_context context,
- krb5_keytab id,
- krb5_keytab_entry *entry)
+krb4_store_keytab_entry(krb5_context context,
+ krb5_keytab_entry *entry,
+ krb5_storage *sp)
{
- struct krb4_kt_data *d = id->data;
krb5_error_code ret;
- int fd;
#define ANAME_SZ 40
#define INST_SZ 40
#define REALM_SZ 40
char service[ANAME_SZ];
char instance[INST_SZ];
char realm[REALM_SZ];
- int8_t kvno;
+ ret = krb5_524_conv_principal (context, entry->principal,
+ service, instance, realm);
+ if (ret)
+ return ret;
+ if (entry->keyblock.keyvalue.length == 8
+ && entry->keyblock.keytype == ETYPE_DES_CBC_MD5) {
+ ret = krb5_store_stringz(sp, service);
+ ret = krb5_store_stringz(sp, instance);
+ ret = krb5_store_stringz(sp, realm);
+ ret = krb5_store_int8(sp, entry->vno);
+ ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, 8);
+ }
+ return 0;
+}
+
+static krb5_error_code
+krb4_kt_add_entry (krb5_context context,
+ krb5_keytab id,
+ krb5_keytab_entry *entry)
+{
+ struct krb4_kt_data *d = id->data;
+ krb5_storage *sp;
+ krb5_error_code ret;
+ int fd;
- fd = open (d->filename, O_WRONLY | O_APPEND | O_BINARY);
+ fd = open_flock (d->filename, O_WRONLY | O_APPEND | O_BINARY, 0);
if (fd < 0) {
- fd = open (d->filename,
+ fd = open_flock (d->filename,
O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600);
- if (fd < 0)
- return errno;
+ if (fd < 0) {
+ ret = errno;
+ krb5_set_error_string(context, "open(%s): %s", d->filename,
+ strerror(ret));
+ return ret;
+ }
}
- ret = krb5_524_conv_principal (context, entry->principal,
- service, instance, realm);
+ sp = krb5_storage_from_fd(fd);
+ if(sp == NULL) {
+ close(fd);
+ return ENOMEM;
+ }
+ krb5_storage_set_eof_code(sp, KRB5_KT_END);
+ ret = krb4_store_keytab_entry(context, entry, sp);
+ krb5_storage_free(sp);
+ if(close (fd) < 0)
+ return errno;
+ return ret;
+}
+
+static krb5_error_code
+krb4_kt_remove_entry(krb5_context context,
+ krb5_keytab id,
+ krb5_keytab_entry *entry)
+{
+ struct krb4_kt_data *d = id->data;
+ krb5_error_code ret;
+ krb5_keytab_entry e;
+ krb5_kt_cursor cursor;
+ krb5_storage *sp;
+ int remove_flag = 0;
+
+ sp = krb5_storage_emem();
+ if (sp == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
+ ret = krb5_kt_start_seq_get(context, id, &cursor);
if (ret) {
- close (fd);
+ krb5_storage_free(sp);
return ret;
+ }
+ while(krb5_kt_next_entry(context, id, &e, &cursor) == 0) {
+ if(!krb5_kt_compare(context, &e, entry->principal,
+ entry->vno, entry->keyblock.keytype)) {
+ ret = krb4_store_keytab_entry(context, &e, sp);
+ if(ret) {
+ krb5_kt_free_entry(context, &e);
+ krb5_storage_free(sp);
+ return ret;
+ }
+ } else
+ remove_flag = 1;
+ krb5_kt_free_entry(context, &e);
}
- if (entry->keyblock.keyvalue.length == 8
- && entry->keyblock.keytype == ETYPE_DES_CBC_MD5) {
- write(fd, service, strlen(service)+1);
- write(fd, instance, strlen(instance)+1);
- write(fd, realm, strlen(realm)+1);
- kvno = entry->vno;
- write(fd, &kvno, sizeof(kvno));
- write(fd, entry->keyblock.keyvalue.data, 8);
+ krb5_kt_end_seq_get(context, id, &cursor);
+ if(remove_flag) {
+ int fd;
+ unsigned char buf[1024];
+ ssize_t n;
+ krb5_data data;
+ struct stat st;
+
+ krb5_storage_to_data(sp, &data);
+ krb5_storage_free(sp);
+
+ fd = open_flock (d->filename, O_RDWR | O_BINARY, 0);
+ if(fd < 0) {
+ memset(data.data, 0, data.length);
+ krb5_data_free(&data);
+ if(errno == EACCES || errno == EROFS)
+ return KRB5_KT_NOWRITE;
+ return errno;
+ }
+
+ if(write(fd, data.data, data.length) != data.length) {
+ memset(data.data, 0, data.length);
+ krb5_data_free(&data);
+ close(fd);
+ krb5_set_error_string(context, "failed writing to \"%s\"", d->filename);
+ return errno;
+ }
+ memset(data.data, 0, data.length);
+ if(fstat(fd, &st) < 0) {
+ krb5_data_free(&data);
+ close(fd);
+ krb5_set_error_string(context, "failed getting size of \"%s\"", d->filename);
+ return errno;
+ }
+ st.st_size -= data.length;
+ memset(buf, 0, sizeof(buf));
+ while(st.st_size > 0) {
+ n = min(st.st_size, sizeof(buf));
+ n = write(fd, buf, n);
+ if(n <= 0) {
+ krb5_data_free(&data);
+ close(fd);
+ krb5_set_error_string(context, "failed writing to \"%s\"", d->filename);
+ return errno;
+
+ }
+ st.st_size -= n;
+ }
+ if(ftruncate(fd, data.length) < 0) {
+ krb5_data_free(&data);
+ close(fd);
+ krb5_set_error_string(context, "failed truncating \"%s\"", d->filename);
+ return errno;
+ }
+ krb5_data_free(&data);
+ if(close(fd) < 0) {
+ krb5_set_error_string(context, "error closing \"%s\"", d->filename);
+ return errno;
+ }
+ return 0;
+ } else {
+ krb5_storage_free(sp);
+ return KRB5_KT_NOTFOUND;
}
- close (fd);
- return 0;
}
+
const krb5_kt_ops krb4_fkt_ops = {
"krb4",
krb4_kt_resolve,
@@ -270,5 +431,18 @@ const krb5_kt_ops krb4_fkt_ops = {
krb4_kt_next_entry,
krb4_kt_end_seq_get,
krb4_kt_add_entry, /* add_entry */
- NULL /* remove_entry */
+ krb4_kt_remove_entry /* remove_entry */
+};
+
+const krb5_kt_ops krb5_srvtab_fkt_ops = {
+ "SRVTAB",
+ krb4_kt_resolve,
+ krb4_kt_get_name,
+ krb4_kt_close,
+ NULL, /* get */
+ krb4_kt_start_seq_get,
+ krb4_kt_next_entry,
+ krb4_kt_end_seq_get,
+ krb4_kt_add_entry, /* add_entry */
+ krb4_kt_remove_entry /* remove_entry */
};
diff --git a/kerberosV/src/lib/krb5/log.c b/kerberosV/src/lib/krb5/log.c
index 67f21e95933..2ab8af9bc2c 100644
--- a/kerberosV/src/lib/krb5/log.c
+++ b/kerberosV/src/lib/krb5/log.c
@@ -301,6 +301,7 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
ret = errno;
krb5_set_error_string (context, "open(%s): %s", fn,
strerror(ret));
+ free(fn);
return ret;
}
file = fdopen(i, "a");
@@ -309,6 +310,7 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
close(i);
krb5_set_error_string (context, "fdopen(%s): %s", fn,
strerror(ret));
+ free(fn);
return ret;
}
keep_open = 1;
diff --git a/kerberosV/src/lib/krb5/mk_req_ext.c b/kerberosV/src/lib/krb5/mk_req_ext.c
index 18faf1d7f57..3ad4bbf0437 100644
--- a/kerberosV/src/lib/krb5/mk_req_ext.c
+++ b/kerberosV/src/lib/krb5/mk_req_ext.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,17 +33,17 @@
#include <krb5_locl.h>
-RCSID("$KTH: mk_req_ext.c,v 1.24 2000/11/15 07:01:26 assar Exp $");
+RCSID("$KTH: mk_req_ext.c,v 1.30 2005/01/05 06:31:01 lukeh Exp $");
krb5_error_code
-krb5_mk_req_internal(krb5_context context,
- krb5_auth_context *auth_context,
- const krb5_flags ap_req_options,
- krb5_data *in_data,
- krb5_creds *in_creds,
- krb5_data *outbuf,
- krb5_key_usage checksum_usage,
- krb5_key_usage encrypt_usage)
+_krb5_mk_req_internal(krb5_context context,
+ krb5_auth_context *auth_context,
+ const krb5_flags ap_req_options,
+ krb5_data *in_data,
+ krb5_creds *in_creds,
+ krb5_data *outbuf,
+ krb5_key_usage checksum_usage,
+ krb5_key_usage encrypt_usage)
{
krb5_error_code ret;
krb5_data authenticator;
@@ -62,6 +62,12 @@ krb5_mk_req_internal(krb5_context context,
if(ret)
return ret;
+ if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) {
+ ret = krb5_auth_con_generatelocalsubkey(context, ac, &in_creds->session);
+ if(ret)
+ goto out;
+ }
+
#if 0
{
/* This is somewhat bogus since we're possibly overwriting a
@@ -87,7 +93,9 @@ krb5_mk_req_internal(krb5_context context,
#endif
krb5_free_keyblock(context, ac->keyblock);
- krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock);
+ ret = krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock);
+ if (ret)
+ goto out;
/* it's unclear what type of checksum we can use. try the best one, except:
* a) if it's configured differently for the current realm, or
@@ -99,29 +107,43 @@ krb5_mk_req_internal(krb5_context context,
/* this is to make DCE secd (and older MIT kdcs?) happy */
ret = krb5_create_checksum(context,
NULL,
+ 0,
CKSUMTYPE_RSA_MD4,
in_data->data,
in_data->length,
&c);
+ } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 ||
+ ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) {
+ /* this is to make MS kdc happy */
+ ret = krb5_create_checksum(context,
+ NULL,
+ 0,
+ CKSUMTYPE_RSA_MD5,
+ in_data->data,
+ in_data->length,
+ &c);
} else {
krb5_crypto crypto;
ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto);
if (ret)
- return ret;
+ goto out;
ret = krb5_create_checksum(context,
crypto,
checksum_usage,
+ 0,
in_data->data,
in_data->length,
&c);
-
- krb5_crypto_destroy(context, crypto);
+ krb5_crypto_destroy(context, crypto);
}
c_opt = &c;
} else {
c_opt = NULL;
}
+
+ if (ret)
+ goto out;
ret = krb5_build_authenticator (context,
ac,
@@ -134,16 +156,17 @@ krb5_mk_req_internal(krb5_context context,
if (c_opt)
free_Checksum (c_opt);
if (ret)
- return ret;
+ goto out;
ret = krb5_build_ap_req (context, ac->keyblock->keytype,
in_creds, ap_req_options, authenticator, outbuf);
+out:
if(auth_context == NULL)
krb5_auth_con_free(context, ac);
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_req_extended(krb5_context context,
krb5_auth_context *auth_context,
const krb5_flags ap_req_options,
@@ -151,7 +174,7 @@ krb5_mk_req_extended(krb5_context context,
krb5_creds *in_creds,
krb5_data *outbuf)
{
- return krb5_mk_req_internal (context,
+ return _krb5_mk_req_internal (context,
auth_context,
ap_req_options,
in_data,
diff --git a/kerberosV/src/lib/krb5/principal.c b/kerberosV/src/lib/krb5/principal.c
index 6145a7b912c..e5e7cccb972 100644
--- a/kerberosV/src/lib/krb5/principal.c
+++ b/kerberosV/src/lib/krb5/principal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2000 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -41,7 +41,7 @@
#include <fnmatch.h>
#include "resolve.h"
-RCSID("$KTH: principal.c,v 1.73 2000/10/16 03:42:14 assar Exp $");
+RCSID("$KTH: principal.c,v 1.88 2004/12/29 01:54:54 lha Exp $");
#define princ_num_comp(P) ((P)->name.name_string.len)
#define princ_type(P) ((P)->name.name_type)
@@ -49,7 +49,7 @@ RCSID("$KTH: principal.c,v 1.73 2000/10/16 03:42:14 assar Exp $");
#define princ_ncomp(P, N) ((P)->name.name_string.val[(N)])
#define princ_realm(P) ((P)->realm)
-void
+void KRB5_LIB_FUNCTION
krb5_free_principal(krb5_context context,
krb5_principal p)
{
@@ -59,17 +59,49 @@ krb5_free_principal(krb5_context context,
}
}
-krb5_error_code
+void KRB5_LIB_FUNCTION
+krb5_principal_set_type(krb5_context context,
+ krb5_principal principal,
+ int type)
+{
+ princ_type(principal) = type;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_principal_get_type(krb5_context context,
+ krb5_principal principal)
+{
+ return princ_type(principal);
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_principal_get_realm(krb5_context context,
+ krb5_principal principal)
+{
+ return princ_realm(principal);
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_principal_get_comp_string(krb5_context context,
+ krb5_principal principal,
+ unsigned int component)
+{
+ if(component >= princ_num_comp(principal))
+ return NULL;
+ return princ_ncomp(principal, component);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
krb5_parse_name(krb5_context context,
const char *name,
krb5_principal *principal)
{
krb5_error_code ret;
- general_string *comp;
- general_string realm;
+ heim_general_string *comp;
+ heim_general_string realm = NULL;
int ncomp;
- char *p;
+ const char *p;
char *q;
char *s;
char *start;
@@ -80,22 +112,28 @@ krb5_parse_name(krb5_context context,
/* count number of component */
ncomp = 1;
- for(p = (char*)name; *p; p++){
+ for(p = name; *p; p++){
if(*p=='\\'){
- if(!p[1])
+ if(!p[1]) {
+ krb5_set_error_string (context,
+ "trailing \\ in principal name");
return KRB5_PARSE_MALFORMED;
+ }
p++;
} else if(*p == '/')
ncomp++;
}
comp = calloc(ncomp, sizeof(*comp));
- if (comp == NULL)
+ if (comp == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
n = 0;
- start = q = p = s = strdup(name);
+ p = start = q = s = strdup(name);
if (start == NULL) {
free (comp);
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
while(*p){
@@ -110,13 +148,22 @@ krb5_parse_name(krb5_context context,
c = '\b';
else if(c == '0')
c = '\0';
+ else if(c == '\0') {
+ krb5_set_error_string (context,
+ "trailing \\ in principal name");
+ ret = KRB5_PARSE_MALFORMED;
+ goto exit;
+ }
}else if(c == '/' || c == '@'){
if(got_realm){
+ krb5_set_error_string (context,
+ "part after realm in principal name");
ret = KRB5_PARSE_MALFORMED;
goto exit;
}else{
comp[n] = malloc(q - start + 1);
if (comp[n] == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
ret = ENOMEM;
goto exit;
}
@@ -130,6 +177,8 @@ krb5_parse_name(krb5_context context,
continue;
}
if(got_realm && (c == ':' || c == '/' || c == '\0')) {
+ krb5_set_error_string (context,
+ "part after realm in principal name");
ret = KRB5_PARSE_MALFORMED;
goto exit;
}
@@ -138,6 +187,7 @@ krb5_parse_name(krb5_context context,
if(got_realm){
realm = malloc(q - start + 1);
if (realm == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
ret = ENOMEM;
goto exit;
}
@@ -150,6 +200,7 @@ krb5_parse_name(krb5_context context,
comp[n] = malloc(q - start + 1);
if (comp[n] == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
ret = ENOMEM;
goto exit;
}
@@ -159,6 +210,7 @@ krb5_parse_name(krb5_context context,
}
*principal = malloc(sizeof(**principal));
if (*principal == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
ret = ENOMEM;
goto exit;
}
@@ -173,6 +225,7 @@ exit:
free(comp[--n]);
}
free(comp);
+ free(realm);
free(s);
return ret;
}
@@ -235,7 +288,7 @@ unparse_name_fixed(krb5_context context,
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_unparse_name_fixed(krb5_context context,
krb5_const_principal principal,
char *name,
@@ -244,7 +297,7 @@ krb5_unparse_name_fixed(krb5_context context,
return unparse_name_fixed(context, principal, name, len, FALSE);
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_unparse_name_fixed_short(krb5_context context,
krb5_const_principal principal,
char *name,
@@ -277,16 +330,21 @@ unparse_name(krb5_context context,
len += 2*plen;
len++;
}
+ len++;
*name = malloc(len);
- if(len != 0 && *name == NULL)
+ if(*name == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
ret = unparse_name_fixed(context, principal, *name, len, short_flag);
- if(ret)
+ if(ret) {
free(*name);
+ *name = NULL;
+ }
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_unparse_name(krb5_context context,
krb5_const_principal principal,
char **name)
@@ -294,7 +352,7 @@ krb5_unparse_name(krb5_context context,
return unparse_name(context, principal, name, FALSE);
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_unparse_name_short(krb5_context context,
krb5_const_principal principal,
char **name)
@@ -304,7 +362,7 @@ krb5_unparse_name_short(krb5_context context,
#if 0 /* not implemented */
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_unparse_name_ext(krb5_context context,
krb5_const_principal principal,
char **name,
@@ -323,7 +381,7 @@ krb5_princ_realm(krb5_context context,
}
-void
+void KRB5_LIB_FUNCTION
krb5_princ_set_realm(krb5_context context,
krb5_principal principal,
krb5_realm *realm)
@@ -332,7 +390,7 @@ krb5_princ_set_realm(krb5_context context,
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_build_principal(krb5_context context,
krb5_principal *principal,
int rlen,
@@ -352,16 +410,20 @@ append_component(krb5_context context, krb5_principal p,
const char *comp,
size_t comp_len)
{
- general_string *tmp;
+ heim_general_string *tmp;
size_t len = princ_num_comp(p);
tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp));
- if(tmp == NULL)
+ if(tmp == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
princ_comp(p) = tmp;
princ_ncomp(p, len) = malloc(comp_len + 1);
- if (princ_ncomp(p, len) == NULL)
+ if (princ_ncomp(p, len) == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
memcpy (princ_ncomp(p, len), comp, comp_len);
princ_ncomp(p, len)[comp_len] = '\0';
princ_num_comp(p)++;
@@ -406,13 +468,16 @@ build_principal(krb5_context context,
krb5_principal p;
p = calloc(1, sizeof(*p));
- if (p == NULL)
+ if (p == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
princ_type(p) = KRB5_NT_PRINCIPAL;
princ_realm(p) = strdup(realm);
if(p->realm == NULL){
free(p);
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
@@ -421,7 +486,7 @@ build_principal(krb5_context context,
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_make_principal(krb5_context context,
krb5_principal *principal,
krb5_const_realm realm,
@@ -444,7 +509,7 @@ krb5_make_principal(krb5_context context,
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_build_principal_va(krb5_context context,
krb5_principal *principal,
int rlen,
@@ -454,7 +519,7 @@ krb5_build_principal_va(krb5_context context,
return build_principal(context, principal, rlen, realm, va_princ, ap);
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_build_principal_va_ext(krb5_context context,
krb5_principal *principal,
int rlen,
@@ -465,7 +530,7 @@ krb5_build_principal_va_ext(krb5_context context,
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_build_principal_ext(krb5_context context,
krb5_principal *principal,
int rlen,
@@ -481,16 +546,21 @@ krb5_build_principal_ext(krb5_context context,
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_principal(krb5_context context,
krb5_const_principal inprinc,
krb5_principal *outprinc)
{
krb5_principal p = malloc(sizeof(*p));
- if (p == NULL)
+ if (p == NULL) {
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
- if(copy_Principal(inprinc, p))
+ }
+ if(copy_Principal(inprinc, p)) {
+ free(p);
+ krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
+ }
*outprinc = p;
return 0;
}
@@ -499,7 +569,7 @@ krb5_copy_principal(krb5_context context,
* return TRUE iff princ1 == princ2 (without considering the realm)
*/
-krb5_boolean
+krb5_boolean KRB5_LIB_FUNCTION
krb5_principal_compare_any_realm(krb5_context context,
krb5_const_principal princ1,
krb5_const_principal princ2)
@@ -518,7 +588,7 @@ krb5_principal_compare_any_realm(krb5_context context,
* return TRUE iff princ1 == princ2
*/
-krb5_boolean
+krb5_boolean KRB5_LIB_FUNCTION
krb5_principal_compare(krb5_context context,
krb5_const_principal princ1,
krb5_const_principal princ2)
@@ -532,7 +602,7 @@ krb5_principal_compare(krb5_context context,
* return TRUE iff realm(princ1) == realm(princ2)
*/
-krb5_boolean
+krb5_boolean KRB5_LIB_FUNCTION
krb5_realm_compare(krb5_context context,
krb5_const_principal princ1,
krb5_const_principal princ2)
@@ -544,7 +614,7 @@ krb5_realm_compare(krb5_context context,
* return TRUE iff princ matches pattern
*/
-krb5_boolean
+krb5_boolean KRB5_LIB_FUNCTION
krb5_principal_match(krb5_context context,
krb5_const_principal princ,
krb5_const_principal pattern)
@@ -562,7 +632,7 @@ krb5_principal_match(krb5_context context,
}
-struct v4_name_convert {
+static struct v4_name_convert {
const char *from;
const char *to;
} default_v4_name_convert[] = {
@@ -571,6 +641,7 @@ struct v4_name_convert {
{ "pop", "pop" },
{ "imap", "imap" },
{ "rcmd", "host" },
+ { "smtp", "smtp" },
{ NULL, NULL }
};
@@ -624,7 +695,7 @@ get_name_conversion(krb5_context context, const char *realm, const char *name)
* if `func', use that function for validating the conversion
*/
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_425_conv_principal_ext(krb5_context context,
const char *name,
const char *instance,
@@ -637,6 +708,7 @@ krb5_425_conv_principal_ext(krb5_context context,
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 is assumed to be a `host' type
@@ -667,48 +739,89 @@ krb5_425_conv_principal_ext(krb5_context context,
}
krb5_free_principal(context, pr);
*princ = NULL;
+ krb5_clear_error_string (context);
return HEIM_ERR_V4_PRINC_NO_CONV;
}
if(resolve){
- const char *inst = NULL;
+ krb5_boolean passed = FALSE;
+ char *inst = NULL;
#ifdef USE_RESOLVER
struct dns_reply *r;
- r = dns_lookup(instance, "a");
- if(r && r->head && r->head->type == T_A)
- inst = r->head->domain;
-#else
- struct hostent *hp = roken_gethostbyname(instance);
- if(hp)
- inst = hp->h_name;
-#endif
- if(inst) {
- char *low_inst = strdup(inst);
- if (low_inst == NULL) {
-#ifdef USE_RESOLVER
+ r = dns_lookup(instance, "aaaa");
+ if (r && r->head && r->head->type == T_AAAA) {
+ inst = strdup(r->head->domain);
+ dns_free_data(r);
+ passed = TRUE;
+ } else {
+ r = dns_lookup(instance, "a");
+ if(r && r->head && r->head->type == T_A) {
+ inst = strdup(r->head->domain);
dns_free_data(r);
+ passed = TRUE;
+ }
+ }
+#else
+ struct addrinfo hints, *ai;
+ int ret;
+
+ 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_string (context, "malloc: out of memory");
return ENOMEM;
}
- ret = krb5_make_principal(context, &pr, realm, name, low_inst,
+ strlwr(inst);
+ ret = krb5_make_principal(context, &pr, realm, name, inst,
NULL);
- free (low_inst);
+ free (inst);
if(ret == 0) {
if(func == NULL || (*func)(context, pr)){
*princ = pr;
-#ifdef USE_RESOLVER
- dns_free_data(r);
-#endif
return 0;
}
krb5_free_principal(context, pr);
}
}
-#ifdef USE_RESOLVER
- if(r)
- dns_free_data(r);
-#endif
}
+ if(func != NULL) {
+ snprintf(host, sizeof(host), "%s.%s", instance, realm);
+ strlwr(host);
+ ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+ if((*func)(context, 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,
@@ -725,24 +838,27 @@ krb5_425_conv_principal_ext(krb5_context context,
}
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_string (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(func == NULL || (*func)(context, pr)){
*princ = pr;
return 0;
}
krb5_free_principal(context, pr);
+ krb5_clear_error_string (context);
return HEIM_ERR_V4_PRINC_NO_CONV;
no_host:
p = krb5_config_get_string(context, NULL,
@@ -768,10 +884,11 @@ no_host:
return 0;
}
krb5_free_principal(context, pr);
+ krb5_clear_error_string (context);
return HEIM_ERR_V4_PRINC_NO_CONV;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_425_conv_principal(krb5_context context,
const char *name,
const char *instance,
@@ -864,7 +981,7 @@ name_convert(krb5_context context, const char *name, const char *realm,
* three parameters. They have to be 40 bytes each (ANAME_SZ).
*/
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_524_conv_principal(krb5_context context,
const krb5_principal principal,
char *name,
@@ -888,6 +1005,9 @@ krb5_524_conv_principal(krb5_context context,
i = principal->name.name_string.val[1];
break;
default:
+ krb5_set_error_string (context,
+ "cannot convert a %d component principal",
+ principal->name.name_string.len);
return KRB5_PARSE_MALFORMED;
}
@@ -910,12 +1030,21 @@ krb5_524_conv_principal(krb5_context context,
i = tmpinst;
}
- if (strlcpy (name, n, aname_sz) >= aname_sz)
+ if (strlcpy (name, n, aname_sz) >= aname_sz) {
+ krb5_set_error_string (context,
+ "too long name component to convert");
return KRB5_PARSE_MALFORMED;
- if (strlcpy (instance, i, aname_sz) >= aname_sz)
+ }
+ if (strlcpy (instance, i, aname_sz) >= aname_sz) {
+ krb5_set_error_string (context,
+ "too long instance component to convert");
return KRB5_PARSE_MALFORMED;
- if (strlcpy (realm, r, aname_sz) >= aname_sz)
+ }
+ if (strlcpy (realm, r, aname_sz) >= aname_sz) {
+ krb5_set_error_string (context,
+ "too long realm component to convert");
return KRB5_PARSE_MALFORMED;
+ }
return 0;
}
@@ -923,7 +1052,7 @@ krb5_524_conv_principal(krb5_context context,
* Create a principal in `ret_princ' for the service `sname' running
* on host `hostname'. */
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_sname_to_principal (krb5_context context,
const char *hostname,
const char *sname,
@@ -934,8 +1063,11 @@ krb5_sname_to_principal (krb5_context context,
char localhost[MAXHOSTNAMELEN];
char **realms, *host = NULL;
- if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN)
+ if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) {
+ krb5_set_error_string (context, "unsupported name type %d",
+ type);
return KRB5_SNAME_UNSUPP_NAMETYPE;
+ }
if(hostname == NULL) {
gethostname(localhost, sizeof(localhost));
hostname = localhost;
diff --git a/kerberosV/src/lib/krb5/rd_req.c b/kerberosV/src/lib/krb5/rd_req.c
index 1ff1ab920bb..b37d41314cc 100644
--- a/kerberosV/src/lib/krb5/rd_req.c
+++ b/kerberosV/src/lib/krb5/rd_req.c
@@ -271,8 +271,10 @@ krb5_verify_authenticator_checksum(krb5_context context,
&authenticator);
if(ret)
return ret;
- if(authenticator->cksum == NULL)
+ if(authenticator->cksum == NULL) {
+ krb5_free_authenticator(context, &authenticator);
return -17;
+ }
ret = krb5_auth_con_getkey(context, ac, &key);
if(ret) {
krb5_free_authenticator(context, &authenticator);
diff --git a/kerberosV/src/lib/krb5/store.c b/kerberosV/src/lib/krb5/store.c
index cf2aadc95d8..b9b2ad8f2dc 100644
--- a/kerberosV/src/lib/krb5/store.c
+++ b/kerberosV/src/lib/krb5/store.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2000 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,28 +32,72 @@
*/
#include "krb5_locl.h"
+#include "store-int.h"
-RCSID("$KTH: store.c,v 1.34 2000/04/11 00:46:09 assar Exp $");
+RCSID("$KTH: store.c,v 1.49 2005/06/01 10:40:05 lha Exp $");
-void
+#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
+#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
+#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
+#define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \
+ krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER))
+
+void KRB5_LIB_FUNCTION
krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
{
sp->flags |= flags;
}
-void
+void KRB5_LIB_FUNCTION
krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
{
sp->flags &= ~flags;
}
-krb5_boolean
+krb5_boolean KRB5_LIB_FUNCTION
krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
{
return (sp->flags & flags) == flags;
}
-ssize_t
+void KRB5_LIB_FUNCTION
+krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
+{
+ sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
+ sp->flags |= byteorder;
+}
+
+krb5_flags KRB5_LIB_FUNCTION
+krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder)
+{
+ return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
+}
+
+off_t KRB5_LIB_FUNCTION
+krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
+{
+ return (*sp->seek)(sp, offset, whence);
+}
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
+{
+ return sp->fetch(sp, buf, len);
+}
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
+{
+ return sp->store(sp, buf, len);
+}
+
+void KRB5_LIB_FUNCTION
+krb5_storage_set_eof_code(krb5_storage *sp, int code)
+{
+ sp->eof_code = code;
+}
+
+krb5_ssize_t KRB5_LIB_FUNCTION
_krb5_put_int(void *buffer, unsigned long value, size_t size)
{
unsigned char *p = buffer;
@@ -65,7 +109,7 @@ _krb5_put_int(void *buffer, unsigned long value, size_t size)
return size;
}
-ssize_t
+krb5_ssize_t KRB5_LIB_FUNCTION
_krb5_get_int(void *buffer, unsigned long *value, size_t size)
{
unsigned char *p = buffer;
@@ -77,7 +121,7 @@ _krb5_get_int(void *buffer, unsigned long *value, size_t size)
return size;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_storage_free(krb5_storage *sp)
{
if(sp->free)
@@ -87,7 +131,7 @@ krb5_storage_free(krb5_storage *sp)
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
{
off_t pos;
@@ -115,21 +159,25 @@ krb5_store_int(krb5_storage *sp,
size_t len)
{
int ret;
- unsigned char v[4];
+ unsigned char v[16];
+ if(len > sizeof(v))
+ return EINVAL;
_krb5_put_int(v, value, len);
ret = sp->store(sp, v, len);
if (ret != len)
- return (ret<0)?errno:KRB5_CC_END;
+ return (ret<0)?errno:sp->eof_code;
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int32(krb5_storage *sp,
int32_t value)
{
- if(krb5_storage_is_flags(sp, KRB5_STORAGE_HOST_BYTEORDER))
+ if(BYTEORDER_IS_HOST(sp))
value = htonl(value);
+ else if(BYTEORDER_IS_LE(sp))
+ value = bswap32(value);
return krb5_store_int(sp, value, 4);
}
@@ -143,34 +191,38 @@ krb5_ret_int(krb5_storage *sp,
unsigned long w;
ret = sp->fetch(sp, v, len);
if(ret != len)
- return (ret<0)?errno:KRB5_CC_END;
+ return (ret<0)?errno:sp->eof_code;
_krb5_get_int(v, &w, len);
*value = w;
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_int32(krb5_storage *sp,
int32_t *value)
{
krb5_error_code ret = krb5_ret_int(sp, value, 4);
if(ret)
return ret;
- if(krb5_storage_is_flags(sp, KRB5_STORAGE_HOST_BYTEORDER))
- *value = ntohl(*value);
+ if(BYTEORDER_IS_HOST(sp))
+ *value = htonl(*value);
+ else if(BYTEORDER_IS_LE(sp))
+ *value = bswap32(*value);
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int16(krb5_storage *sp,
int16_t value)
{
- if(krb5_storage_is_flags(sp, KRB5_STORAGE_HOST_BYTEORDER))
+ if(BYTEORDER_IS_HOST(sp))
value = htons(value);
+ else if(BYTEORDER_IS_LE(sp))
+ value = bswap16(value);
return krb5_store_int(sp, value, 2);
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_int16(krb5_storage *sp,
int16_t *value)
{
@@ -180,12 +232,14 @@ krb5_ret_int16(krb5_storage *sp,
if(ret)
return ret;
*value = v;
- if(krb5_storage_is_flags(sp, KRB5_STORAGE_HOST_BYTEORDER))
- *value = ntohs(*value);
+ if(BYTEORDER_IS_HOST(sp))
+ *value = htons(*value);
+ else if(BYTEORDER_IS_LE(sp))
+ *value = bswap16(*value);
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int8(krb5_storage *sp,
int8_t value)
{
@@ -193,11 +247,11 @@ krb5_store_int8(krb5_storage *sp,
ret = sp->store(sp, &value, sizeof(value));
if (ret != sizeof(value))
- return (ret<0)?errno:KRB5_CC_END;
+ return (ret<0)?errno:sp->eof_code;
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_int8(krb5_storage *sp,
int8_t *value)
{
@@ -205,11 +259,11 @@ krb5_ret_int8(krb5_storage *sp,
ret = sp->fetch(sp, value, sizeof(*value));
if (ret != sizeof(*value))
- return (ret<0)?errno:KRB5_CC_END;
+ return (ret<0)?errno:sp->eof_code;
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_data(krb5_storage *sp,
krb5_data data)
{
@@ -221,12 +275,12 @@ krb5_store_data(krb5_storage *sp,
if(ret != data.length){
if(ret < 0)
return errno;
- return KRB5_CC_END;
+ return sp->eof_code;
}
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_data(krb5_storage *sp,
krb5_data *data)
{
@@ -242,12 +296,12 @@ krb5_ret_data(krb5_storage *sp,
if (size) {
ret = sp->fetch(sp, data->data, size);
if(ret != size)
- return (ret < 0)? errno : KRB5_CC_END;
+ return (ret < 0)? errno : sp->eof_code;
}
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_string(krb5_storage *sp, const char *s)
{
krb5_data data;
@@ -256,7 +310,7 @@ krb5_store_string(krb5_storage *sp, const char *s)
return krb5_store_data(sp, data);
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_string(krb5_storage *sp,
char **string)
{
@@ -274,7 +328,7 @@ krb5_ret_string(krb5_storage *sp,
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_stringz(krb5_storage *sp, const char *s)
{
size_t len = strlen(s) + 1;
@@ -285,12 +339,12 @@ krb5_store_stringz(krb5_storage *sp, const char *s)
if(ret < 0)
return ret;
else
- return KRB5_CC_END;
+ return sp->eof_code;
}
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_stringz(krb5_storage *sp,
char **string)
{
@@ -316,7 +370,7 @@ krb5_ret_stringz(krb5_storage *sp,
if(ret != 1){
free(s);
if(ret == 0)
- return KRB5_CC_END;
+ return sp->eof_code;
return ret;
}
*string = s;
@@ -324,7 +378,7 @@ krb5_ret_stringz(krb5_storage *sp,
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_principal(krb5_storage *sp,
krb5_principal p)
{
@@ -350,7 +404,7 @@ krb5_store_principal(krb5_storage *sp,
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_principal(krb5_storage *sp,
krb5_principal *princ)
{
@@ -366,7 +420,7 @@ krb5_ret_principal(krb5_storage *sp,
if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
type = KRB5_NT_UNKNOWN;
- else if((ret = krb5_ret_int32(sp, &type))){
+ else if((ret = krb5_ret_int32(sp, &type))){
free(p);
return ret;
}
@@ -376,24 +430,37 @@ krb5_ret_principal(krb5_storage *sp,
}
if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
ncomp--;
+ if (ncomp < 0) {
+ free(p);
+ return EINVAL;
+ }
p->name.name_type = type;
p->name.name_string.len = ncomp;
ret = krb5_ret_string(sp, &p->realm);
- if(ret) return ret;
+ if(ret) {
+ free(p);
+ return ret;
+ }
p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val));
- if(p->name.name_string.val == NULL){
+ if(p->name.name_string.val == NULL && ncomp != 0){
free(p->realm);
return ENOMEM;
}
for(i = 0; i < ncomp; i++){
ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
- if(ret) return ret; /* XXX */
+ if(ret) {
+ while (i >= 0)
+ free(p->name.name_string.val[i--]);
+ free(p->realm);
+ free(p);
+ return ret;
+ }
}
*princ = p;
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
{
int ret;
@@ -411,7 +478,7 @@ krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
{
int ret;
@@ -430,7 +497,7 @@ krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_times(krb5_storage *sp, krb5_times times)
{
int ret;
@@ -444,7 +511,7 @@ krb5_store_times(krb5_storage *sp, krb5_times times)
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_times(krb5_storage *sp, krb5_times *times)
{
int ret;
@@ -463,7 +530,7 @@ krb5_ret_times(krb5_storage *sp, krb5_times *times)
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_address(krb5_storage *sp, krb5_address p)
{
int ret;
@@ -473,7 +540,7 @@ krb5_store_address(krb5_storage *sp, krb5_address p)
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_address(krb5_storage *sp, krb5_address *adr)
{
int16_t t;
@@ -485,7 +552,7 @@ krb5_ret_address(krb5_storage *sp, krb5_address *adr)
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
{
int i;
@@ -499,7 +566,7 @@ krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
{
int i;
@@ -510,6 +577,8 @@ krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
if(ret) return ret;
adr->len = tmp;
ALLOC(adr->val, adr->len);
+ if (adr->val == NULL && adr->len != 0)
+ return ENOMEM;
for(i = 0; i < adr->len; i++){
ret = krb5_ret_address(sp, &adr->val[i]);
if(ret) break;
@@ -517,7 +586,7 @@ krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
{
krb5_error_code ret;
@@ -533,7 +602,7 @@ krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
return 0;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
{
krb5_error_code ret;
@@ -543,6 +612,8 @@ krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
ret = krb5_ret_int32(sp, &tmp);
if(ret) return ret;
ALLOC_SEQ(auth, tmp);
+ if (auth->val == NULL && tmp != 0)
+ return ENOMEM;
for(i = 0; i < tmp; i++){
ret = krb5_ret_int16(sp, &tmp2);
if(ret) break;
@@ -553,50 +624,65 @@ krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
return ret;
}
+static int32_t
+bitswap32(int32_t b)
+{
+ int32_t r = 0;
+ int i;
+ for (i = 0; i < 32; i++) {
+ r = r << 1 | (b & 1);
+ b = b >> 1;
+ }
+ return r;
+}
+
+
/*
- * store `creds' on `sp' returning error or zero
+ *
*/
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
{
int ret;
ret = krb5_store_principal(sp, creds->client);
- if (ret)
+ if(ret)
return ret;
ret = krb5_store_principal(sp, creds->server);
- if (ret)
+ if(ret)
return ret;
ret = krb5_store_keyblock(sp, creds->session);
- if (ret)
+ if(ret)
return ret;
ret = krb5_store_times(sp, creds->times);
- if (ret)
+ if(ret)
return ret;
- ret = krb5_store_int8(sp, 0); /* this is probably the
- enc-tkt-in-skey bit from KDCOptions */
- if (ret)
+ ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
+ if(ret)
return ret;
- ret = krb5_store_int32(sp, creds->flags.i);
- if (ret)
+
+ if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER))
+ ret = krb5_store_int32(sp, creds->flags.i);
+ else
+ ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
+ if(ret)
return ret;
+
ret = krb5_store_addrs(sp, creds->addresses);
- if (ret)
+ if(ret)
return ret;
ret = krb5_store_authdata(sp, creds->authdata);
- if (ret)
+ if(ret)
return ret;
ret = krb5_store_data(sp, creds->ticket);
- if (ret)
+ if(ret)
return ret;
ret = krb5_store_data(sp, creds->second_ticket);
- if (ret)
- return ret;
- return 0;
+ return ret;
}
-krb5_error_code
+krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
{
krb5_error_code ret;
@@ -616,6 +702,22 @@ krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
if(ret) goto cleanup;
ret = krb5_ret_int32 (sp, &dummy32);
if(ret) goto cleanup;
+ /*
+ * Runtime detect the what is the higher bits of the bitfield. If
+ * any of the higher bits are set in the input data, its either a
+ * new ticket flag (and this code need to be removed), or its a
+ * MIT cache (or new Heimdal cache), lets change it to our current
+ * format.
+ */
+ {
+ u_int32_t mask = 0xffff0000;
+ creds->flags.i = 0;
+ creds->flags.b.anonymous = 1;
+ if (creds->flags.i & mask)
+ mask = ~mask;
+ if (dummy32 & mask)
+ dummy32 = bitswap32(dummy32);
+ }
creds->flags.i = dummy32;
ret = krb5_ret_addrs (sp, &creds->addresses);
if(ret) goto cleanup;
@@ -625,10 +727,176 @@ krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
if(ret) goto cleanup;
ret = krb5_ret_data (sp, &creds->second_ticket);
cleanup:
+ if(ret) {
+#if 0
+ krb5_free_cred_contents(context, creds); /* XXX */
+#endif
+ }
+ return ret;
+}
+
+#define SC_CLIENT_PRINCIPAL 0x0001
+#define SC_SERVER_PRINCIPAL 0x0002
+#define SC_SESSION_KEY 0x0004
+#define SC_TICKET 0x0008
+#define SC_SECOND_TICKET 0x0010
+#define SC_AUTHDATA 0x0020
+#define SC_ADDRESSES 0x0040
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_creds_tag(krb5_storage *sp,
+ krb5_creds *creds)
+{
+ int ret;
+ int32_t header = 0;
+
+ if (creds->client)
+ header |= SC_CLIENT_PRINCIPAL;
+ if (creds->server)
+ header |= SC_SERVER_PRINCIPAL;
+ if (creds->session.keyvalue.data)
+ header |= SC_SESSION_KEY;
+ if (creds->ticket.data)
+ header |= SC_TICKET;
+ if (creds->second_ticket.length)
+ header |= SC_SECOND_TICKET;
+ if (creds->authdata.len)
+ header |= SC_AUTHDATA;
+ if (creds->addresses.len)
+ header |= SC_ADDRESSES;
+
+ ret = krb5_store_int32(sp, header);
+
+ if (creds->client) {
+ ret = krb5_store_principal(sp, creds->client);
+ if(ret)
+ return ret;
+ }
+
+ if (creds->server) {
+ ret = krb5_store_principal(sp, creds->server);
+ if(ret)
+ return ret;
+ }
+
+ if (creds->session.keyvalue.data) {
+ ret = krb5_store_keyblock(sp, creds->session);
+ if(ret)
+ return ret;
+ }
+
+ ret = krb5_store_times(sp, creds->times);
+ if(ret)
+ return ret;
+ ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
if(ret)
+ return ret;
+
+ ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
+ if(ret)
+ return ret;
+
+ if (creds->addresses.len) {
+ ret = krb5_store_addrs(sp, creds->addresses);
+ if(ret)
+ return ret;
+ }
+
+ if (creds->authdata.len) {
+ ret = krb5_store_authdata(sp, creds->authdata);
+ if(ret)
+ return ret;
+ }
+
+ if (creds->ticket.data) {
+ ret = krb5_store_data(sp, creds->ticket);
+ if(ret)
+ return ret;
+ }
+
+ if (creds->second_ticket.data) {
+ ret = krb5_store_data(sp, creds->second_ticket);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_creds_tag(krb5_storage *sp,
+ krb5_creds *creds)
+{
+ krb5_error_code ret;
+ int8_t dummy8;
+ int32_t dummy32, header;
+
+ memset(creds, 0, sizeof(*creds));
+
+ ret = krb5_ret_int32 (sp, &header);
+ if (ret) goto cleanup;
+
+ if (header & SC_CLIENT_PRINCIPAL) {
+ ret = krb5_ret_principal (sp, &creds->client);
+ if(ret) goto cleanup;
+ }
+ if (header & SC_SERVER_PRINCIPAL) {
+ ret = krb5_ret_principal (sp, &creds->server);
+ if(ret) goto cleanup;
+ }
+ if (header & SC_SESSION_KEY) {
+ ret = krb5_ret_keyblock (sp, &creds->session);
+ if(ret) goto cleanup;
+ }
+ ret = krb5_ret_times (sp, &creds->times);
+ if(ret) goto cleanup;
+ ret = krb5_ret_int8 (sp, &dummy8);
+ if(ret) goto cleanup;
+ ret = krb5_ret_int32 (sp, &dummy32);
+ if(ret) goto cleanup;
+ /*
+ * Runtime detect the what is the higher bits of the bitfield. If
+ * any of the higher bits are set in the input data, its either a
+ * new ticket flag (and this code need to be removed), or its a
+ * MIT cache (or new Heimdal cache), lets change it to our current
+ * format.
+ */
+ {
+ u_int32_t mask = 0xffff0000;
+ creds->flags.i = 0;
+ creds->flags.b.anonymous = 1;
+ if (creds->flags.i & mask)
+ mask = ~mask;
+ if (dummy32 & mask)
+ dummy32 = bitswap32(dummy32);
+ }
+ creds->flags.i = dummy32;
+ if (header & SC_ADDRESSES) {
+ ret = krb5_ret_addrs (sp, &creds->addresses);
+ if(ret) goto cleanup;
+ }
+ if (header & SC_AUTHDATA) {
+ ret = krb5_ret_authdata (sp, &creds->authdata);
+ if(ret) goto cleanup;
+ }
+ if (header & SC_TICKET) {
+ ret = krb5_ret_data (sp, &creds->ticket);
+ if(ret) goto cleanup;
+ }
+ if (header & SC_SECOND_TICKET) {
+ ret = krb5_ret_data (sp, &creds->second_ticket);
+ if(ret) goto cleanup;
+ }
+
+cleanup:
+ if(ret) {
#if 0
- krb5_free_creds_contents(context, creds) /* XXX */
+ krb5_free_cred_contents(context, creds); /* XXX */
#endif
- ;
+ }
return ret;
}
diff --git a/kerberosV/src/lib/krb5/transited.c b/kerberosV/src/lib/krb5/transited.c
index 4635a7d71d2..b617625b331 100644
--- a/kerberosV/src/lib/krb5/transited.c
+++ b/kerberosV/src/lib/krb5/transited.c
@@ -100,8 +100,10 @@ make_path(krb5_context context, struct tr_realm *r,
p = from + strlen(from);
while(1){
while(p >= from && *p != '/') p--;
- if(p == from)
+ if(p == from) {
+ r->next = path; /* XXX */
return KRB5KDC_ERR_POLICY;
+ }
if(strncmp(to, from, p - from) == 0)
break;
tmp = calloc(1, sizeof(*tmp));