17c478bd9Sstevel@tonic-gate /*
2*159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * lib/krb5/os/an_to_ln.c
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
117c478bd9Sstevel@tonic-gate  * All Rights Reserved.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
147c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
157c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
167c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
17*159d09a2SMark Phalan  *
187c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
197c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
207c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
217c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
227c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
237c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
247c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
257c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
267c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
277c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
287c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
297c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
307c478bd9Sstevel@tonic-gate  * or implied warranty.
31*159d09a2SMark Phalan  *
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * krb5_aname_to_localname()
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate  * We're only to AN_TO_LN rules at this point, and not doing the
387c478bd9Sstevel@tonic-gate  * database lookup  (moved from configure script)
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate #define AN_TO_LN_RULES
417c478bd9Sstevel@tonic-gate 
42*159d09a2SMark Phalan #include "k5-int.h"
437c478bd9Sstevel@tonic-gate #include <ctype.h>
447c478bd9Sstevel@tonic-gate #if	HAVE_REGEX_H
457c478bd9Sstevel@tonic-gate #include <regex.h>
467c478bd9Sstevel@tonic-gate #endif	/* HAVE_REGEX_H */
47505d05c7Sgtb #include <string.h>
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate  * Use compile(3) if no regcomp present.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate #if	!defined(HAVE_REGCOMP) && defined(HAVE_REGEXPR_H) && defined(HAVE_COMPILE)
527c478bd9Sstevel@tonic-gate #define	RE_BUF_SIZE	1024
537c478bd9Sstevel@tonic-gate #include <regexpr.h>
547c478bd9Sstevel@tonic-gate #endif	/* !HAVE_REGCOMP && HAVE_REGEXP_H && HAVE_COMPILE */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	MAX_FORMAT_BUFFER	1024
577c478bd9Sstevel@tonic-gate #ifndef	min
587c478bd9Sstevel@tonic-gate #define	min(a,b)	((a>b) ? b : a)
597c478bd9Sstevel@tonic-gate #endif	/* min */
607c478bd9Sstevel@tonic-gate #ifdef ANAME_DB
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate  * Use standard DBM code.
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate #define	KDBM_OPEN(db, fl, mo)	dbm_open(db, fl, mo)
657c478bd9Sstevel@tonic-gate #define	KDBM_CLOSE(db)		dbm_close(db)
667c478bd9Sstevel@tonic-gate #define	KDBM_FETCH(db, key)	dbm_fetch(db, key)
677c478bd9Sstevel@tonic-gate #endif /*ANAME_DB*/
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Find the portion of the flattened principal name that we use for mapping.
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate static char *
aname_full_to_mapping_name(char * fprincname)737c478bd9Sstevel@tonic-gate aname_full_to_mapping_name(char *fprincname)
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate     char	*atp;
767c478bd9Sstevel@tonic-gate     size_t	mlen;
777c478bd9Sstevel@tonic-gate     char	*mname;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate     mname = (char *) NULL;
807c478bd9Sstevel@tonic-gate     if (fprincname) {
817c478bd9Sstevel@tonic-gate 	atp = strrchr(fprincname, '@');
827c478bd9Sstevel@tonic-gate 	if (!atp)
837c478bd9Sstevel@tonic-gate 	    atp = &fprincname[strlen(fprincname)];
847c478bd9Sstevel@tonic-gate 	mlen = (size_t) (atp - fprincname);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	if ((mname = (char *) malloc(mlen+1))) {
877c478bd9Sstevel@tonic-gate 	    strncpy(mname, fprincname, mlen);
887c478bd9Sstevel@tonic-gate 	    mname[mlen] = '\0';
897c478bd9Sstevel@tonic-gate 	}
907c478bd9Sstevel@tonic-gate     }
917c478bd9Sstevel@tonic-gate     return(mname);
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate #ifdef ANAME_DB
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Implementation:  This version uses a DBM database, indexed by aname,
977c478bd9Sstevel@tonic-gate  * to generate a lname.
987c478bd9Sstevel@tonic-gate  *
997c478bd9Sstevel@tonic-gate  * The entries in the database are normal C strings, and include the trailing
1007c478bd9Sstevel@tonic-gate  * null in the DBM datum.size.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate static krb5_error_code
db_an_to_ln(context,dbname,aname,lnsize,lname)1037c478bd9Sstevel@tonic-gate db_an_to_ln(context, dbname, aname, lnsize, lname)
1047c478bd9Sstevel@tonic-gate     krb5_context context;
1057c478bd9Sstevel@tonic-gate     char *dbname;
1067c478bd9Sstevel@tonic-gate     krb5_const_principal aname;
107505d05c7Sgtb     const unsigned int lnsize;
1087c478bd9Sstevel@tonic-gate     char *lname;
1097c478bd9Sstevel@tonic-gate {
110505d05c7Sgtb #if !defined(_WIN32)
1117c478bd9Sstevel@tonic-gate     DBM *db;
1127c478bd9Sstevel@tonic-gate     krb5_error_code retval;
1137c478bd9Sstevel@tonic-gate     datum key, contents;
1147c478bd9Sstevel@tonic-gate     char *princ_name;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate     if ((retval = krb5_unparse_name(context, aname, &princ_name)))
1177c478bd9Sstevel@tonic-gate 	return(retval);
1187c478bd9Sstevel@tonic-gate     key.dptr = princ_name;
1197c478bd9Sstevel@tonic-gate     key.dsize = strlen(princ_name)+1;	/* need to store the NULL for
1207c478bd9Sstevel@tonic-gate 					   decoding */
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate     db = KDBM_OPEN(dbname, O_RDONLY, 0600);
1237c478bd9Sstevel@tonic-gate     if (!db) {
1247c478bd9Sstevel@tonic-gate 	krb5_xfree(princ_name);
1257c478bd9Sstevel@tonic-gate 	return KRB5_LNAME_CANTOPEN;
1267c478bd9Sstevel@tonic-gate     }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate     contents = KDBM_FETCH(db, key);
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate     krb5_xfree(princ_name);
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate     if (contents.dptr == NULL) {
1337c478bd9Sstevel@tonic-gate 	retval = KRB5_LNAME_NOTRANS;
1347c478bd9Sstevel@tonic-gate     } else {
1357c478bd9Sstevel@tonic-gate 	strncpy(lname, contents.dptr, lnsize);
1367c478bd9Sstevel@tonic-gate 	if (lnsize < contents.dsize)
1377c478bd9Sstevel@tonic-gate 	    retval = KRB5_CONFIG_NOTENUFSPACE;
1387c478bd9Sstevel@tonic-gate 	else if (lname[contents.dsize-1] != '\0')
1397c478bd9Sstevel@tonic-gate 	    retval = KRB5_LNAME_BADFORMAT;
1407c478bd9Sstevel@tonic-gate 	else
1417c478bd9Sstevel@tonic-gate 	    retval = 0;
1427c478bd9Sstevel@tonic-gate     }
1437c478bd9Sstevel@tonic-gate     /* can't close until we copy the contents. */
1447c478bd9Sstevel@tonic-gate     (void) KDBM_CLOSE(db);
1457c478bd9Sstevel@tonic-gate     return retval;
146505d05c7Sgtb #else	/* !_WIN32 && !MACINTOSH */
1477c478bd9Sstevel@tonic-gate     /*
1487c478bd9Sstevel@tonic-gate      * If we don't have support for a database mechanism, then we can't
1497c478bd9Sstevel@tonic-gate      * translate this now, can we?
1507c478bd9Sstevel@tonic-gate      */
1517c478bd9Sstevel@tonic-gate     return KRB5_LNAME_NOTRANS;
152505d05c7Sgtb #endif	/* !_WIN32 && !MACINTOSH */
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate #endif /*ANAME_DB*/
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate #ifdef	AN_TO_LN_RULES
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  * Format and transform a principal name to a local name.  This is particularly
1597c478bd9Sstevel@tonic-gate  * useful when Kerberos principals and local user names are formatted to
1607c478bd9Sstevel@tonic-gate  * some particular convention.
1617c478bd9Sstevel@tonic-gate  *
1627c478bd9Sstevel@tonic-gate  * There are three parts to each rule:
1637c478bd9Sstevel@tonic-gate  * First part - formulate the string to perform operations on:  If not present
1647c478bd9Sstevel@tonic-gate  * then the string defaults to the fully flattened principal minus the realm
1657c478bd9Sstevel@tonic-gate  * name.  Otherwise the syntax is as follows:
1667c478bd9Sstevel@tonic-gate  *	"[" <ncomps> ":" <format> "]"
1677c478bd9Sstevel@tonic-gate  *		Where:
1687c478bd9Sstevel@tonic-gate  *			<ncomps> is the number of expected components for this
1697c478bd9Sstevel@tonic-gate  *			rule.  If the particular principal does not have this
1707c478bd9Sstevel@tonic-gate  *			many components, then this rule does not apply.
1717c478bd9Sstevel@tonic-gate  *
1727c478bd9Sstevel@tonic-gate  *			<format> is a string of <component> or verbatim
1737c478bd9Sstevel@tonic-gate  *			characters to be inserted.
1747c478bd9Sstevel@tonic-gate  *
1757c478bd9Sstevel@tonic-gate  *			<component> is of the form "$"<number> to select the
1767c478bd9Sstevel@tonic-gate  *			<number>th component.  <number> begins from 1.
1777c478bd9Sstevel@tonic-gate  *
1787c478bd9Sstevel@tonic-gate  * Second part - select rule validity:  If not present, then this rule may
1797c478bd9Sstevel@tonic-gate  * apply to all selections.  Otherwise the syntax is as follows:
1807c478bd9Sstevel@tonic-gate  *	"(" <regexp> ")"
1817c478bd9Sstevel@tonic-gate  *		Where:	<regexp> is a selector regular expression.  If this
1827c478bd9Sstevel@tonic-gate  *			regular expression matches the whole pattern generated
1837c478bd9Sstevel@tonic-gate  *			from the first part, then this rule still applies.
1847c478bd9Sstevel@tonic-gate  *
1857c478bd9Sstevel@tonic-gate  * Last part - Transform rule:  If not present, then the selection string
1867c478bd9Sstevel@tonic-gate  * is passed verbatim and is matched.  Otherwise, the syntax is as follows:
1877c478bd9Sstevel@tonic-gate  *	<rule> ...
1887c478bd9Sstevel@tonic-gate  *		Where:	<rule> is of the form:
1897c478bd9Sstevel@tonic-gate  *			"s/" <regexp> "/" <text> "/" ["g"]
190*159d09a2SMark Phalan  *
1917c478bd9Sstevel@tonic-gate  * In order to be able to select rule validity, the native system must support
1927c478bd9Sstevel@tonic-gate  * one of compile(3), re_comp(3) or regcomp(3).  In order to be able to
1937c478bd9Sstevel@tonic-gate  * transform (e.g. substitute), the native system must support regcomp(3) or
1947c478bd9Sstevel@tonic-gate  * compile(3).
1957c478bd9Sstevel@tonic-gate  */
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  * aname_do_match() 	- Does our name match the parenthesized regular
1997c478bd9Sstevel@tonic-gate  *			  expression?
200*159d09a2SMark Phalan  *
2017c478bd9Sstevel@tonic-gate  * Chew up the match portion of the regular expression and update *contextp.
2027c478bd9Sstevel@tonic-gate  * If no re_comp() or regcomp(), then always return a match.
2037c478bd9Sstevel@tonic-gate  */
2047c478bd9Sstevel@tonic-gate static krb5_error_code
aname_do_match(char * string,char ** contextp)2057c478bd9Sstevel@tonic-gate aname_do_match(char *string, char **contextp)
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
2087c478bd9Sstevel@tonic-gate     char		*regexp, *startp, *endp = 0;
2097c478bd9Sstevel@tonic-gate     size_t		regexlen;
2107c478bd9Sstevel@tonic-gate #if	HAVE_REGCOMP
2117c478bd9Sstevel@tonic-gate     regex_t		match_exp;
2127c478bd9Sstevel@tonic-gate     regmatch_t		match_match;
2137c478bd9Sstevel@tonic-gate #elif	HAVE_REGEXPR_H
2147c478bd9Sstevel@tonic-gate     char		regexp_buffer[RE_BUF_SIZE];
2157c478bd9Sstevel@tonic-gate #endif	/* HAVE_REGEXP_H */
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate     kret = 0;
2187c478bd9Sstevel@tonic-gate     /*
2197c478bd9Sstevel@tonic-gate      * Is this a match expression?
2207c478bd9Sstevel@tonic-gate      */
2217c478bd9Sstevel@tonic-gate     if (**contextp == '(') {
2227c478bd9Sstevel@tonic-gate 	kret = KRB5_CONFIG_BADFORMAT;
2237c478bd9Sstevel@tonic-gate 	startp = (*contextp) + 1;
2247c478bd9Sstevel@tonic-gate 	endp = strchr(startp, ')');
2257c478bd9Sstevel@tonic-gate 	/* Find the end of the match expression. */
2267c478bd9Sstevel@tonic-gate 	if (endp) {
2277c478bd9Sstevel@tonic-gate 	    regexlen = (size_t) (endp - startp);
2287c478bd9Sstevel@tonic-gate 	    regexp = (char *) malloc((size_t) regexlen+1);
2297c478bd9Sstevel@tonic-gate 	    kret = ENOMEM;
2307c478bd9Sstevel@tonic-gate 	    if (regexp) {
2317c478bd9Sstevel@tonic-gate 		strncpy(regexp, startp, regexlen);
2327c478bd9Sstevel@tonic-gate 		regexp[regexlen] = '\0';
2337c478bd9Sstevel@tonic-gate 		kret = KRB5_LNAME_NOTRANS;
2347c478bd9Sstevel@tonic-gate 		/*
2357c478bd9Sstevel@tonic-gate 		 * Perform the match.
2367c478bd9Sstevel@tonic-gate 		 */
2377c478bd9Sstevel@tonic-gate #if	HAVE_REGCOMP
2387c478bd9Sstevel@tonic-gate 		if (!regcomp(&match_exp, regexp, REG_EXTENDED) &&
2397c478bd9Sstevel@tonic-gate 		    !regexec(&match_exp, string, 1, &match_match, 0)) {
2407c478bd9Sstevel@tonic-gate 		    if ((match_match.rm_so == 0) &&
2417c478bd9Sstevel@tonic-gate 			(match_match.rm_eo == strlen(string)))
2427c478bd9Sstevel@tonic-gate 			kret = 0;
2437c478bd9Sstevel@tonic-gate 		}
2447c478bd9Sstevel@tonic-gate 		regfree(&match_exp);
2457c478bd9Sstevel@tonic-gate #elif	HAVE_REGEXPR_H
2467c478bd9Sstevel@tonic-gate 		compile(regexp,
2477c478bd9Sstevel@tonic-gate 			regexp_buffer,
248*159d09a2SMark Phalan 			&regexp_buffer[RE_BUF_SIZE]);
2497c478bd9Sstevel@tonic-gate 		if (step(string, regexp_buffer)) {
2507c478bd9Sstevel@tonic-gate 		    if ((loc1 == string) &&
2517c478bd9Sstevel@tonic-gate 			(loc2 == &string[strlen(string)]))
2527c478bd9Sstevel@tonic-gate 			kret = 0;
2537c478bd9Sstevel@tonic-gate 		}
2547c478bd9Sstevel@tonic-gate #elif	HAVE_RE_COMP
2557c478bd9Sstevel@tonic-gate 		if (!re_comp(regexp) && re_exec(string))
2567c478bd9Sstevel@tonic-gate 		    kret = 0;
2577c478bd9Sstevel@tonic-gate #else	/* HAVE_RE_COMP */
2587c478bd9Sstevel@tonic-gate 		kret = 0;
2597c478bd9Sstevel@tonic-gate #endif	/* HAVE_RE_COMP */
2607c478bd9Sstevel@tonic-gate 		free(regexp);
2617c478bd9Sstevel@tonic-gate 	    }
2627c478bd9Sstevel@tonic-gate 	    endp++;
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate 	else
2657c478bd9Sstevel@tonic-gate 	    endp = startp;
2667c478bd9Sstevel@tonic-gate     }
2677c478bd9Sstevel@tonic-gate     *contextp = endp;
2687c478bd9Sstevel@tonic-gate     return(kret);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate /*
2727c478bd9Sstevel@tonic-gate  * do_replacement()	- Replace the regular expression with the specified
2737c478bd9Sstevel@tonic-gate  * 			  replacement.
2747c478bd9Sstevel@tonic-gate  *
2757c478bd9Sstevel@tonic-gate  * If "doall" is set, it's a global replacement, otherwise, just a oneshot
2767c478bd9Sstevel@tonic-gate  * deal.
2777c478bd9Sstevel@tonic-gate  * If no regcomp() then just return the input string verbatim in the output
2787c478bd9Sstevel@tonic-gate  * string.
2797c478bd9Sstevel@tonic-gate  */
2807c478bd9Sstevel@tonic-gate #define use_bytes(x) \
281*159d09a2SMark Phalan     out_used += (x); \
282*159d09a2SMark Phalan     if (out_used > MAX_FORMAT_BUFFER) goto mem_err
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate static int
do_replacement(char * regexp,char * repl,int doall,char * in,char * out)2857c478bd9Sstevel@tonic-gate do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate     size_t out_used = 0;
2887c478bd9Sstevel@tonic-gate #if	HAVE_REGCOMP
2897c478bd9Sstevel@tonic-gate     regex_t	match_exp;
2907c478bd9Sstevel@tonic-gate     regmatch_t	match_match;
2917c478bd9Sstevel@tonic-gate     int		matched;
2927c478bd9Sstevel@tonic-gate     char	*cp;
2937c478bd9Sstevel@tonic-gate     char	*op;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate     if (!regcomp(&match_exp, regexp, REG_EXTENDED)) {
2967c478bd9Sstevel@tonic-gate 	cp = in;
2977c478bd9Sstevel@tonic-gate 	op = out;
2987c478bd9Sstevel@tonic-gate 	matched = 0;
2997c478bd9Sstevel@tonic-gate 	do {
3007c478bd9Sstevel@tonic-gate 	    if (!regexec(&match_exp, cp, 1, &match_match, 0)) {
3017c478bd9Sstevel@tonic-gate 		if (match_match.rm_so) {
3027c478bd9Sstevel@tonic-gate 		    use_bytes(match_match.rm_so);
3037c478bd9Sstevel@tonic-gate 		    strncpy(op, cp, match_match.rm_so);
3047c478bd9Sstevel@tonic-gate 		    op += match_match.rm_so;
3057c478bd9Sstevel@tonic-gate 		}
3067c478bd9Sstevel@tonic-gate 		use_bytes(strlen(repl));
3077c478bd9Sstevel@tonic-gate 		strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
3087c478bd9Sstevel@tonic-gate 		op += strlen(op);
3097c478bd9Sstevel@tonic-gate 		cp += match_match.rm_eo;
3107c478bd9Sstevel@tonic-gate 		if (!doall) {
3117c478bd9Sstevel@tonic-gate 		    use_bytes(strlen(cp));
3127c478bd9Sstevel@tonic-gate 		    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
3137c478bd9Sstevel@tonic-gate 		}
3147c478bd9Sstevel@tonic-gate 		matched = 1;
3157c478bd9Sstevel@tonic-gate 	    }
3167c478bd9Sstevel@tonic-gate 	    else {
3177c478bd9Sstevel@tonic-gate 		use_bytes(strlen(cp));
3187c478bd9Sstevel@tonic-gate 		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
3197c478bd9Sstevel@tonic-gate 		matched = 0;
3207c478bd9Sstevel@tonic-gate 	    }
3217c478bd9Sstevel@tonic-gate 	} while (doall && matched);
3227c478bd9Sstevel@tonic-gate 	regfree(&match_exp);
3237c478bd9Sstevel@tonic-gate     }
3247c478bd9Sstevel@tonic-gate #elif	HAVE_REGEXPR_H
3257c478bd9Sstevel@tonic-gate     int		matched;
3267c478bd9Sstevel@tonic-gate     char	*cp;
3277c478bd9Sstevel@tonic-gate     char	*op;
3287c478bd9Sstevel@tonic-gate     char	regexp_buffer[RE_BUF_SIZE];
3297c478bd9Sstevel@tonic-gate     size_t	sdispl, edispl;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate     compile(regexp,
3327c478bd9Sstevel@tonic-gate 	    regexp_buffer,
333*159d09a2SMark Phalan 	    &regexp_buffer[RE_BUF_SIZE]);
3347c478bd9Sstevel@tonic-gate     cp = in;
3357c478bd9Sstevel@tonic-gate     op = out;
3367c478bd9Sstevel@tonic-gate     matched = 0;
3377c478bd9Sstevel@tonic-gate     do {
3387c478bd9Sstevel@tonic-gate 	if (step(cp, regexp_buffer)) {
3397c478bd9Sstevel@tonic-gate 	    sdispl = (size_t) (loc1 - cp);
3407c478bd9Sstevel@tonic-gate 	    edispl = (size_t) (loc2 - cp);
3417c478bd9Sstevel@tonic-gate 	    if (sdispl) {
3427c478bd9Sstevel@tonic-gate 		use_bytes(sdispl);
3437c478bd9Sstevel@tonic-gate 		strncpy(op, cp, sdispl);
3447c478bd9Sstevel@tonic-gate 		op += sdispl;
3457c478bd9Sstevel@tonic-gate 	    }
3467c478bd9Sstevel@tonic-gate 	    use_bytes(strlen(repl));
3477c478bd9Sstevel@tonic-gate 	    strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
3487c478bd9Sstevel@tonic-gate 	    op += strlen(repl);
3497c478bd9Sstevel@tonic-gate 	    cp += edispl;
3507c478bd9Sstevel@tonic-gate 	    if (!doall) {
3517c478bd9Sstevel@tonic-gate 		use_bytes(strlen(cp));
3527c478bd9Sstevel@tonic-gate 		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
3537c478bd9Sstevel@tonic-gate 	    }
3547c478bd9Sstevel@tonic-gate 	    matched = 1;
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 	else {
3577c478bd9Sstevel@tonic-gate 	    use_bytes(strlen(cp));
3587c478bd9Sstevel@tonic-gate 	    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
3597c478bd9Sstevel@tonic-gate 	    matched = 0;
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate     } while (doall && matched);
3627c478bd9Sstevel@tonic-gate #else	/* HAVE_REGEXP_H */
3637c478bd9Sstevel@tonic-gate     memcpy(out, in, MAX_FORMAT_BUFFER);
3647c478bd9Sstevel@tonic-gate #endif	/* HAVE_REGCOMP */
3657c478bd9Sstevel@tonic-gate     return 1;
3667c478bd9Sstevel@tonic-gate  mem_err:
3677c478bd9Sstevel@tonic-gate #ifdef HAVE_REGCMP
3687c478bd9Sstevel@tonic-gate     	regfree(&match_exp);
3697c478bd9Sstevel@tonic-gate #endif
3707c478bd9Sstevel@tonic-gate 	return 0;
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate #undef use_bytes
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate  * aname_replacer()	- Perform the specified substitutions on the input
3777c478bd9Sstevel@tonic-gate  *			  string and return the result.
3787c478bd9Sstevel@tonic-gate  *
3797c478bd9Sstevel@tonic-gate  * This routine enforces the "s/<pattern>/<replacement>/[g]" syntax.
3807c478bd9Sstevel@tonic-gate  */
3817c478bd9Sstevel@tonic-gate static krb5_error_code
aname_replacer(char * string,char ** contextp,char ** result)3827c478bd9Sstevel@tonic-gate aname_replacer(char *string, char **contextp, char **result)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
3857c478bd9Sstevel@tonic-gate     char		*in;
3867c478bd9Sstevel@tonic-gate     char		*out;
3877c478bd9Sstevel@tonic-gate     char		*cp, *ep, *tp;
3887c478bd9Sstevel@tonic-gate     char		*rule, *repl;
3897c478bd9Sstevel@tonic-gate     size_t		rule_size, repl_size;
3907c478bd9Sstevel@tonic-gate     int			doglobal;
3917c478bd9Sstevel@tonic-gate     char		sep;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate     kret = ENOMEM;
3947c478bd9Sstevel@tonic-gate     *result = (char *) NULL;
3957c478bd9Sstevel@tonic-gate     /* Allocate the formatting buffers */
396*159d09a2SMark Phalan     /* Solaris Kerberos */
3977c478bd9Sstevel@tonic-gate     if (((in = (char *) malloc(MAX_FORMAT_BUFFER)) != NULL) &&
3987c478bd9Sstevel@tonic-gate 	((out = (char *) malloc(MAX_FORMAT_BUFFER)) != NULL)) {
3997c478bd9Sstevel@tonic-gate 	/*
4007c478bd9Sstevel@tonic-gate 	 * Prime the buffers.  Copy input string to "out" to simulate it
4017c478bd9Sstevel@tonic-gate 	 * being the result of an initial iteration.
4027c478bd9Sstevel@tonic-gate 	 */
4037c478bd9Sstevel@tonic-gate 	strncpy(out, string, MAX_FORMAT_BUFFER - 1);
4047c478bd9Sstevel@tonic-gate 	out[MAX_FORMAT_BUFFER - 1] = '\0';
4057c478bd9Sstevel@tonic-gate 	in[0] = '\0';
4067c478bd9Sstevel@tonic-gate 	kret = 0;
4077c478bd9Sstevel@tonic-gate 	/*
4087c478bd9Sstevel@tonic-gate 	 * Pound through the expression until we're done.
4097c478bd9Sstevel@tonic-gate 	 */
4107c478bd9Sstevel@tonic-gate 	for (cp = *contextp; *cp; ) {
4117c478bd9Sstevel@tonic-gate 	    /* Skip leading whitespace */
412*159d09a2SMark Phalan 	    while (isspace((int) (*cp)))
4137c478bd9Sstevel@tonic-gate 		cp++;
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	    /*
416*159d09a2SMark Phalan 	     * Solaris Kerberos
4177c478bd9Sstevel@tonic-gate 	     * Find our separators.  First two characters must be "s<sep>"
4187c478bd9Sstevel@tonic-gate 	     * We must also find another "<sep>" followed by another * "<sep>".
4197c478bd9Sstevel@tonic-gate 	     */
4207c478bd9Sstevel@tonic-gate 	    if (cp[0] != 's') {
4217c478bd9Sstevel@tonic-gate 		/* Bad syntax */
4227c478bd9Sstevel@tonic-gate 		kret = KRB5_CONFIG_BADFORMAT;
4237c478bd9Sstevel@tonic-gate 		break;
4247c478bd9Sstevel@tonic-gate 	    }
4257c478bd9Sstevel@tonic-gate 	    if (strspn(cp + 1, ",/;|!%") < 1) {
4267c478bd9Sstevel@tonic-gate 		/* Bad syntax */
4277c478bd9Sstevel@tonic-gate 		kret = KRB5_CONFIG_BADFORMAT;
4287c478bd9Sstevel@tonic-gate 		break;
4297c478bd9Sstevel@tonic-gate 	    }
4307c478bd9Sstevel@tonic-gate 	    sep = cp[1];
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	    if (((ep = strchr(&cp[2], sep)) != NULL) &&
4337c478bd9Sstevel@tonic-gate 		((tp = strchr(&ep[1], sep)) != NULL)) {
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 		/* Figure out sizes of strings and allocate them */
4367c478bd9Sstevel@tonic-gate 		rule_size = (size_t) (ep - &cp[2]);
4377c478bd9Sstevel@tonic-gate 		repl_size = (size_t) (tp - &ep[1]);
438*159d09a2SMark Phalan 		/* Solaris Kerberos */
4397c478bd9Sstevel@tonic-gate 		if (((rule = (char *) malloc(rule_size+1)) != NULL) &&
4407c478bd9Sstevel@tonic-gate 		    ((repl = (char *) malloc(repl_size+1)) != NULL)) {
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 		    /* Copy the strings */
4437c478bd9Sstevel@tonic-gate 		    strncpy(rule, &cp[2], rule_size);
4447c478bd9Sstevel@tonic-gate 		    strncpy(repl, &ep[1], repl_size);
4457c478bd9Sstevel@tonic-gate 		    rule[rule_size] = repl[repl_size] = '\0';
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 		    /* Check for trailing "g" */
4487c478bd9Sstevel@tonic-gate 		    doglobal = (tp[1] == 'g') ? 1 : 0;
4497c478bd9Sstevel@tonic-gate 		    if (doglobal)
4507c478bd9Sstevel@tonic-gate 			tp++;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 		    /* Swap previous in and out buffers */
4537c478bd9Sstevel@tonic-gate 		    ep = in;
4547c478bd9Sstevel@tonic-gate 		    in = out;
4557c478bd9Sstevel@tonic-gate 		    out = ep;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 		    /* Do the replacemenbt */
4587c478bd9Sstevel@tonic-gate 		    memset(out, '\0', MAX_FORMAT_BUFFER);
4597c478bd9Sstevel@tonic-gate 		    if (!do_replacement(rule, repl, doglobal, in, out)) {
4607c478bd9Sstevel@tonic-gate 			free(rule);
4617c478bd9Sstevel@tonic-gate 		    free(repl);
4627c478bd9Sstevel@tonic-gate 			kret = KRB5_LNAME_NOTRANS;
4637c478bd9Sstevel@tonic-gate 			break;
4647c478bd9Sstevel@tonic-gate 		    }
4657c478bd9Sstevel@tonic-gate 		    free(rule);
4667c478bd9Sstevel@tonic-gate 		    free(repl);
4677c478bd9Sstevel@tonic-gate 
4687c478bd9Sstevel@tonic-gate 		    /* If we have no output buffer left, this can't be good */
4697c478bd9Sstevel@tonic-gate 		    if (strlen(out) == 0) {
4707c478bd9Sstevel@tonic-gate 			kret = KRB5_LNAME_NOTRANS;
4717c478bd9Sstevel@tonic-gate 			break;
4727c478bd9Sstevel@tonic-gate 		    }
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 		else {
4757c478bd9Sstevel@tonic-gate 		    /* No memory for copies */
4767c478bd9Sstevel@tonic-gate 		    kret = ENOMEM;
4777c478bd9Sstevel@tonic-gate 		    break;
4787c478bd9Sstevel@tonic-gate 		}
4797c478bd9Sstevel@tonic-gate 	    }
4807c478bd9Sstevel@tonic-gate 	    else {
4817c478bd9Sstevel@tonic-gate 		/* Bad syntax */
4827c478bd9Sstevel@tonic-gate 		kret = KRB5_CONFIG_BADFORMAT;
4837c478bd9Sstevel@tonic-gate 		break;
4847c478bd9Sstevel@tonic-gate 	    }
4857c478bd9Sstevel@tonic-gate 	    /* Advance past trailer */
4867c478bd9Sstevel@tonic-gate 	    cp = &tp[1];
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 	free(in);
4897c478bd9Sstevel@tonic-gate 	if (!kret)
4907c478bd9Sstevel@tonic-gate 	    *result = out;
4917c478bd9Sstevel@tonic-gate 	else
4927c478bd9Sstevel@tonic-gate 	    free(out);
4937c478bd9Sstevel@tonic-gate     }
4947c478bd9Sstevel@tonic-gate     return(kret);
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate /*
4987c478bd9Sstevel@tonic-gate  * rule_an_to_ln()	- Handle aname to lname translations for RULE rules.
4997c478bd9Sstevel@tonic-gate  *
5007c478bd9Sstevel@tonic-gate  * The initial part of this routine handles the formulation of the strings from
5017c478bd9Sstevel@tonic-gate  * the principal name.
5027c478bd9Sstevel@tonic-gate  */
5037c478bd9Sstevel@tonic-gate static krb5_error_code
rule_an_to_ln(krb5_context context,char * rule,krb5_const_principal aname,const unsigned int lnsize,char * lname)504*159d09a2SMark Phalan rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, const unsigned int lnsize, char *lname)
5057c478bd9Sstevel@tonic-gate {
5067c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
5077c478bd9Sstevel@tonic-gate     char		*current;
5087c478bd9Sstevel@tonic-gate     char		*fprincname;
5097c478bd9Sstevel@tonic-gate     char		*selstring = 0;
5107c478bd9Sstevel@tonic-gate     int			num_comps, compind;
5117c478bd9Sstevel@tonic-gate     size_t selstring_used;
5127c478bd9Sstevel@tonic-gate     char		*cout;
5137c478bd9Sstevel@tonic-gate     krb5_const krb5_data *datap;
5147c478bd9Sstevel@tonic-gate     char		*outstring;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate     /*
5177c478bd9Sstevel@tonic-gate      * First flatten the name.
5187c478bd9Sstevel@tonic-gate      */
5197c478bd9Sstevel@tonic-gate     current = rule;
5207c478bd9Sstevel@tonic-gate     if (!(kret = krb5_unparse_name(context, aname, &fprincname))) {
5217c478bd9Sstevel@tonic-gate 	/*
5227c478bd9Sstevel@tonic-gate 	 * First part.
5237c478bd9Sstevel@tonic-gate 	 */
5247c478bd9Sstevel@tonic-gate 	if (*current == '[') {
5257c478bd9Sstevel@tonic-gate 	    if (sscanf(current+1,"%d:", &num_comps) == 1) {
5267c478bd9Sstevel@tonic-gate 		if (num_comps == aname->length) {
5277c478bd9Sstevel@tonic-gate 		    /*
5287c478bd9Sstevel@tonic-gate 		     * We have a match based on the number of components.
5297c478bd9Sstevel@tonic-gate 		     */
5307c478bd9Sstevel@tonic-gate 		    current = strchr(current, ':');
5317c478bd9Sstevel@tonic-gate 		    selstring = (char *) malloc(MAX_FORMAT_BUFFER);
5327c478bd9Sstevel@tonic-gate 		    selstring_used = 0;
5337c478bd9Sstevel@tonic-gate 		    if (current && selstring) {
5347c478bd9Sstevel@tonic-gate 			current++;
5357c478bd9Sstevel@tonic-gate 			cout = selstring;
5367c478bd9Sstevel@tonic-gate 			/*
5377c478bd9Sstevel@tonic-gate 			 * Plow through the string.
5387c478bd9Sstevel@tonic-gate 			 */
5397c478bd9Sstevel@tonic-gate 			while ((*current != ']') &&
5407c478bd9Sstevel@tonic-gate 			       (*current != '\0')) {
5417c478bd9Sstevel@tonic-gate 			    /*
5427c478bd9Sstevel@tonic-gate 			     * Expand to a component.
5437c478bd9Sstevel@tonic-gate 			     */
5447c478bd9Sstevel@tonic-gate 			    if (*current == '$') {
5457c478bd9Sstevel@tonic-gate 				if ((sscanf(current+1, "%d", &compind) == 1) &&
5467c478bd9Sstevel@tonic-gate 				    (compind <= num_comps) &&
547*159d09a2SMark Phalan 				    (datap =
548*159d09a2SMark Phalan 				     (compind > 0)
549*159d09a2SMark Phalan 				     ? krb5_princ_component(context, aname,
550*159d09a2SMark Phalan 							    compind-1)
551*159d09a2SMark Phalan 				     : krb5_princ_realm(context, aname))
552*159d09a2SMark Phalan 				    ) {
5537c478bd9Sstevel@tonic-gate 				    if ((datap->length < MAX_FORMAT_BUFFER)
5547c478bd9Sstevel@tonic-gate 					&&  (selstring_used+datap->length
5557c478bd9Sstevel@tonic-gate 					     < MAX_FORMAT_BUFFER)) {
5567c478bd9Sstevel@tonic-gate 					selstring_used += datap->length;
5577c478bd9Sstevel@tonic-gate 				    } else {
558505d05c7Sgtb 					kret = ENOMEM;
5597c478bd9Sstevel@tonic-gate 					goto errout;
5607c478bd9Sstevel@tonic-gate 				    }
5617c478bd9Sstevel@tonic-gate 				    strncpy(cout,
5627c478bd9Sstevel@tonic-gate 					    datap->data,
563505d05c7Sgtb 					    (unsigned) datap->length);
5647c478bd9Sstevel@tonic-gate 				    cout += datap->length;
5657c478bd9Sstevel@tonic-gate 				    *cout = '\0';
5667c478bd9Sstevel@tonic-gate 				    current++;
5677c478bd9Sstevel@tonic-gate 				    /* Point past number */
568*159d09a2SMark Phalan 				    while (isdigit((int) (*current)))
5697c478bd9Sstevel@tonic-gate 					current++;
5707c478bd9Sstevel@tonic-gate 				}
5717c478bd9Sstevel@tonic-gate 				else
5727c478bd9Sstevel@tonic-gate 				    kret = KRB5_CONFIG_BADFORMAT;
5737c478bd9Sstevel@tonic-gate 			    }
5747c478bd9Sstevel@tonic-gate 			    else {
5757c478bd9Sstevel@tonic-gate 				/* Copy in verbatim. */
5767c478bd9Sstevel@tonic-gate 				*cout = *current;
5777c478bd9Sstevel@tonic-gate 				cout++;
5787c478bd9Sstevel@tonic-gate 				*cout = '\0';
5797c478bd9Sstevel@tonic-gate 				current++;
5807c478bd9Sstevel@tonic-gate 			    }
5817c478bd9Sstevel@tonic-gate 			}
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 			/*
5847c478bd9Sstevel@tonic-gate 			 * Advance past separator if appropriate.
5857c478bd9Sstevel@tonic-gate 			 */
5867c478bd9Sstevel@tonic-gate 			if (*current == ']')
5877c478bd9Sstevel@tonic-gate 			    current++;
5887c478bd9Sstevel@tonic-gate 			else
5897c478bd9Sstevel@tonic-gate 			    kret = KRB5_CONFIG_BADFORMAT;
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 			errout: if (kret)
5927c478bd9Sstevel@tonic-gate 			    free(selstring);
5937c478bd9Sstevel@tonic-gate 		    }
5947c478bd9Sstevel@tonic-gate 		}
5957c478bd9Sstevel@tonic-gate 		else
5967c478bd9Sstevel@tonic-gate 		    kret = KRB5_LNAME_NOTRANS;
5977c478bd9Sstevel@tonic-gate 	    }
5987c478bd9Sstevel@tonic-gate 	    else
5997c478bd9Sstevel@tonic-gate 		kret = KRB5_CONFIG_BADFORMAT;
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate 	else {
6027c478bd9Sstevel@tonic-gate 	    if (!(selstring = aname_full_to_mapping_name(fprincname)))
6037c478bd9Sstevel@tonic-gate 		kret = ENOMEM;
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 	krb5_xfree(fprincname);
6067c478bd9Sstevel@tonic-gate     }
6077c478bd9Sstevel@tonic-gate     if (!kret) {
6087c478bd9Sstevel@tonic-gate 	/*
6097c478bd9Sstevel@tonic-gate 	 * Second part
6107c478bd9Sstevel@tonic-gate 	 */
6117c478bd9Sstevel@tonic-gate 	if (*current == '(')
6127c478bd9Sstevel@tonic-gate 	    kret = aname_do_match(selstring, &current);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	/*
6157c478bd9Sstevel@tonic-gate 	 * Third part.
6167c478bd9Sstevel@tonic-gate 	 */
6177c478bd9Sstevel@tonic-gate 	if (!kret) {
6187c478bd9Sstevel@tonic-gate 	    outstring = (char *) NULL;
6197c478bd9Sstevel@tonic-gate 	    kret = aname_replacer(selstring, &current, &outstring);
6207c478bd9Sstevel@tonic-gate 	    if (outstring) {
6217c478bd9Sstevel@tonic-gate 		/* Copy out the value if there's enough room */
6227c478bd9Sstevel@tonic-gate 		if (strlen(outstring)+1 <= (size_t) lnsize)
6237c478bd9Sstevel@tonic-gate 		    strcpy(lname, outstring);
6247c478bd9Sstevel@tonic-gate 		else
6257c478bd9Sstevel@tonic-gate 		    kret = KRB5_CONFIG_NOTENUFSPACE;
6267c478bd9Sstevel@tonic-gate 		free(outstring);
6277c478bd9Sstevel@tonic-gate 	    }
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 	free(selstring);
6307c478bd9Sstevel@tonic-gate     }
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate     return(kret);
6337c478bd9Sstevel@tonic-gate }
6347c478bd9Sstevel@tonic-gate #endif	/* AN_TO_LN_RULES */
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate /*
6377c478bd9Sstevel@tonic-gate  * Solaris Kerberos
6387c478bd9Sstevel@tonic-gate  * Return true (1) if the princ's realm matches any of the
6397c478bd9Sstevel@tonic-gate  * 'auth_to_local_realm' relations in the default realm section.
6407c478bd9Sstevel@tonic-gate  */
6417c478bd9Sstevel@tonic-gate static int
an_to_ln_realm_chk(krb5_context context,krb5_const_principal aname,char * def_realm,int realm_length)6427c478bd9Sstevel@tonic-gate an_to_ln_realm_chk(
6437c478bd9Sstevel@tonic-gate 	krb5_context context,
6447c478bd9Sstevel@tonic-gate 	krb5_const_principal aname,
6457c478bd9Sstevel@tonic-gate 	char *def_realm,
6467c478bd9Sstevel@tonic-gate 	int realm_length)
6477c478bd9Sstevel@tonic-gate {
6487c478bd9Sstevel@tonic-gate 	char        **values, **cpp;
6497c478bd9Sstevel@tonic-gate 	const char  *realm_names[4];
6507c478bd9Sstevel@tonic-gate 	krb5_error_code     retval;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	realm_names[0] = "realms";
6537c478bd9Sstevel@tonic-gate 	realm_names[1] = def_realm;
6547c478bd9Sstevel@tonic-gate 	realm_names[2] = "auth_to_local_realm";
6557c478bd9Sstevel@tonic-gate 	realm_names[3] = 0;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	if (context->profile == 0)
6587c478bd9Sstevel@tonic-gate 		return (0);
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	retval = profile_get_values(context->profile, realm_names,
6617c478bd9Sstevel@tonic-gate 				    &values);
6627c478bd9Sstevel@tonic-gate 	if (retval)
6637c478bd9Sstevel@tonic-gate 		return (0);
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate 	for (cpp = values; *cpp; cpp++) {
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 		if (((size_t) realm_length == strlen(*cpp)) &&
6687c478bd9Sstevel@tonic-gate 		    (memcmp(*cpp, krb5_princ_realm(context, aname)->data,
6697c478bd9Sstevel@tonic-gate 			    realm_length) == 0)) {
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 			profile_free_list(values);
6727c478bd9Sstevel@tonic-gate 			return (1); /* success */
6737c478bd9Sstevel@tonic-gate 		}
6747c478bd9Sstevel@tonic-gate 	}
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 	profile_free_list(values);
6777c478bd9Sstevel@tonic-gate 	return (0);
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate /*
6817c478bd9Sstevel@tonic-gate  * Implementation:  This version checks the realm to see if it is the local
6827c478bd9Sstevel@tonic-gate  * realm; if so, and there is exactly one non-realm component to the name,
6837c478bd9Sstevel@tonic-gate  * that name is returned as the lname.
6847c478bd9Sstevel@tonic-gate  */
6857c478bd9Sstevel@tonic-gate static krb5_error_code
default_an_to_ln(krb5_context context,krb5_const_principal aname,const unsigned int lnsize,char * lname)686*159d09a2SMark Phalan default_an_to_ln(krb5_context context, krb5_const_principal aname, const unsigned int lnsize, char *lname)
6877c478bd9Sstevel@tonic-gate {
6887c478bd9Sstevel@tonic-gate     krb5_error_code retval;
6897c478bd9Sstevel@tonic-gate     char *def_realm;
690505d05c7Sgtb     unsigned int realm_length;
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate     realm_length = krb5_princ_realm(context, aname)->length;
693*159d09a2SMark Phalan 
6947c478bd9Sstevel@tonic-gate     if ((retval = krb5_get_default_realm(context, &def_realm))) {
6957c478bd9Sstevel@tonic-gate 	return(retval);
6967c478bd9Sstevel@tonic-gate     }
697*159d09a2SMark Phalan     /* Solaris Kerberos */
6987c478bd9Sstevel@tonic-gate     /* compare against default realm and auth_to_local_realm(s) */
6997c478bd9Sstevel@tonic-gate     if ((((size_t) realm_length != strlen(def_realm)) ||
7007c478bd9Sstevel@tonic-gate         (memcmp(def_realm, krb5_princ_realm(context, aname)->data,
7017c478bd9Sstevel@tonic-gate 		realm_length))) &&
7027c478bd9Sstevel@tonic-gate 	!an_to_ln_realm_chk(context, aname, def_realm,
7037c478bd9Sstevel@tonic-gate 			    realm_length)) {
7047c478bd9Sstevel@tonic-gate         free(def_realm);
7057c478bd9Sstevel@tonic-gate         return KRB5_LNAME_NOTRANS;
7067c478bd9Sstevel@tonic-gate     }
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate     if (krb5_princ_size(context, aname) != 1) {
7097c478bd9Sstevel@tonic-gate         if (krb5_princ_size(context, aname) == 2 ) {
7107c478bd9Sstevel@tonic-gate            /* Check to see if 2nd component is the local realm. */
711*159d09a2SMark Phalan            if ( strncmp(krb5_princ_component(context, aname,1)->data,def_realm,
712*159d09a2SMark Phalan                         realm_length) ||
713*159d09a2SMark Phalan                 realm_length != krb5_princ_component(context, aname,1)->length) {
7147c478bd9Sstevel@tonic-gate 		    /* XXX an_to_ln_realm_chk ? */
715*159d09a2SMark Phalan 		/* Solaris Kerberos */
716ab9b2e15Sgtb 		free(def_realm);
7177c478bd9Sstevel@tonic-gate                 return KRB5_LNAME_NOTRANS;
718ab9b2e15Sgtb 	    }
7197c478bd9Sstevel@tonic-gate         }
720ab9b2e15Sgtb         else {
7217c478bd9Sstevel@tonic-gate            /* no components or more than one component to non-realm part of name
7227c478bd9Sstevel@tonic-gate            --no translation. */
723*159d09a2SMark Phalan 	    /* Solaris Kerberos */
724ab9b2e15Sgtb 	    free(def_realm);
7257c478bd9Sstevel@tonic-gate             return KRB5_LNAME_NOTRANS;
726ab9b2e15Sgtb 	}
7277c478bd9Sstevel@tonic-gate     }
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate     free(def_realm);
730*159d09a2SMark Phalan     strncpy(lname, krb5_princ_component(context, aname,0)->data,
7317c478bd9Sstevel@tonic-gate 	    min(krb5_princ_component(context, aname,0)->length,lnsize));
7327c478bd9Sstevel@tonic-gate     if (lnsize <= krb5_princ_component(context, aname,0)->length ) {
7337c478bd9Sstevel@tonic-gate 	retval = KRB5_CONFIG_NOTENUFSPACE;
7347c478bd9Sstevel@tonic-gate     } else {
7357c478bd9Sstevel@tonic-gate 	lname[krb5_princ_component(context, aname,0)->length] = '\0';
7367c478bd9Sstevel@tonic-gate 	retval = 0;
7377c478bd9Sstevel@tonic-gate     }
7387c478bd9Sstevel@tonic-gate     return retval;
7397c478bd9Sstevel@tonic-gate }
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate /*
7427c478bd9Sstevel@tonic-gate  Converts an authentication name to a local name suitable for use by
7437c478bd9Sstevel@tonic-gate  programs wishing a translation to an environment-specific name (e.g.
7447c478bd9Sstevel@tonic-gate  user account name).
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate  lnsize specifies the maximum length name that is to be filled into
7477c478bd9Sstevel@tonic-gate  lname.
7487c478bd9Sstevel@tonic-gate  The translation will be null terminated in all non-error returns.
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate  returns system errors, NOT_ENOUGH_SPACE
7517c478bd9Sstevel@tonic-gate */
7527c478bd9Sstevel@tonic-gate 
753*159d09a2SMark Phalan krb5_error_code KRB5_CALLCONV
krb5_aname_to_localname(krb5_context context,krb5_const_principal aname,const int lnsize_in,char * lname)754*159d09a2SMark Phalan krb5_aname_to_localname(krb5_context context, krb5_const_principal aname, const int lnsize_in, char *lname)
7557c478bd9Sstevel@tonic-gate {
7567c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
7577c478bd9Sstevel@tonic-gate     char		*realm;
7587c478bd9Sstevel@tonic-gate     char		*pname;
7597c478bd9Sstevel@tonic-gate     char		*mname;
7607c478bd9Sstevel@tonic-gate     const char		*hierarchy[5];
7617c478bd9Sstevel@tonic-gate     char		**mapping_values;
7627c478bd9Sstevel@tonic-gate     int			i, nvalid;
7637c478bd9Sstevel@tonic-gate     char		*cp, *s;
7647c478bd9Sstevel@tonic-gate     char		*typep, *argp;
765505d05c7Sgtb     unsigned int        lnsize;
7667c478bd9Sstevel@tonic-gate 
767505d05c7Sgtb     if (lnsize_in < 0)
768*159d09a2SMark Phalan       return KRB5_CONFIG_NOTENUFSPACE;
7697c478bd9Sstevel@tonic-gate 
770505d05c7Sgtb     lnsize = lnsize_in; /* Unsigned */
771505d05c7Sgtb 
7727c478bd9Sstevel@tonic-gate     /*
7737c478bd9Sstevel@tonic-gate      * First get the default realm.
7747c478bd9Sstevel@tonic-gate      */
7757c478bd9Sstevel@tonic-gate     if (!(kret = krb5_get_default_realm(context, &realm))) {
7767c478bd9Sstevel@tonic-gate 	/* Flatten the name */
7777c478bd9Sstevel@tonic-gate 	if (!(kret = krb5_unparse_name(context, aname, &pname))) {
7787c478bd9Sstevel@tonic-gate 	    if ((mname = aname_full_to_mapping_name(pname))) {
7797c478bd9Sstevel@tonic-gate 		/*
7807c478bd9Sstevel@tonic-gate 		 * Search first for explicit mappings of the form:
7817c478bd9Sstevel@tonic-gate 		 *
7827c478bd9Sstevel@tonic-gate 		 * [realms]->realm->"auth_to_local_names"->mapping_name
7837c478bd9Sstevel@tonic-gate 		 */
7847c478bd9Sstevel@tonic-gate 		hierarchy[0] = "realms";
7857c478bd9Sstevel@tonic-gate 		hierarchy[1] = realm;
7867c478bd9Sstevel@tonic-gate 		hierarchy[2] = "auth_to_local_names";
7877c478bd9Sstevel@tonic-gate 		hierarchy[3] = mname;
7887c478bd9Sstevel@tonic-gate 		hierarchy[4] = (char *) NULL;
7897c478bd9Sstevel@tonic-gate 		if (!(kret = profile_get_values(context->profile,
7907c478bd9Sstevel@tonic-gate 						hierarchy,
7917c478bd9Sstevel@tonic-gate 						&mapping_values))) {
7927c478bd9Sstevel@tonic-gate 		    /* We found one or more explicit mappings. */
7937c478bd9Sstevel@tonic-gate 		    for (nvalid=0; mapping_values[nvalid]; nvalid++);
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 		    /* Just use the last one. */
7967c478bd9Sstevel@tonic-gate 		    /* Trim the value. */
7977c478bd9Sstevel@tonic-gate 		    s = mapping_values[nvalid-1];
7987c478bd9Sstevel@tonic-gate 		    cp = s + strlen(s);
7997c478bd9Sstevel@tonic-gate 		    while (cp > s) {
8007c478bd9Sstevel@tonic-gate 			cp--;
8017c478bd9Sstevel@tonic-gate 			if (!isspace((int)(*cp)))
8027c478bd9Sstevel@tonic-gate 			    break;
8037c478bd9Sstevel@tonic-gate 			*cp = '\0';
8047c478bd9Sstevel@tonic-gate 		    }
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 		    /* Copy out the value if there's enough room */
8077c478bd9Sstevel@tonic-gate 		    if (strlen(mapping_values[nvalid-1])+1 <= (size_t) lnsize)
8087c478bd9Sstevel@tonic-gate 			strcpy(lname, mapping_values[nvalid-1]);
8097c478bd9Sstevel@tonic-gate 		    else
8107c478bd9Sstevel@tonic-gate 			kret = KRB5_CONFIG_NOTENUFSPACE;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 		    /* Free residue */
8137c478bd9Sstevel@tonic-gate 		    profile_free_list(mapping_values);
8147c478bd9Sstevel@tonic-gate 		}
8157c478bd9Sstevel@tonic-gate 		else {
8167c478bd9Sstevel@tonic-gate 		    /*
8177c478bd9Sstevel@tonic-gate 		     * OK - There's no explicit mapping.  Now check for
8187c478bd9Sstevel@tonic-gate 		     * general auth_to_local rules of the form:
8197c478bd9Sstevel@tonic-gate 		     *
8207c478bd9Sstevel@tonic-gate 		     * [realms]->realm->"auth_to_local"
8217c478bd9Sstevel@tonic-gate 		     *
8227c478bd9Sstevel@tonic-gate 		     * This can have one or more of the following kinds of
8237c478bd9Sstevel@tonic-gate 		     * values:
8247c478bd9Sstevel@tonic-gate 		     *	DB:<filename>	- Look up principal in aname database.
8257c478bd9Sstevel@tonic-gate 		     *	RULE:<sed-exp>	- Formulate lname from sed-exp.
8267c478bd9Sstevel@tonic-gate 		     *	DEFAULT		- Use default rule.
8277c478bd9Sstevel@tonic-gate 		     * The first rule to find a match is used.
8287c478bd9Sstevel@tonic-gate 		     */
8297c478bd9Sstevel@tonic-gate 		    hierarchy[0] = "realms";
8307c478bd9Sstevel@tonic-gate 		    hierarchy[1] = realm;
8317c478bd9Sstevel@tonic-gate 		    hierarchy[2] = "auth_to_local";
8327c478bd9Sstevel@tonic-gate 		    hierarchy[3] = (char *) NULL;
8337c478bd9Sstevel@tonic-gate 		    if (!(kret = profile_get_values(context->profile,
8347c478bd9Sstevel@tonic-gate 						    hierarchy,
8357c478bd9Sstevel@tonic-gate 						    &mapping_values))) {
8367c478bd9Sstevel@tonic-gate 			/*
8377c478bd9Sstevel@tonic-gate 			 * Loop through all the mapping values.
8387c478bd9Sstevel@tonic-gate 			 */
8397c478bd9Sstevel@tonic-gate 			for (i=0; mapping_values[i]; i++) {
8407c478bd9Sstevel@tonic-gate 			    typep = mapping_values[i];
8417c478bd9Sstevel@tonic-gate 			    argp = strchr(typep, ':');
8427c478bd9Sstevel@tonic-gate 			    if (argp) {
8437c478bd9Sstevel@tonic-gate 				*argp = '\0';
8447c478bd9Sstevel@tonic-gate 				argp++;
8457c478bd9Sstevel@tonic-gate 			    }
8467c478bd9Sstevel@tonic-gate #ifdef ANAME_DB
8477c478bd9Sstevel@tonic-gate 			    if (!strcmp(typep, "DB") && argp) {
8487c478bd9Sstevel@tonic-gate 				kret = db_an_to_ln(context,
8497c478bd9Sstevel@tonic-gate 						   argp,
8507c478bd9Sstevel@tonic-gate 						   aname,
8517c478bd9Sstevel@tonic-gate 						   lnsize,
8527c478bd9Sstevel@tonic-gate 						   lname);
8537c478bd9Sstevel@tonic-gate 				if (kret != KRB5_LNAME_NOTRANS)
8547c478bd9Sstevel@tonic-gate 				    break;
8557c478bd9Sstevel@tonic-gate 			    }
8567c478bd9Sstevel@tonic-gate 			    else
8577c478bd9Sstevel@tonic-gate #endif
8587c478bd9Sstevel@tonic-gate #ifdef	AN_TO_LN_RULES
8597c478bd9Sstevel@tonic-gate 			    if (!strcmp(typep, "RULE") && argp) {
8607c478bd9Sstevel@tonic-gate 				kret = rule_an_to_ln(context,
8617c478bd9Sstevel@tonic-gate 						     argp,
8627c478bd9Sstevel@tonic-gate 						     aname,
8637c478bd9Sstevel@tonic-gate 						     lnsize,
8647c478bd9Sstevel@tonic-gate 						     lname);
8657c478bd9Sstevel@tonic-gate 				if (kret != KRB5_LNAME_NOTRANS)
8667c478bd9Sstevel@tonic-gate 				    break;
8677c478bd9Sstevel@tonic-gate 			    }
8687c478bd9Sstevel@tonic-gate 			    else
8697c478bd9Sstevel@tonic-gate #endif	/* AN_TO_LN_RULES */
8707c478bd9Sstevel@tonic-gate 			    if (!strcmp(typep, "DEFAULT") && !argp) {
8717c478bd9Sstevel@tonic-gate 				kret = default_an_to_ln(context,
8727c478bd9Sstevel@tonic-gate 							aname,
8737c478bd9Sstevel@tonic-gate 							lnsize,
8747c478bd9Sstevel@tonic-gate 							lname);
8757c478bd9Sstevel@tonic-gate 				if (kret != KRB5_LNAME_NOTRANS)
8767c478bd9Sstevel@tonic-gate 				    break;
8777c478bd9Sstevel@tonic-gate 			    }
8787c478bd9Sstevel@tonic-gate 			    else {
8797c478bd9Sstevel@tonic-gate 				kret = KRB5_CONFIG_BADFORMAT;
8807c478bd9Sstevel@tonic-gate 				break;
8817c478bd9Sstevel@tonic-gate 			    }
8827c478bd9Sstevel@tonic-gate 			}
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 			/* We're done, clean up the droppings. */
8857c478bd9Sstevel@tonic-gate 			profile_free_list(mapping_values);
8867c478bd9Sstevel@tonic-gate 		    }
8877c478bd9Sstevel@tonic-gate 		    else {
8887c478bd9Sstevel@tonic-gate 			/*
8897c478bd9Sstevel@tonic-gate 			 * No profile relation found, try default mapping.
8907c478bd9Sstevel@tonic-gate 			 */
8917c478bd9Sstevel@tonic-gate 			kret = default_an_to_ln(context,
8927c478bd9Sstevel@tonic-gate 						aname,
8937c478bd9Sstevel@tonic-gate 						lnsize,
8947c478bd9Sstevel@tonic-gate 						lname);
8957c478bd9Sstevel@tonic-gate 		    }
8967c478bd9Sstevel@tonic-gate 		}
8977c478bd9Sstevel@tonic-gate 		free(mname);
8987c478bd9Sstevel@tonic-gate 	    }
8997c478bd9Sstevel@tonic-gate 	    else
9007c478bd9Sstevel@tonic-gate 		kret = ENOMEM;
9017c478bd9Sstevel@tonic-gate 	    krb5_xfree(pname);
9027c478bd9Sstevel@tonic-gate 	}
9037c478bd9Sstevel@tonic-gate 	krb5_xfree(realm);
9047c478bd9Sstevel@tonic-gate     }
9057c478bd9Sstevel@tonic-gate     return(kret);
9067c478bd9Sstevel@tonic-gate }
907*159d09a2SMark Phalan 
908