Add profile and Berkeley database smarts for aname_to_lname
authorPaul Park <pjpark@mit.edu>
Fri, 30 Jun 1995 20:21:28 +0000 (20:21 +0000)
committerPaul Park <pjpark@mit.edu>
Fri, 30 Jun 1995 20:21:28 +0000 (20:21 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6213 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/os/ChangeLog
src/lib/krb5/os/Makefile.in
src/lib/krb5/os/an_to_ln.c
src/lib/krb5/os/configure.in
src/lib/krb5/os/t_an_to_ln.c [new file with mode: 0644]

index b22e21e03f7789e4a8f6780cb648682d6237f59b..2307a994f2d056fb870103da8c90b5121092b0c8 100644 (file)
@@ -1,4 +1,14 @@
 
+Fri Jun 30 14:44:17 EDT 1995   Paul Park       (pjpark@mit.edu)
+       * an_to_ln.c - Add profile logic to aname_to_lname.  We can now
+               specify databases, rules and explicit mappings to convert
+               between auth name and local name.
+       * t_an_to_ln.c - Rudimentary test procedure.  Needs work to be automatic
+       * configure.in - Add --with-aname-dbm to select between Berkeley and
+               DBM aname database format.
+       * Makefile.in - Add definitions to select aname rules.
+
+
 Tue Jun 27 15:48:41 EDT 1995   Paul Park       (pjpark@mit.edu)
        * read_pwd.c(intr_routine) - Add signal name argument to signal handler
                to conform to prototype.
index 810a9574e3a0bf7b7201bd1ad5c0542025da06d5..358fbacd59172b3c47ced727c7cbe96cccc60695 100644 (file)
@@ -1,4 +1,5 @@
-CFLAGS = $(CCOPTS) $(DEFS)
+DBFLAGS=@DBFLAGS@
+CFLAGS = $(CCOPTS) $(DEFS) $(DBFLAGS) -DAN_TO_LN_RULES
 
 ##DOSBUILDTOP = ..\..\..
 ##DOSLIBNAME=..\krb5.lib
@@ -95,15 +96,21 @@ shared:
 
 COMERRLIB=$(BUILDTOP)/util/et/libcom_err.a
 
-TEST_PROGS= t_std_conf
+TEST_PROGS= t_std_conf t_an_to_ln
 
 T_STD_CONF_OBJS= t_std_conf.o def_realm.o get_krbhst.o realm_dom.o \
                hst_realm.o init_os_ctx.o locate_kdc.o $(COMERRLIB) \
                $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a
 
+T_AN_TO_LN_OBJS = t_an_to_ln.o an_to_ln.o $(TOPLIBD)/libkrb5.a \
+               $(TOPLIBD)/libcrypto.a $(COMERRLIB)
+
 t_std_conf: $(T_STD_CONF_OBJS)
        $(CC) -o t_std_conf $(T_STD_CONF_OBJS) $(LIBS)
 
+t_an_to_ln: $(T_AN_TO_LN_OBJS)
+       $(CC) -o t_an_to_ln $(T_AN_TO_LN_OBJS) $(LIBS)
+
 check:: check-$(WHAT)
 
 check-unix:: $(TEST_PROGS)
index d6c429ddfca93ff5825f779338d8ac3aaf03a284..368ea0aafac7c887b25e12946c033c917670d21a 100644 (file)
  */
 
 #include "k5-int.h"
-
-#ifndef min
-#define min(a,b) ((a) > (b) ? (b) : (a))
-#endif /* min */
-
-int krb5_lname_username_fallback = 1;
-extern char *krb5_lname_file;
-
-#ifndef _MSDOS    
-
-static krb5_error_code dbm_an_to_ln();
-static krb5_error_code username_an_to_ln();
-
+#if    HAVE_REGEX_H
+#include <regex.h>
+#endif /* HAVE_REGEX_H */
 /*
- Converts an authentication name to a local name suitable for use by
- programs wishing a translation to an environment-specific name (e.g.
- user account name).
+ * Use compile(3) if no regcomp present.
+ */
+#if    !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H)
+#define        INIT            char *sp = instring;
+#define        GETC()          (*sp++)
+#define        PEEKC()         (*sp)
+#define        UNGETC(c)       (--sp)
+#define        RETURN(c)       return(c)
+#define        ERROR(c)        
+#define        RE_BUF_SIZE     1024
+#include <regexp.h>
+#endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */
 
- lnsize specifies the maximum length name that is to be filled into
- lname.
- The translation will be null terminated in all non-error returns.
+#define        MAX_FORMAT_BUFFER       1024
+#ifndef        min
+#define        min(a,b)        ((a>b) ? b : a)
+#endif /* min */
 
- returns system errors, NOT_ENOUGH_SPACE
-*/
+#ifdef BERK_DB_DBM
+/*
+ * Use Berkeley Hashed Database code.
+ */
+extern DBM     *db_dbm_open KRB5_PROTOTYPE((char *, int, int));
+extern void    db_dbm_close KRB5_PROTOTYPE((DBM *));
+extern datum   db_dbm_fetch KRB5_PROTOTYPE((DBM *, datum));
+#define        KDBM_OPEN(db, fl, mo)   db_dbm_open(db, fl, mo)
+#define        KDBM_CLOSE(db)          db_dbm_close(db)
+#define        KDBM_FETCH(db, key)     db_dbm_fetch(db, key)
+#else  /* BERK_DB_DBM */
+/*
+ * Use standard DBM code.
+ */
+#define        KDBM_OPEN(db, fl, mo)   dbm_open(db, fl, mo)
+#define        KDBM_CLOSE(db)          dbm_close(db)
+#define        KDBM_FETCH(db, key)     dbm_fetch(db, key)
+#endif /* BERK_DB_DBM */
 
-krb5_error_code
-krb5_aname_to_localname(context, aname, lnsize, lname)
-    krb5_context context;
-       krb5_const_principal aname;
-       const int lnsize;
-       char *lname;
+/*
+ * Find the portion of the flattened principal name that we use for mapping.
+ */
+static char *
+aname_full_to_mapping_name(fprincname)
+    char *fprincname;
 {
-       struct stat statbuf;
-
-#ifdef USE_DBM_LNAME
-       if (!stat(krb5_lname_file,&statbuf))
-               return dbm_an_to_ln(context, aname, lnsize, lname);
-#endif
-       if (krb5_lname_username_fallback)
-               return username_an_to_ln(context, aname, lnsize, lname);
-       return KRB5_LNAME_CANTOPEN;
+    char       *atp;
+    size_t     mlen;
+    char       *mname;
+
+    mname = (char *) NULL;
+    if (fprincname) {
+       atp = strrchr(fprincname, '@');
+       if (!atp)
+           atp = &fprincname[strlen(fprincname)];
+       mlen = (size_t) (atp - fprincname);
+       
+       if (mname = (char *) malloc(mlen+1)) {
+           strncpy(mname, fprincname, mlen);
+           mname[mlen] = '\0';
+       }
+    }
+    return(mname);
 }
 
-#ifdef USE_DBM_LNAME
 /*
  * Implementation:  This version uses a DBM database, indexed by aname,
  * to generate a lname.
@@ -77,12 +100,14 @@ krb5_aname_to_localname(context, aname, lnsize, lname)
  * null in the DBM datum.size.
  */
 static krb5_error_code
-dbm_an_to_ln(context, aname, lnsize, lname)
+db_an_to_ln(context, dbname, aname, lnsize, lname)
     krb5_context context;
+    char *dbname;
     krb5_const_principal aname;
     const int lnsize;
     char *lname;
 {
+#if    defined(BERK_DB_DBM) || !defined(_WINDOWS)
     DBM *db;
     krb5_error_code retval;
     datum key, contents;
@@ -94,13 +119,13 @@ dbm_an_to_ln(context, aname, lnsize, lname)
     key.dsize = strlen(princ_name)+1;  /* need to store the NULL for
                                           decoding */
 
-    db = dbm_open(krb5_lname_file, O_RDONLY, 0600);
+    db = KDBM_OPEN(dbname, O_RDONLY, 0600);
     if (!db) {
        krb5_xfree(princ_name);
        return KRB5_LNAME_CANTOPEN;
     }
 
-    contents = dbm_fetch(db, key);
+    contents = KDBM_FETCH(db, key);
 
     krb5_xfree(princ_name);
 
@@ -116,11 +141,457 @@ dbm_an_to_ln(context, aname, lnsize, lname)
            retval = 0;
     }
     /* can't close until we copy the contents. */
-    (void) dbm_close(db);
+    (void) KDBM_CLOSE(db);
     return retval;
+#else  /* BERK_DB_DBM && !_WINDOWS */
+    /*
+     * If we don't have support for a database mechanism, then we can't
+     * translate this now, can we?
+     */
+    return KRB5_LNAME_NOTRANS;
+#endif /* BERK_DB_DBM && !_WINDOWS */
+}
+
+#ifdef AN_TO_LN_RULES
+/*
+ * Format and transform a principal name to a local name.  This is particularly
+ * useful when Kerberos principals and local user names are formatted to
+ * some particular convention.
+ *
+ * There are three parts to each rule:
+ * First part - formulate the string to perform operations on:  If not present
+ * then the string defaults to the fully flattened principal minus the realm
+ * name.  Otherwise the syntax is as follows:
+ *     "[" <ncomps> ":" <format> "]"
+ *             Where:
+ *                     <ncomps> is the number of expected components for this
+ *                     rule.  If the particular principal does not have this
+ *                     many components, then this rule does not apply.
+ *
+ *                     <format> is a string of <component> or verbatim
+ *                     characters to be inserted.
+ *
+ *                     <component> is of the form "$"<number> to select the
+ *                     <number>th component.  <number> begins from 1.
+ *
+ * Second part - select rule validity:  If not present, then this rule may
+ * apply to all selections.  Otherwise the syntax is as follows:
+ *     "(" <regexp> ")"
+ *             Where:  <regexp> is a selector regular expression.  If this
+ *                     regular expression matches the whole pattern generated
+ *                     from the first part, then this rule still applies.
+ *
+ * Last part - Transform rule:  If not present, then the selection string
+ * is passed verbatim and is matched.  Otherwise, the syntax is as follows:
+ *     <rule> ...
+ *             Where:  <rule> is of the form:
+ *                     "s/" <regexp> "/" <text> "/" ["g"]
+ * 
+ * In order to be able to select rule validity, the native system must support
+ * one of compile(3), re_comp(3) or regcomp(3).  In order to be able to
+ * transform (e.g. substitute), the native system must support regcomp(3) or
+ * compile(3).
+ */
+
+/*
+ * aname_do_match()    - Does our name match the parenthesized regular
+ *                       expression?
+ * 
+ * Chew up the match portion of the regular expression and update *contextp.
+ * If no re_comp() or regcomp(), then always return a match.
+ */
+static krb5_error_code
+aname_do_match(string, contextp)
+    char       *string;
+    char       **contextp;
+{
+    krb5_error_code    kret;
+    char               *regexp, *startp, *endp;
+    size_t             regexlen;
+#if    HAVE_REGCOMP
+    regex_t            match_exp;
+    regmatch_t         match_match;
+#elif  HAVE_REGEXP_H
+    char               regexp_buffer[RE_BUF_SIZE];
+#endif /* HAVE_REGEXP_H */
+
+    kret = 0;
+    /*
+     * Is this a match expression?
+     */
+    if (**contextp == '(') {
+       kret = KRB5_CONFIG_BADFORMAT;
+       startp = (*contextp) + 1;
+       endp = strchr(startp, ')');
+       /* Find the end of the match expression. */
+       if (endp) {
+           regexlen = (size_t) (endp - startp);
+           regexp = (char *) malloc((size_t) regexlen+1);
+           kret = ENOMEM;
+           if (regexp) {
+               strncpy(regexp, startp, regexlen);
+               regexp[regexlen] = '\0';
+               kret = KRB5_LNAME_NOTRANS;
+               /*
+                * Perform the match.
+                */
+#if    HAVE_REGCOMP
+               if (!regcomp(&match_exp, regexp, REG_EXTENDED) &&
+                   !regexec(&match_exp, string, 1, &match_match, 0)) {
+                   if ((match_match.rm_so == 0) &&
+                       (match_match.rm_eo == strlen(string)))
+                       kret = 0;
+               }
+               regfree(&match_exp);
+#elif  HAVE_REGEXP_H
+               compile(regexp,
+                       regexp_buffer,
+                       &regexp_buffer[RE_BUF_SIZE],
+                       '\0');
+               if (step(string, regexp_buffer)) {
+                   if ((loc1 == string) &&
+                       (loc2 == &string[strlen(string)]))
+                       kret = 0;
+               }
+#elif  HAVE_RE_COMP
+               if (!re_comp(regexp) && re_exec(string))
+                   kret = 0;
+#else  /* HAVE_RE_COMP */
+               kret = 0;
+#endif /* HAVE_RE_COMP */
+               free(regexp);
+           }
+           endp++;
+       }
+       else
+           endp = startp;
+    }
+    *contextp = endp;
+    return(kret);
+}
+
+/*
+ * do_replacement()    - Replace the regular expression with the specified
+ *                       replacement.
+ *
+ * If "doall" is set, it's a global replacement, otherwise, just a oneshot
+ * deal.
+ * If no regcomp() then just return the input string verbatim in the output
+ * string.
+ */
+static void
+do_replacement(regexp, repl, doall, in, out)
+    char       *regexp;
+    char       *repl;
+    int                doall;
+    char       *in;
+    char       *out;
+{
+#if    HAVE_REGCOMP
+    regex_t    match_exp;
+    regmatch_t match_match;
+    int                matched;
+    char       *cp;
+    char       *op;
+
+    if (!regcomp(&match_exp, regexp, REG_EXTENDED)) {
+       cp = in;
+       op = out;
+       matched = 0;
+       do {
+           if (!regexec(&match_exp, cp, 1, &match_match, 0)) {
+               if (match_match.rm_so) {
+                   strncpy(op, cp, match_match.rm_so);
+                   op += match_match.rm_so;
+               }
+               strcpy(op, repl);
+               op += strlen(repl);
+               cp += match_match.rm_eo;
+               if (!doall)
+                   strcpy(op, cp);
+               matched = 1;
+           }
+           else {
+               strcpy(op, cp);
+               matched = 0;
+           }
+       } while (doall && matched);
+       regfree(&match_exp);
+    }
+#elif  HAVE_REGEXP_H
+    int                matched;
+    char       *cp;
+    char       *op;
+    char       regexp_buffer[RE_BUF_SIZE];
+    size_t     sdispl, edispl;
+
+    compile(regexp,
+           regexp_buffer,
+           &regexp_buffer[RE_BUF_SIZE],
+           '\0');
+    cp = in;
+    op = out;
+    matched = 0;
+    do {
+       if (step(cp, regexp_buffer)) {
+           sdispl = (size_t) (loc1 - cp);
+           edispl = (size_t) (loc2 - cp);
+           if (sdispl) {
+               strncpy(op, cp, sdispl);
+               op += sdispl;
+           }
+           strcpy(op, repl);
+           op += strlen(repl);
+           cp += edispl;
+           if (!doall)
+               strcpy(op, cp);
+           matched = 1;
+       }
+       else {
+           strcpy(op, cp);
+           matched = 0;
+       }
+    } while (doall && matched);
+#else  /* HAVE_REGEXP_H */
+    strcpy(out, in);
+#endif /* HAVE_REGCOMP */
 }
-#endif /* USE_DBM_LNAME */
-#endif /* _MSDOS */
+
+/*
+ * aname_replacer()    - Perform the specified substitutions on the input
+ *                       string and return the result.
+ *
+ * This routine enforces the "s/<pattern>/<replacement>/[g]" syntax.
+ */
+static krb5_error_code
+aname_replacer(string, contextp, result)
+    char       *string;
+    char       **contextp;
+    char       **result;
+{
+    krb5_error_code    kret;
+    char               *in;
+    char               *out;
+    char               *cp, *ep, *tp;
+    char               *rule, *repl;
+    size_t             rule_size, repl_size;
+    int                        doglobal;
+
+    kret = ENOMEM;
+    *result = (char *) NULL;
+    /* Allocate the formatting buffers */
+    if ((in = (char *) malloc(MAX_FORMAT_BUFFER)) &&
+       (out = (char *) malloc(MAX_FORMAT_BUFFER))) {
+       /*
+        * Prime the buffers.  Copy input string to "out" to simulate it
+        * being the result of an initial iteration.
+        */
+       strcpy(out, string);
+       in[0] = '\0';
+       kret = 0;
+       /*
+        * Pound through the expression until we're done.
+        */
+       for (cp = *contextp; *cp; ) {
+           /* Skip leading whitespace */
+           while (isspace(*cp))
+               cp++;
+
+           /*
+            * Find our separators.  First two characters must be "s/"
+            * We must also find another "/" followed by another "/".
+            */
+           if ((cp[0] == 's') &&
+               (cp[1] == '/') &&
+               (ep = strchr(&cp[2], '/')) &&
+               (tp = strchr(&ep[1], '/'))) {
+
+               /* Figure out sizes of strings and allocate them */
+               rule_size = (size_t) (ep - &cp[2]);
+               repl_size = (size_t) (tp - &ep[1]);
+               if ((rule = (char *) malloc(rule_size+1)) &&
+                   (repl = (char *) malloc(repl_size+1))) {
+
+                   /* Copy the strings */
+                   strncpy(rule, &cp[2], rule_size);
+                   strncpy(repl, &ep[1], repl_size);
+                   rule[rule_size] = repl[repl_size] = '\0';
+
+                   /* Check for trailing "g" */
+                   doglobal = (tp[1] == 'g') ? 1 : 0;
+                   if (doglobal)
+                       tp++;
+
+                   /* Swap previous in and out buffers */
+                   ep = in;
+                   in = out;
+                   out = ep;
+
+                   /* Do the replacemenbt */
+                   do_replacement(rule, repl, doglobal, in, out);
+                   free(rule);
+                   free(repl);
+
+                   /* If we have no output buffer left, this can't be good */
+                   if (strlen(out) == 0) {
+                       kret = KRB5_LNAME_NOTRANS;
+                       break;
+                   }
+               }
+               else {
+                   /* No memory for copies */
+                   kret = ENOMEM;
+                   break;
+               }
+           }
+           else {
+               /* Bad syntax */
+               kret = KRB5_CONFIG_BADFORMAT;
+               break;
+           }
+           /* Advance past trailer */
+           cp = &tp[1];
+       }
+       free(in);
+       if (!kret)
+           *result = out;
+       else
+           free(out);
+    }
+    return(kret);
+}
+
+/*
+ * rule_an_to_ln()     - Handle aname to lname translations for RULE rules.
+ *
+ * The initial part of this routine handles the formulation of the strings from
+ * the principal name.
+ */
+static krb5_error_code
+rule_an_to_ln(context, rule, aname, lnsize, lname)
+    krb5_context               context;
+    char *                     rule;
+    krb5_const_principal       aname;
+    const int                  lnsize;
+    char *                     lname;
+{
+    krb5_error_code    kret;
+    char               *current;
+    char               *fprincname;
+    char               *selstring;
+    int                        num_comps, compind;
+    char               *cout;
+    krb5_data          *datap;
+    char               *outstring;
+
+    /*
+     * First flatten the name.
+     */
+    current = rule;
+    if (!(kret = krb5_unparse_name(context, aname, &fprincname))) {
+       /*
+        * First part.
+        */
+       if (*current == '[') {
+           if (sscanf(current+1,"%d:", &num_comps) == 1) {
+               if (num_comps == aname->length) {
+                   /*
+                    * We have a match based on the number of components.
+                    */
+                   current = strchr(current, ':');
+                   selstring = (char *) malloc(MAX_FORMAT_BUFFER);
+                   if (current && selstring) {
+                       current++;
+                       cout = selstring;
+                       /*
+                        * Plow through the string.
+                        */
+                       while ((*current != ']') &&
+                              (*current != '\0')) {
+                           /*
+                            * Expand to a component.
+                            */
+                           if (*current == '$') {
+                               if ((sscanf(current+1, "%d", &compind) == 1) &&
+                                   (compind <= num_comps) &&
+                                   (datap = krb5_princ_component(context,
+                                                                 aname,
+                                                                 compind-1))
+                                   ) {
+                                   strncpy(cout,
+                                           datap->data,
+                                           datap->length);
+                                   cout += datap->length;
+                                   *cout = '\0';
+                                   current++;
+                                   /* Point past number */
+                                   while (isdigit(*current))
+                                       current++;
+                               }
+                               else
+                                   kret = KRB5_CONFIG_BADFORMAT;
+                           }
+                           else {
+                               /* Copy in verbatim. */
+                               *cout = *current;
+                               cout++;
+                               *cout = '\0';
+                               current++;
+                           }
+                       }
+
+                       /*
+                        * Advance past separator if appropriate.
+                        */
+                       if (*current == ']')
+                           current++;
+                       else
+                           kret = KRB5_CONFIG_BADFORMAT;
+
+                       if (kret)
+                           free(selstring);
+                   }
+               }
+               else
+                   kret = KRB5_LNAME_NOTRANS;
+           }
+           else
+               kret = KRB5_CONFIG_BADFORMAT;
+       }
+       else {
+           if (!(selstring = aname_full_to_mapping_name(fprincname)))
+               kret = ENOMEM;
+       }
+       krb5_xfree(fprincname);
+    }
+    if (!kret) {
+       /*
+        * Second part
+        */
+       if (*current == '(')
+           kret = aname_do_match(selstring, &current);
+
+       /*
+        * Third part.
+        */
+       if (!kret) {
+           outstring = (char *) NULL;
+           kret = aname_replacer(selstring, &current, &outstring);
+           if (outstring) {
+               /* Copy out the value if there's enough room */
+               if (strlen(outstring)+1 <= (size_t) lnsize)
+                   strcpy(lname, outstring);
+               else
+                   kret = KRB5_CONFIG_NOTENUFSPACE;
+               free(outstring);
+           }
+       }
+       free(selstring);
+    }
+
+    return(kret);
+}
+#endif /* AN_TO_LN_RULES */
 
 /*
  * Implementation:  This version checks the realm to see if it is the local
@@ -128,7 +599,7 @@ dbm_an_to_ln(context, aname, lnsize, lname)
  * that name is returned as the lname.
  */
 static krb5_error_code
-username_an_to_ln(context, aname, lnsize, lname)
+default_an_to_ln(context, aname, lnsize, lname)
     krb5_context context;
     krb5_const_principal aname;
     const int lnsize;
@@ -175,18 +646,169 @@ username_an_to_ln(context, aname, lnsize, lname)
     return retval;
 }
 
-#ifdef _MSDOS
+/*
+ Converts an authentication name to a local name suitable for use by
+ programs wishing a translation to an environment-specific name (e.g.
+ user account name).
+
+ lnsize specifies the maximum length name that is to be filled into
+ lname.
+ The translation will be null terminated in all non-error returns.
+
+ returns system errors, NOT_ENOUGH_SPACE
+*/
 
 krb5_error_code
 krb5_aname_to_localname(context, aname, lnsize, lname)
     krb5_context context;
-       krb5_const_principal aname;
-       const int lnsize;
-       char *lname;
+    krb5_const_principal aname;
+    const int lnsize;
+    char *lname;
 {
-       if (krb5_lname_username_fallback)
-               return username_an_to_ln(context, aname, lnsize, lname);
-       return KRB5_LNAME_CANTOPEN;
+    krb5_error_code    kret;
+    char               *realm;
+    char               *pname;
+    char               *mname;
+    const char         *hierarchy[5];
+    char               **mapping_values;
+    int                        i, nvalid;
+    char               *cp;
+    char               *typep, *argp;
+
+    /*
+     * First get the default realm.
+     */
+    if (!(kret = krb5_get_default_realm(context, &realm))) {
+       /* Flatten the name */
+       if (!(kret = krb5_unparse_name(context, aname, &pname))) {
+           if (mname = aname_full_to_mapping_name(pname)) {
+               /*
+                * Search first for explicit mappings of the form:
+                *
+                * [realms]->realm->"auth_to_local_names"->mapping_name
+                */
+               hierarchy[0] = "realms";
+               hierarchy[1] = realm;
+               hierarchy[2] = "auth_to_local_names";
+               hierarchy[3] = mname;
+               hierarchy[4] = (char *) NULL;
+               if (!(kret = profile_get_values(context->profile,
+                                               hierarchy,
+                                               &mapping_values))) {
+                   /* We found one or more explicit mappings. */
+                   for (nvalid=0; mapping_values[nvalid]; nvalid++);
+
+                   /* Free the other ones, just use the last one */
+                   for (i=0; i<nvalid-1; i++)
+                       krb5_xfree(mapping_values[i]);
+
+                   /* Trim the value. */
+                   cp = &mapping_values[nvalid-1]
+                       [strlen(mapping_values[nvalid-1])];
+                   while (isspace(*cp)) cp--;
+                   cp++;
+                   *cp = '\0';
+
+                   /* Copy out the value if there's enough room */
+                   if (strlen(mapping_values[nvalid-1])+1 <= (size_t) lnsize)
+                       strcpy(lname, mapping_values[nvalid-1]);
+                   else
+                       kret = KRB5_CONFIG_NOTENUFSPACE;
+
+                   /* Free residue */
+                   krb5_xfree(mapping_values[nvalid-1]);
+                   krb5_xfree(mapping_values);
+               }
+               else {
+                   /*
+                    * OK - There's no explicit mapping.  Now check for
+                    * general auth_to_local rules of the form:
+                    *
+                    * [realms]->realm->"auth_to_local"
+                    *
+                    * This can have one or more of the following kinds of
+                    * values:
+                    *  DB:<filename>   - Look up principal in aname database.
+                    *  RULE:<sed-exp>  - Formulate lname from sed-exp.
+                    *  DEFAULT         - Use default rule.
+                    * The first rule to find a match is used.
+                    */
+                   hierarchy[0] = "realms";
+                   hierarchy[1] = realm;
+                   hierarchy[2] = "auth_to_local";
+                   hierarchy[3] = (char *) NULL;
+                   if (!(kret = profile_get_values(context->profile,
+                                                   hierarchy,
+                                                   &mapping_values))) {
+                       /*
+                        * Loop through all the mapping values.
+                        */
+                       for (i=0; mapping_values[i]; i++) {
+                           typep = mapping_values[i];
+                           argp = strchr(typep, ':');
+                           if (argp) {
+                               *argp = '\0';
+                               argp++;
+                           }
+                           if (!strcmp(typep, "DB") && argp) {
+                               kret = db_an_to_ln(context,
+                                                  argp,
+                                                  aname,
+                                                  lnsize,
+                                                  lname);
+                               if (kret != KRB5_LNAME_NOTRANS)
+                                   break;
+                           }
+                           else
+#ifdef AN_TO_LN_RULES
+                           if (!strcmp(typep, "RULE") && argp) {
+                               kret = rule_an_to_ln(context,
+                                                    argp,
+                                                    aname,
+                                                    lnsize,
+                                                    lname);
+                               if (kret != KRB5_LNAME_NOTRANS)
+                                   break;
+                           }
+                           else
+#endif /* AN_TO_LN_RULES */
+                           if (!strcmp(typep, "DEFAULT") && !argp) {
+                               kret = default_an_to_ln(context,
+                                                       aname,
+                                                       lnsize,
+                                                       lname);
+                               if (kret != KRB5_LNAME_NOTRANS)
+                                   break;
+                           }
+                           else {
+                               kret = KRB5_CONFIG_BADFORMAT;
+                               break;
+                           }
+                       }
+
+                       /* We're done, clean up the droppings. */
+                       for (i=0; mapping_values[i]; i++)
+                           krb5_xfree(mapping_values[i]);
+                       krb5_xfree(mapping_values);
+                   }
+                   else {
+                       /*
+                        * No profile relation found, try default mapping.
+                        */
+                       kret = default_an_to_ln(context,
+                                               aname,
+                                               lnsize,
+                                               lname);
+                   }
+               }
+               free(mname);
+           }
+           else
+               kret = ENOMEM;
+           krb5_xfree(pname);
+       }
+       krb5_xfree(realm);
+    }
+    return(kret);
 }
 
-#endif /* _MSDOS */
index ac7d4306ae36716908b141bcc5c15fb892a943ca..c356bfc4dac8b8e2248b967ac6bff523eb716ed0 100644 (file)
@@ -3,9 +3,24 @@ CONFIG_RULES
 dnl time checks are for timeofday.c (which gets them from osconf.h)
 dnl and gmt_mktime.c (which only gets them from here...)
 AC_TIME_WITH_SYS_TIME
-AC_HAVE_HEADERS(unistd.h sys/time.h)
+AC_HAVE_HEADERS(unistd.h sys/time.h regex.h regexp.h)
+AC_HAVE_FUNCS(re_comp regcomp)
 AC_HEADER_EGREP(time_t, sys/types.h, AC_DEFINE(POSIX_TYPES))
 HAS_ANSI_VOLATILE
+AC_ARG_WITH([aname-dbm],
+[  --with-aname-dbm            use native dbm for aname_to_lname database
+  --without-aname-dbm          use included version of Berkeley db (default)],
+,
+withval=no)dnl
+if test "$withval" = yes; then
+       AC_MSG_RESULT(Using native dbm for aname_to_lname database)
+       DBFLAGS=
+else
+       AC_MSG_RESULT(Using Berkeley db for aname_to_lname database)
+       DBFLAGS=-DBERK_DB_DBM
+fi
+AC_SUBST(DBFLAGS)dnl
+dnl
 V5_SHARED_LIB_OBJS
 SubdirLibraryRule([${OBJS}])
 V5_AC_OUTPUT_MAKEFILE
diff --git a/src/lib/krb5/os/t_an_to_ln.c b/src/lib/krb5/os/t_an_to_ln.c
new file mode 100644 (file)
index 0000000..b174055
--- /dev/null
@@ -0,0 +1,39 @@
+#include "krb5.h"
+
+int
+main(argc, argv)
+    int                argc;
+    char       *argv[];
+{
+    krb5_error_code    kret;
+    krb5_context       kcontext;
+    krb5_principal     principal;
+    char               *programname;
+    int                        i;
+    char               sbuf[1024];
+
+    programname = argv[0];
+    krb5_init_context(&kcontext);
+    krb5_init_ets(kcontext);
+    for (i=1; i < argc; i++) {
+       if (!(kret = krb5_parse_name(kcontext, argv[i], &principal))) {
+           if (!(kret = krb5_aname_to_localname(kcontext,
+                                                principal,
+                                                1024,
+                                                sbuf))) {
+               printf("%s: aname_to_lname maps %s -> <%s>\n",
+                      programname, argv[i], sbuf);
+           }
+           else {
+               printf("%s: aname to lname returns %s\n", programname,
+                      error_message(kret));
+           }
+           krb5_free_principal(kcontext, principal);
+       }
+       else {
+           printf("%s: parse_name returns %s\n", programname,
+                  error_message(kret));
+       }
+    }
+    krb5_free_context(kcontext);
+}