summaryrefslogtreecommitdiffstats
path: root/src/util
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2007-08-16 22:55:06 +0000
committerKen Raeburn <raeburn@mit.edu>2007-08-16 22:55:06 +0000
commitc15ec7751a7d7c1d97dbeb1dd88dda2a328515e0 (patch)
tree824bd8c158b1c5b72913515953c7e8576399d912 /src/util
parent9db2f5eb745287654117e70032d05dd9f5a91a3f (diff)
remap mechanism-specific status codes in mechglue/spnego
This patch creates a mapping in the mechglue/spnego code to modify mechanism status codes when passing them back to the application, so that mechglue's display_status dispatcher can determine the correct mechanism to dispatch to. This is part of the "get enhanced error messages from gssapi applications" project; ticket 5590 has updates to the Kerberos 5 mechanism to extract enhanced error messages (when there are any) from the Kerberos library. util/gen.pl, util/t_*.pm: New code generation script and templates. lib/gssapi/generic: Add a new, global mapping that enumerates the {mechOID,status} pairs as they're seen, allowing a magic mechOID value to indicate com_err error codes from mechglue and spnego, and reserving status code 0 for unknown errors. Preload the Kerberos "wrong principal" error code once for each mechanism OID used for Kerberos, so the entries get fixed positions (1-3) in the table. lib/gssapi/gss_libinit.c: Call the initializer and destructor functions. lib/gssapi/mechglue, lib/gssapi/spnego: Enter all mechanism-generated or locally-generated status codes into the mapping table, and return the table index to the application. Do the reverse in display_status, to get the messages from the mechanism.. lib/rpc: Define new function gssrpcint_printf to use for debugging instead of printf, to redirect output away from dejagnu; add a couple more debugging calls. Check for minor status codes 1-3 now instead of KRB5KRB_AP_WRONG_PRINC. tests/dejagnu/krb-standalone/gssftp.exp: Test getting more detailed error messages back, by having the ftp client attempt to authenticate to a non-existent service, and examining the error message for the service principal name. ticket: new git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19831 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/util')
-rw-r--r--src/util/gen.pl61
-rw-r--r--src/util/t_array.pm129
-rw-r--r--src/util/t_enum.pm133
-rw-r--r--src/util/t_template.pm61
-rw-r--r--src/util/t_tsenum.pm163
5 files changed, 547 insertions, 0 deletions
diff --git a/src/util/gen.pl b/src/util/gen.pl
new file mode 100644
index 000000000..9d2a3a180
--- /dev/null
+++ b/src/util/gen.pl
@@ -0,0 +1,61 @@
+# -*- perl -*-
+
+# Crude template instantiation hack.
+#
+# The template named on the command line maps to a perl module t_$foo
+# which defines certain methods including variable processing and
+# output generation. It can also suck in additional template modules
+# for internal use. One output file is generated, which typically
+# contains structures and inline functions, and should be included by
+# other files which will define, for example, the typedefname
+# parameters supplied to this script.
+
+# To do:
+# Find a way to make dependency generation automatic.
+# Make it less gross.
+
+sub usage {
+ print STDERR "usage: $0 TemplateName [-oOutputFile] PARM=value ...\n";
+ print STDERR " where acceptable PARM values depend on the template\n";
+ exit(1);
+}
+
+my $orig_args = join(" ", @ARGV);
+my $templatename = shift @ARGV || &usage;
+my $outfile = shift @ARGV || &usage;
+my $x;
+
+eval "require t_$templatename;" || die;
+eval "\$x = new t_$templatename;" || die;
+
+sub getparms {
+ my $arg;
+ my $outfile;
+ my %allowed_parms = ();
+
+ foreach $arg (@ARGV) {
+ my @words = split '=', $arg;
+ if ($#words != 1) {
+ print STDERR "$0: $arg : #words = $#words\n";
+ &usage;
+ }
+ $x->setparm($words[0], $words[1]);
+ }
+}
+
+sub generate {
+ open OUTFILE, ">$outfile" || die;
+ print OUTFILE "/*\n";
+ print OUTFILE " * This file is generated, please don't edit it.\n";
+ print OUTFILE " * script: $0\n";
+ print OUTFILE " * args: $orig_args\n";
+ print OUTFILE " * The rest of this file is copied from a template, with\n";
+ print OUTFILE " * substitutions. See the template for copyright info.\n";
+ print OUTFILE " */\n";
+ $x->output(\*OUTFILE);
+ close OUTFILE;
+}
+
+&getparms;
+&generate;
+exit (0);
diff --git a/src/util/t_array.pm b/src/util/t_array.pm
new file mode 100644
index 000000000..d4b217393
--- /dev/null
+++ b/src/util/t_array.pm
@@ -0,0 +1,129 @@
+package t_array;
+
+use strict;
+use vars qw(@ISA);
+
+#require ktemplate;
+require t_template;
+
+@ISA=qw(t_template);
+
+my @parms = qw(NAME TYPE);
+my %defaults = ( );
+my @templatelines = <DATA>;
+
+sub new { # no args
+ my $self = {};
+ bless $self;
+ $self->init(\@parms, \%defaults, \@templatelines);
+ return $self;
+}
+
+__DATA__
+
+/*
+ * array type, derived from template
+ *
+ * parameters:
+ * NAME: <NAME>
+ * TYPE: <TYPE>
+ *
+ * methods:
+ * int init() -> nonzero if fail initial allocation
+ * unsigned long size() -> nonnegative number of values stored
+ * int grow(newsize) -> negative if fail allocation, memset(,0,) new space
+ * <TYPE> *getaddr(idx) -> aborts if out of range
+ * void set(idx, value) -> aborts if out of range
+ * <TYPE> get(idx) -> value, or aborts if out of range
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+
+struct <NAME>__header {
+ size_t allocated;
+ <TYPE> *elts;
+};
+typedef struct <NAME>__header <NAME>;
+
+static inline int
+<NAME>_init(<NAME> *arr)
+{
+ arr->elts = calloc(10, sizeof(<TYPE>));
+ if (arr->elts == NULL)
+ return ENOMEM;
+ arr->allocated = 10;
+ return 0;
+}
+
+static inline long
+<NAME>_size(<NAME> *arr)
+{
+ return arr->allocated;
+}
+
+static inline long
+<NAME>_max_size(<NAME> *arr)
+{
+ size_t upper_bound;
+
+ upper_bound = SIZE_MAX / sizeof(*arr->elts);
+ if (upper_bound > LONG_MAX)
+ upper_bound = LONG_MAX;
+ return (long) upper_bound;
+}
+
+static inline int
+<NAME>_grow(<NAME> *arr, unsigned long newcount)
+{
+ size_t oldsize = sizeof(*arr->elts) * arr->allocated;
+ size_t newsize;
+ void *ptr;
+
+ if (newcount > LONG_MAX)
+ return -1;
+ if (newcount < arr->allocated)
+ return 0;
+ if (newcount > <NAME>_max_size(arr))
+ return -1;
+
+ newsize = sizeof(*arr->elts) * newcount;
+ ptr = realloc(arr->elts, newsize);
+ if (ptr == NULL)
+ return -1;
+ memset((char *)arr->elts + oldsize, 0, newsize - oldsize);
+ arr->elts = ptr;
+ arr->allocated = newcount;
+ return 0;
+}
+
+static inline <TYPE> *
+<NAME>_getaddr (<NAME> *arr, long idx)
+{
+ if (idx < 0 || idx >= arr->allocated)
+ abort();
+ return arr->elts + idx;
+}
+
+static inline void
+<NAME>_set (<NAME> *arr, long idx, <TYPE> value)
+{
+ <TYPE> *newvalp;
+ newvalp = <NAME>_getaddr(arr, idx);
+ *newvalp = value;
+}
+
+static inline <TYPE>
+<NAME>_get (<NAME> *arr, long idx)
+{
+ return *<NAME>_getaddr(arr, idx);
+}
+
+static inline void
+<NAME>_destroy (<NAME> *arr)
+{
+ free(arr->elts);
+ arr->elts = 0;
+}
diff --git a/src/util/t_enum.pm b/src/util/t_enum.pm
new file mode 100644
index 000000000..e62bfce5a
--- /dev/null
+++ b/src/util/t_enum.pm
@@ -0,0 +1,133 @@
+package t_enum;
+
+use strict;
+use vars qw(@ISA);
+
+#require ktemplate;
+require t_template;
+require t_array;
+
+@ISA=qw(t_template);
+
+my @parms = qw(NAME TYPE COMPARE);
+my %defaults = ( );
+my @templatelines = <DATA>;
+
+sub new { # no args
+ my $self = {};
+ bless $self;
+ $self->init(\@parms, \%defaults, \@templatelines);
+ return $self;
+}
+
+sub output {
+ my ($self, $fh) = @_;
+ my $a = new t_array;
+ $a->setparm("NAME", $self->{values}{"NAME"} . "__enumerator_array");
+ $a->setparm("TYPE", $self->{values}{"TYPE"});
+ $a->output($fh);
+ $self->SUPER::output($fh);
+}
+
+1;
+
+__DATA__
+
+/*
+ * an enumerated collection type, generated from template
+ *
+ * Methods:
+ * int init() -> returns nonzero on alloc failure
+ * long size()
+ * long find(match) -> -1 or index of any match
+ * long append(value) -> -1 or new index
+ * <TYPE> get(index) -> aborts if out of range
+ * void destroy() -> frees array data
+ *
+ * Errors adding elements don't distinguish between "out of memory"
+ * and "too big for size_t".
+ *
+ * Initial implementation: A flat array, reallocated as needed. Our
+ * uses probably aren't going to get very large.
+ */
+
+struct <NAME>__enumerator {
+ <NAME>__enumerator_array a;
+ size_t used; /* number of entries used, idx used-1 is last */
+};
+typedef struct <NAME>__enumerator <NAME>;
+
+static inline int
+<NAME>_init(<NAME> *en)
+{
+ en->used = 0;
+ return <NAME>__enumerator_array_init(&en->a);
+}
+
+static inline long
+<NAME>_size(<NAME> *en)
+{
+ return en->used;
+}
+
+static inline long
+<NAME>__s2l(size_t idx)
+{
+ long l;
+ if (idx > LONG_MAX)
+ abort();
+ l = idx;
+ if (l != idx)
+ abort();
+ return l;
+}
+
+static inline long
+<NAME>_find(<NAME> *en, <TYPE> value)
+{
+ size_t i;
+ for (i = 0; i < en->used; i++) {
+ if (<COMPARE> (value, <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(i))) == 0)
+ return i;
+ }
+ return -1;
+}
+
+static inline long
+<NAME>_append(<NAME> *en, <TYPE> value)
+{
+ if (en->used >= LONG_MAX - 1)
+ return -1;
+ if (en->used >= SIZE_MAX - 1)
+ return -1;
+ if (<NAME>__enumerator_array_size(&en->a) == en->used) {
+ if (<NAME>__enumerator_array_grow(&en->a, en->used + 1) < 0)
+ return -1;
+ }
+ <NAME>__enumerator_array_set(&en->a, <NAME>__s2l(en->used), value);
+ en->used++;
+ return en->used-1;
+}
+
+static inline <TYPE>
+<NAME>_get(<NAME> *en, size_t idx)
+{
+ return <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(idx));
+}
+
+static inline void
+<NAME>_destroy(<NAME> *en)
+{
+ <NAME>__enumerator_array_destroy(&en->a);
+ en->used = 0;
+}
+
+static inline void
+<NAME>_foreach(<NAME> *en, int (*fn)(size_t i, <TYPE> t, void *p), void *p)
+{
+ size_t i;
+ for (i = 0; i < en->used; i++) {
+ if (fn (i, <NAME>__enumerator_array_get(&en->a, <NAME>__s2l(i)), p) != 0)
+ break;
+ }
+}
diff --git a/src/util/t_template.pm b/src/util/t_template.pm
new file mode 100644
index 000000000..9722a8730
--- /dev/null
+++ b/src/util/t_template.pm
@@ -0,0 +1,61 @@
+package t_template;
+
+use strict;
+use vars qw(@ISA @EXPORT_OK);
+
+@ISA=();
+@EXPORT_OK= qw(init setparm output);
+
+sub init { # (\@parms, \%defaults, \@template)
+ my ($self, $parms, $defs, $templatelines) = @_;
+ $self->{parms} = { };
+ $self->{values} = { };
+ my $key;
+ foreach $key (@$parms) {
+ $self->{parms}{$key} = 1;
+ }
+ foreach $key (keys %$defs) {
+ $self->{values}{$key} = ${$defs}{$key};
+ }
+ if (defined($templatelines)) {
+ $self->{template} = join "", @$templatelines;
+ }
+}
+
+sub validateparm { # (parmname)
+ no strict 'refs';
+ my ($self, $parmname) = @_;
+ if (!defined($self->{parms}{$parmname})) {
+ die "unknown parameter $parmname";
+ }
+}
+
+sub setparm { # (parm, value)
+ my ($self, $parm, $value) = @_;
+ $self->validateparm($parm);
+ $self->{values}{$parm} = $value;
+}
+
+sub substitute { # (text)
+ my ($self, $text) = @_;
+ my ($p);
+
+ # Do substitutions.
+ foreach $p (keys %{$self->{parms}}) {
+ if (!defined $self->{values}{$p}) {
+ die "$0: No value supplied for parameter $p\n";
+ }
+ # XXX More careful quoting of supplied value!
+ $text =~ s|<$p>|$self->{values}{$p}|g;
+ }
+ return $text;
+}
+
+sub output { # (fh)
+ my ($self, $fh) = @_;
+ print $fh "/* start of ", ref($self), " template */\n";
+ print $fh $self->substitute($self->{template});
+ print $fh "/* end of ", ref($self), " template */\n";
+}
+
+1;
diff --git a/src/util/t_tsenum.pm b/src/util/t_tsenum.pm
new file mode 100644
index 000000000..00efb5142
--- /dev/null
+++ b/src/util/t_tsenum.pm
@@ -0,0 +1,163 @@
+package t_tsenum;
+
+use strict;
+use vars qw(@ISA);
+
+require t_template;
+require t_enum;
+
+@ISA=qw(t_template);
+
+my @parms = qw(NAME TYPE COMPARE COPY PRINT);
+my %defaults = ( "COPY", "0", "PRINT", "0" );
+my @templatelines = <DATA>;
+
+sub new { # no args
+ my $self = {};
+ bless $self;
+ $self->init(\@parms, \%defaults, \@templatelines);
+ return $self;
+}
+
+sub output {
+ my ($self, $fh) = @_;
+ my $a = new t_enum;
+ $a->setparm("NAME", $self->{values}{"NAME"} . "__unsafe_enumerator");
+ $a->setparm("TYPE", $self->{values}{"TYPE"});
+ $a->setparm("COMPARE", $self->{values}{"COMPARE"});
+ $a->output($fh);
+ $self->SUPER::output($fh);
+}
+
+1;
+
+__DATA__
+
+/*
+ */
+#include "k5-thread.h"
+struct <NAME>__ts_enumerator {
+ <NAME>__unsafe_enumerator e;
+ k5_mutex_t m;
+};
+typedef struct <NAME>__ts_enumerator <NAME>;
+
+static inline int
+<NAME>_init(<NAME> *en)
+{
+ int err = k5_mutex_init(&en->m);
+ if (err)
+ return err;
+ err = <NAME>__unsafe_enumerator_init(&en->e);
+ if (err) {
+ k5_mutex_destroy(&en->m);
+ return err;
+ }
+ return 0;
+}
+
+static inline int
+<NAME>_size(<NAME> *en, long *size)
+{
+ int err = k5_mutex_lock(&en->m);
+ if (err) {
+ *size = -48;
+ return err;
+ }
+ *size = <NAME>__unsafe_enumerator_size(&en->e);
+ k5_mutex_unlock(&en->m);
+ return 0;
+}
+
+static inline int
+<NAME>__do_copy (<TYPE> *dest, <TYPE> src)
+{
+ int (*copyfn)(<TYPE>*, <TYPE>) = <COPY>;
+ if (copyfn)
+ return copyfn(dest, src);
+ *dest = src;
+ return 0;
+}
+
+static inline int
+<NAME>_find_or_append(<NAME> *en, <TYPE> value, long *idxp, int *added)
+{
+ int err;
+ long idx;
+
+ err = k5_mutex_lock(&en->m);
+ if (err)
+ return err;
+ idx = <NAME>__unsafe_enumerator_find(&en->e, value);
+ if (idx < 0) {
+ <TYPE> newvalue;
+ err = <NAME>__do_copy(&newvalue, value);
+ if (err == 0)
+ idx = <NAME>__unsafe_enumerator_append(&en->e, newvalue);
+ k5_mutex_unlock(&en->m);
+ if (err != 0)
+ return err;
+ if (idx < 0)
+ return ENOMEM;
+ *idxp = idx;
+ *added = 1;
+ return 0;
+ }
+ k5_mutex_unlock(&en->m);
+ *idxp = idx;
+ *added = 0;
+ return 0;
+}
+
+static inline int
+<NAME>_get(<NAME> *en, size_t idx, <TYPE> *value)
+{
+ int err;
+ err = k5_mutex_lock(&en->m);
+ if (err)
+ return err;
+ *value = <NAME>__unsafe_enumerator_get(&en->e, idx);
+ k5_mutex_unlock(&en->m);
+ return 0;
+}
+
+static inline void
+<NAME>_destroy(<NAME> *en)
+{
+ k5_mutex_destroy(&en->m);
+ <NAME>__unsafe_enumerator_destroy(&en->e);
+}
+
+static inline int
+<NAME>_foreach(<NAME> *en, int (*fn)(size_t i, <TYPE> t, void *p), void *p)
+{
+ int err = k5_mutex_lock(&en->m);
+ if (err)
+ return err;
+ <NAME>__unsafe_enumerator_foreach(&en->e, fn, p);
+ k5_mutex_unlock(&en->m);
+ return 0;
+}
+
+static inline int
+<NAME>__print_map_elt(size_t idx, <TYPE> val, void *p)
+{
+ void (*printfn)(<TYPE>, FILE *) = <PRINT>;
+ FILE *f = (FILE *) p;
+ if (printfn) {
+ fprintf(f, " %lu=", (unsigned long) idx);
+ printfn(val, f);
+ }
+ return 0;
+}
+
+static inline void
+<NAME>_print(<NAME> *en, FILE *f)
+{
+ void (*printfn)(<TYPE>, FILE *) = <PRINT>;
+ if (printfn) {
+ fprintf(f, "{");
+ <NAME>_foreach (en, <NAME>__print_map_elt, f);
+ fprintf(f, " }");
+ }
+}