an_to_ln.c revision ab9b2e153c3a9a2b1141fefa87925b1a9beb1236
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/an_to_ln.c
*
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
*
* krb5_aname_to_localname()
*/
/*
* We're only to AN_TO_LN rules at this point, and not doing the
* database lookup (moved from configure script)
*/
#ifndef AN_TO_LN_RULES
#define AN_TO_LN_RULES
#endif
#include <k5-int.h>
#include <ctype.h>
#if HAVE_REGEX_H
#include <regex.h>
#endif /* HAVE_REGEX_H */
#include <string.h>
/*
* Use compile(3) if no regcomp present.
*/
#define RE_BUF_SIZE 1024
#include <regexpr.h>
#endif /* !HAVE_REGCOMP && HAVE_REGEXP_H && HAVE_COMPILE */
#define MAX_FORMAT_BUFFER 1024
#ifndef min
#define min(a,b) ((a>b) ? b : a)
#endif /* min */
#ifdef ANAME_DB
/*
* Use standard DBM code.
*/
#else /*ANAME_DB*/
extern DBM *db_dbm_open (char *, int, int);
extern void db_dbm_close (DBM *);
#endif /*ANAME_DB*/
/*
* Find the portion of the flattened principal name that we use for mapping.
*/
static char *
{
char *atp;
char *mname;
if (fprincname) {
if (!atp)
}
}
return(mname);
}
#ifdef ANAME_DB
/*
* Implementation: This version uses a DBM database, indexed by aname,
* to generate a lname.
*
* The entries in the database are normal C strings, and include the trailing
* null in the DBM datum.size.
*/
static krb5_error_code
char *dbname;
const unsigned int lnsize;
char *lname;
{
#if !defined(_WIN32)
char *princ_name;
return(retval);
decoding */
if (!db) {
return KRB5_LNAME_CANTOPEN;
}
} else {
else
retval = 0;
}
/* can't close until we copy the contents. */
(void) KDBM_CLOSE(db);
return retval;
#else /* !_WIN32 && !MACINTOSH */
/*
* If we don't have support for a database mechanism, then we can't
* translate this now, can we?
*/
return KRB5_LNAME_NOTRANS;
#endif /* !_WIN32 && !MACINTOSH */
}
#endif /*ANAME_DB*/
#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
{
#if HAVE_REGCOMP
char regexp_buffer[RE_BUF_SIZE];
#endif /* HAVE_REGEXP_H */
kret = 0;
/*
* Is this a match expression?
*/
if (**contextp == '(') {
/* Find the end of the match expression. */
if (endp) {
if (regexp) {
/*
* Perform the match.
*/
#if HAVE_REGCOMP
if ((match_match.rm_so == 0) &&
kret = 0;
}
'\0');
kret = 0;
}
kret = 0;
#else /* HAVE_RE_COMP */
kret = 0;
#endif /* HAVE_RE_COMP */
}
endp++;
}
else
}
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.
*/
#define use_bytes(x) \
out_used += (x); \
static int
{
#if HAVE_REGCOMP
int matched;
char *cp;
char *op;
matched = 0;
do {
if (match_match.rm_so) {
}
if (!doall) {
}
matched = 1;
}
else {
matched = 0;
}
}
int matched;
char *cp;
char *op;
char regexp_buffer[RE_BUF_SIZE];
'\0');
matched = 0;
do {
if (sdispl) {
}
if (!doall) {
}
matched = 1;
}
else {
matched = 0;
}
#else /* HAVE_REGEXP_H */
#endif /* HAVE_REGCOMP */
return 1;
#ifdef HAVE_REGCMP
#endif
return 0;
}
/*
* 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
{
char *in;
char *out;
int doglobal;
char sep;
/* Allocate the formatting buffers */
/*
* Prime the buffers. Copy input string to "out" to simulate it
* being the result of an initial iteration.
*/
in[0] = '\0';
kret = 0;
/*
* Pound through the expression until we're done.
*/
/* Skip leading whitespace */
cp++;
/*
* Find our separators. First two characters must be "s<sep>"
* We must also find another "<sep>" followed by another * "<sep>".
*/
if (cp[0] != 's') {
/* Bad syntax */
break;
}
/* Bad syntax */
break;
}
/* Figure out sizes of strings and allocate them */
/* Copy the strings */
/* Check for trailing "g" */
if (doglobal)
tp++;
/* Swap previous in and out buffers */
/* Do the replacemenbt */
break;
}
/* If we have no output buffer left, this can't be good */
break;
}
}
else {
/* No memory for copies */
break;
}
}
else {
/* Bad syntax */
break;
}
/* Advance past trailer */
}
if (!kret)
else
}
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
{
char *current;
char *fprincname;
char *selstring = 0;
char *cout;
char *outstring;
/*
* First flatten the name.
*/
/*
* First part.
*/
if (*current == '[') {
/*
* We have a match based on the number of components.
*/
selstring_used = 0;
current++;
/*
* Plow through the string.
*/
while ((*current != ']') &&
(*current != '\0')) {
/*
* Expand to a component.
*/
if (*current == '$') {
< MAX_FORMAT_BUFFER)) {
} else {
goto errout;
}
*cout = '\0';
current++;
/* Point past number */
current++;
}
else
}
else {
/* Copy in verbatim. */
cout++;
*cout = '\0';
current++;
}
}
/*
* Advance past separator if appropriate.
*/
if (*current == ']')
current++;
else
}
}
else
}
else
}
else {
}
}
if (!kret) {
/*
* Second part
*/
if (*current == '(')
/*
* Third part.
*/
if (!kret) {
if (outstring) {
/* Copy out the value if there's enough room */
else
}
}
}
return(kret);
}
#endif /* AN_TO_LN_RULES */
/*
* Solaris Kerberos
* Return true (1) if the princ's realm matches any of the
* 'auth_to_local_realm' relations in the default realm section.
*/
static int
char *def_realm,
int realm_length)
{
const char *realm_names[4];
realm_names[0] = "realms";
realm_names[3] = 0;
return (0);
&values);
if (retval)
return (0);
realm_length) == 0)) {
return (1); /* success */
}
}
return (0);
}
/*
* Implementation: This version checks the realm to see if it is the local
* realm; if so, and there is exactly one non-realm component to the name,
* that name is returned as the lname.
*/
static krb5_error_code
{
char *def_realm;
unsigned int realm_length;
return(retval);
}
/* compare against default realm and auth_to_local_realm(s) */
realm_length))) &&
realm_length)) {
return KRB5_LNAME_NOTRANS;
}
/* Check to see if 2nd component is the local realm. */
def_realm, realm_length) ||
realm_length !=
/* XXX an_to_ln_realm_chk ? */
return KRB5_LNAME_NOTRANS;
}
}
else {
/* no components or more than one component to non-realm part of name
--no translation. */
return KRB5_LNAME_NOTRANS;
}
}
} else {
retval = 0;
}
return retval;
}
/*
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
*/
{
char *realm;
char *pname;
char *mname;
const char *hierarchy[5];
char **mapping_values;
int i, nvalid;
char *cp, *s;
unsigned int lnsize;
if (lnsize_in < 0)
return KRB5_CONFIG_NOTENUFSPACE;
/*
* First get the default realm.
*/
/* Flatten the name */
/*
* Search first for explicit mappings of the form:
*
* [realms]->realm->"auth_to_local_names"->mapping_name
*/
hierarchy[0] = "realms";
&mapping_values))) {
/* We found one or more explicit mappings. */
/* Just use the last one. */
/* Trim the value. */
while (cp > s) {
cp--;
break;
*cp = '\0';
}
/* Copy out the value if there's enough room */
else
/* Free residue */
}
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";
&mapping_values))) {
/*
* Loop through all the mapping values.
*/
for (i=0; mapping_values[i]; i++) {
typep = mapping_values[i];
if (argp) {
*argp = '\0';
argp++;
}
#ifdef ANAME_DB
argp,
lname);
if (kret != KRB5_LNAME_NOTRANS)
break;
}
else
#endif
#ifdef AN_TO_LN_RULES
argp,
lname);
if (kret != KRB5_LNAME_NOTRANS)
break;
}
else
#endif /* AN_TO_LN_RULES */
lname);
if (kret != KRB5_LNAME_NOTRANS)
break;
}
else {
break;
}
}
/* We're done, clean up the droppings. */
}
else {
/*
* No profile relation found, try default mapping.
*/
lname);
}
}
}
else
}
}
return(kret);
}