diff options
| author | Ken Raeburn <raeburn@mit.edu> | 2007-08-16 22:55:06 +0000 |
|---|---|---|
| committer | Ken Raeburn <raeburn@mit.edu> | 2007-08-16 22:55:06 +0000 |
| commit | c15ec7751a7d7c1d97dbeb1dd88dda2a328515e0 (patch) | |
| tree | 824bd8c158b1c5b72913515953c7e8576399d912 /src/util | |
| parent | 9db2f5eb745287654117e70032d05dd9f5a91a3f (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.pl | 61 | ||||
| -rw-r--r-- | src/util/t_array.pm | 129 | ||||
| -rw-r--r-- | src/util/t_enum.pm | 133 | ||||
| -rw-r--r-- | src/util/t_template.pm | 61 | ||||
| -rw-r--r-- | src/util/t_tsenum.pm | 163 |
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, " }"); + } +} |
