1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*7c478bd9Sstevel@tonic-gate 
8*7c478bd9Sstevel@tonic-gate /*
9*7c478bd9Sstevel@tonic-gate  * lib/krb5/os/an_to_ln.c
10*7c478bd9Sstevel@tonic-gate  *
11*7c478bd9Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
12*7c478bd9Sstevel@tonic-gate  * All Rights Reserved.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
15*7c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
16*7c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
17*7c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
18*7c478bd9Sstevel@tonic-gate  *
19*7c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
20*7c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
21*7c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
22*7c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
23*7c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
24*7c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
25*7c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
26*7c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
27*7c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
28*7c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
29*7c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
30*7c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
31*7c478bd9Sstevel@tonic-gate  * or implied warranty.
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  *
34*7c478bd9Sstevel@tonic-gate  * krb5_aname_to_localname()
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate /*
39*7c478bd9Sstevel@tonic-gate  * We're only to AN_TO_LN rules at this point, and not doing the
40*7c478bd9Sstevel@tonic-gate  * database lookup  (moved from configure script)
41*7c478bd9Sstevel@tonic-gate  */
42*7c478bd9Sstevel@tonic-gate #ifndef AN_TO_LN_RULES
43*7c478bd9Sstevel@tonic-gate #define AN_TO_LN_RULES
44*7c478bd9Sstevel@tonic-gate #endif
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #include <k5-int.h>
47*7c478bd9Sstevel@tonic-gate #include <ctype.h>
48*7c478bd9Sstevel@tonic-gate #if	HAVE_REGEX_H
49*7c478bd9Sstevel@tonic-gate #include <regex.h>
50*7c478bd9Sstevel@tonic-gate #endif	/* HAVE_REGEX_H */
51*7c478bd9Sstevel@tonic-gate /*
52*7c478bd9Sstevel@tonic-gate  * Use compile(3) if no regcomp present.
53*7c478bd9Sstevel@tonic-gate  */
54*7c478bd9Sstevel@tonic-gate #if	!defined(HAVE_REGCOMP) && defined(HAVE_REGEXPR_H) && defined(HAVE_COMPILE)
55*7c478bd9Sstevel@tonic-gate #define	RE_BUF_SIZE	1024
56*7c478bd9Sstevel@tonic-gate #include <regexpr.h>
57*7c478bd9Sstevel@tonic-gate #endif	/* !HAVE_REGCOMP && HAVE_REGEXP_H && HAVE_COMPILE */
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #define	MAX_FORMAT_BUFFER	1024
60*7c478bd9Sstevel@tonic-gate #ifndef	min
61*7c478bd9Sstevel@tonic-gate #define	min(a,b)	((a>b) ? b : a)
62*7c478bd9Sstevel@tonic-gate #endif	/* min */
63*7c478bd9Sstevel@tonic-gate #ifdef ANAME_DB
64*7c478bd9Sstevel@tonic-gate /*
65*7c478bd9Sstevel@tonic-gate  * Use standard DBM code.
66*7c478bd9Sstevel@tonic-gate  */
67*7c478bd9Sstevel@tonic-gate #define	KDBM_OPEN(db, fl, mo)	dbm_open(db, fl, mo)
68*7c478bd9Sstevel@tonic-gate #define	KDBM_CLOSE(db)		dbm_close(db)
69*7c478bd9Sstevel@tonic-gate #define	KDBM_FETCH(db, key)	dbm_fetch(db, key)
70*7c478bd9Sstevel@tonic-gate #else /*ANAME_DB*/
71*7c478bd9Sstevel@tonic-gate extern DBM	*db_dbm_open KRB5_PROTOTYPE((char *, int, int));
72*7c478bd9Sstevel@tonic-gate extern void	db_dbm_close KRB5_PROTOTYPE((DBM *));
73*7c478bd9Sstevel@tonic-gate extern datum	db_dbm_fetch KRB5_PROTOTYPE((DBM *, datum));
74*7c478bd9Sstevel@tonic-gate #define KDBM_OPEN(db, fl, mo)	db_dbm_open(db, fl, mo)
75*7c478bd9Sstevel@tonic-gate #define KDBM_CLOSE(db)		db_dbm_close(db)
76*7c478bd9Sstevel@tonic-gate #define KDBM_FETCH(db, key)	db_dbm_fetch(db, key)
77*7c478bd9Sstevel@tonic-gate #endif /*ANAME_DB*/
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate /*
80*7c478bd9Sstevel@tonic-gate  * Find the portion of the flattened principal name that we use for mapping.
81*7c478bd9Sstevel@tonic-gate  */
82*7c478bd9Sstevel@tonic-gate static char *
83*7c478bd9Sstevel@tonic-gate aname_full_to_mapping_name(char *fprincname)
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate     char	*atp;
86*7c478bd9Sstevel@tonic-gate     size_t	mlen;
87*7c478bd9Sstevel@tonic-gate     char	*mname;
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate     mname = (char *) NULL;
90*7c478bd9Sstevel@tonic-gate     if (fprincname) {
91*7c478bd9Sstevel@tonic-gate 	atp = strrchr(fprincname, '@');
92*7c478bd9Sstevel@tonic-gate 	if (!atp)
93*7c478bd9Sstevel@tonic-gate 	    atp = &fprincname[strlen(fprincname)];
94*7c478bd9Sstevel@tonic-gate 	mlen = (size_t) (atp - fprincname);
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	if ((mname = (char *) malloc(mlen+1))) {
97*7c478bd9Sstevel@tonic-gate 	    strncpy(mname, fprincname, mlen);
98*7c478bd9Sstevel@tonic-gate 	    mname[mlen] = '\0';
99*7c478bd9Sstevel@tonic-gate 	}
100*7c478bd9Sstevel@tonic-gate     }
101*7c478bd9Sstevel@tonic-gate     return(mname);
102*7c478bd9Sstevel@tonic-gate }
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate #ifdef ANAME_DB
105*7c478bd9Sstevel@tonic-gate /*
106*7c478bd9Sstevel@tonic-gate  * Implementation:  This version uses a DBM database, indexed by aname,
107*7c478bd9Sstevel@tonic-gate  * to generate a lname.
108*7c478bd9Sstevel@tonic-gate  *
109*7c478bd9Sstevel@tonic-gate  * The entries in the database are normal C strings, and include the trailing
110*7c478bd9Sstevel@tonic-gate  * null in the DBM datum.size.
111*7c478bd9Sstevel@tonic-gate  */
112*7c478bd9Sstevel@tonic-gate static krb5_error_code
113*7c478bd9Sstevel@tonic-gate db_an_to_ln(context, dbname, aname, lnsize, lname)
114*7c478bd9Sstevel@tonic-gate     krb5_context context;
115*7c478bd9Sstevel@tonic-gate     char *dbname;
116*7c478bd9Sstevel@tonic-gate     krb5_const_principal aname;
117*7c478bd9Sstevel@tonic-gate     const int lnsize;
118*7c478bd9Sstevel@tonic-gate     char *lname;
119*7c478bd9Sstevel@tonic-gate {
120*7c478bd9Sstevel@tonic-gate #if	(!defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh))
121*7c478bd9Sstevel@tonic-gate     DBM *db;
122*7c478bd9Sstevel@tonic-gate     krb5_error_code retval;
123*7c478bd9Sstevel@tonic-gate     datum key, contents;
124*7c478bd9Sstevel@tonic-gate     char *princ_name;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate     if ((retval = krb5_unparse_name(context, aname, &princ_name)))
127*7c478bd9Sstevel@tonic-gate 	return(retval);
128*7c478bd9Sstevel@tonic-gate     key.dptr = princ_name;
129*7c478bd9Sstevel@tonic-gate     key.dsize = strlen(princ_name)+1;	/* need to store the NULL for
130*7c478bd9Sstevel@tonic-gate 					   decoding */
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate     db = KDBM_OPEN(dbname, O_RDONLY, 0600);
133*7c478bd9Sstevel@tonic-gate     if (!db) {
134*7c478bd9Sstevel@tonic-gate 	krb5_xfree(princ_name);
135*7c478bd9Sstevel@tonic-gate 	return KRB5_LNAME_CANTOPEN;
136*7c478bd9Sstevel@tonic-gate     }
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate     contents = KDBM_FETCH(db, key);
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate     krb5_xfree(princ_name);
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate     if (contents.dptr == NULL) {
143*7c478bd9Sstevel@tonic-gate 	retval = KRB5_LNAME_NOTRANS;
144*7c478bd9Sstevel@tonic-gate     } else {
145*7c478bd9Sstevel@tonic-gate 	strncpy(lname, contents.dptr, lnsize);
146*7c478bd9Sstevel@tonic-gate 	if (lnsize < contents.dsize)
147*7c478bd9Sstevel@tonic-gate 	    retval = KRB5_CONFIG_NOTENUFSPACE;
148*7c478bd9Sstevel@tonic-gate 	else if (lname[contents.dsize-1] != '\0')
149*7c478bd9Sstevel@tonic-gate 	    retval = KRB5_LNAME_BADFORMAT;
150*7c478bd9Sstevel@tonic-gate 	else
151*7c478bd9Sstevel@tonic-gate 	    retval = 0;
152*7c478bd9Sstevel@tonic-gate     }
153*7c478bd9Sstevel@tonic-gate     /* can't close until we copy the contents. */
154*7c478bd9Sstevel@tonic-gate     (void) KDBM_CLOSE(db);
155*7c478bd9Sstevel@tonic-gate     return retval;
156*7c478bd9Sstevel@tonic-gate #else	/* !_MSDOS && !_WIN32 && !MACINTOSH */
157*7c478bd9Sstevel@tonic-gate     /*
158*7c478bd9Sstevel@tonic-gate      * If we don't have support for a database mechanism, then we can't
159*7c478bd9Sstevel@tonic-gate      * translate this now, can we?
160*7c478bd9Sstevel@tonic-gate      */
161*7c478bd9Sstevel@tonic-gate     return KRB5_LNAME_NOTRANS;
162*7c478bd9Sstevel@tonic-gate #endif	/* !_MSDOS && !_WIN32 && !MACINTOSH */
163*7c478bd9Sstevel@tonic-gate }
164*7c478bd9Sstevel@tonic-gate #endif /*ANAME_DB*/
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate #ifdef	AN_TO_LN_RULES
167*7c478bd9Sstevel@tonic-gate /*
168*7c478bd9Sstevel@tonic-gate  * Format and transform a principal name to a local name.  This is particularly
169*7c478bd9Sstevel@tonic-gate  * useful when Kerberos principals and local user names are formatted to
170*7c478bd9Sstevel@tonic-gate  * some particular convention.
171*7c478bd9Sstevel@tonic-gate  *
172*7c478bd9Sstevel@tonic-gate  * There are three parts to each rule:
173*7c478bd9Sstevel@tonic-gate  * First part - formulate the string to perform operations on:  If not present
174*7c478bd9Sstevel@tonic-gate  * then the string defaults to the fully flattened principal minus the realm
175*7c478bd9Sstevel@tonic-gate  * name.  Otherwise the syntax is as follows:
176*7c478bd9Sstevel@tonic-gate  *	"[" <ncomps> ":" <format> "]"
177*7c478bd9Sstevel@tonic-gate  *		Where:
178*7c478bd9Sstevel@tonic-gate  *			<ncomps> is the number of expected components for this
179*7c478bd9Sstevel@tonic-gate  *			rule.  If the particular principal does not have this
180*7c478bd9Sstevel@tonic-gate  *			many components, then this rule does not apply.
181*7c478bd9Sstevel@tonic-gate  *
182*7c478bd9Sstevel@tonic-gate  *			<format> is a string of <component> or verbatim
183*7c478bd9Sstevel@tonic-gate  *			characters to be inserted.
184*7c478bd9Sstevel@tonic-gate  *
185*7c478bd9Sstevel@tonic-gate  *			<component> is of the form "$"<number> to select the
186*7c478bd9Sstevel@tonic-gate  *			<number>th component.  <number> begins from 1.
187*7c478bd9Sstevel@tonic-gate  *
188*7c478bd9Sstevel@tonic-gate  * Second part - select rule validity:  If not present, then this rule may
189*7c478bd9Sstevel@tonic-gate  * apply to all selections.  Otherwise the syntax is as follows:
190*7c478bd9Sstevel@tonic-gate  *	"(" <regexp> ")"
191*7c478bd9Sstevel@tonic-gate  *		Where:	<regexp> is a selector regular expression.  If this
192*7c478bd9Sstevel@tonic-gate  *			regular expression matches the whole pattern generated
193*7c478bd9Sstevel@tonic-gate  *			from the first part, then this rule still applies.
194*7c478bd9Sstevel@tonic-gate  *
195*7c478bd9Sstevel@tonic-gate  * Last part - Transform rule:  If not present, then the selection string
196*7c478bd9Sstevel@tonic-gate  * is passed verbatim and is matched.  Otherwise, the syntax is as follows:
197*7c478bd9Sstevel@tonic-gate  *	<rule> ...
198*7c478bd9Sstevel@tonic-gate  *		Where:	<rule> is of the form:
199*7c478bd9Sstevel@tonic-gate  *			"s/" <regexp> "/" <text> "/" ["g"]
200*7c478bd9Sstevel@tonic-gate  *
201*7c478bd9Sstevel@tonic-gate  * In order to be able to select rule validity, the native system must support
202*7c478bd9Sstevel@tonic-gate  * one of compile(3), re_comp(3) or regcomp(3).  In order to be able to
203*7c478bd9Sstevel@tonic-gate  * transform (e.g. substitute), the native system must support regcomp(3) or
204*7c478bd9Sstevel@tonic-gate  * compile(3).
205*7c478bd9Sstevel@tonic-gate  */
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate /*
208*7c478bd9Sstevel@tonic-gate  * aname_do_match() 	- Does our name match the parenthesized regular
209*7c478bd9Sstevel@tonic-gate  *			  expression?
210*7c478bd9Sstevel@tonic-gate  *
211*7c478bd9Sstevel@tonic-gate  * Chew up the match portion of the regular expression and update *contextp.
212*7c478bd9Sstevel@tonic-gate  * If no re_comp() or regcomp(), then always return a match.
213*7c478bd9Sstevel@tonic-gate  */
214*7c478bd9Sstevel@tonic-gate static krb5_error_code
215*7c478bd9Sstevel@tonic-gate aname_do_match(char *string, char **contextp)
216*7c478bd9Sstevel@tonic-gate {
217*7c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
218*7c478bd9Sstevel@tonic-gate     char		*regexp, *startp, *endp = 0;
219*7c478bd9Sstevel@tonic-gate     size_t		regexlen;
220*7c478bd9Sstevel@tonic-gate #if	HAVE_REGCOMP
221*7c478bd9Sstevel@tonic-gate     regex_t		match_exp;
222*7c478bd9Sstevel@tonic-gate     regmatch_t		match_match;
223*7c478bd9Sstevel@tonic-gate #elif	HAVE_REGEXPR_H
224*7c478bd9Sstevel@tonic-gate     char		regexp_buffer[RE_BUF_SIZE];
225*7c478bd9Sstevel@tonic-gate #endif	/* HAVE_REGEXP_H */
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate     kret = 0;
228*7c478bd9Sstevel@tonic-gate     /*
229*7c478bd9Sstevel@tonic-gate      * Is this a match expression?
230*7c478bd9Sstevel@tonic-gate      */
231*7c478bd9Sstevel@tonic-gate     if (**contextp == '(') {
232*7c478bd9Sstevel@tonic-gate 	kret = KRB5_CONFIG_BADFORMAT;
233*7c478bd9Sstevel@tonic-gate 	startp = (*contextp) + 1;
234*7c478bd9Sstevel@tonic-gate 	endp = strchr(startp, ')');
235*7c478bd9Sstevel@tonic-gate 	/* Find the end of the match expression. */
236*7c478bd9Sstevel@tonic-gate 	if (endp) {
237*7c478bd9Sstevel@tonic-gate 	    regexlen = (size_t) (endp - startp);
238*7c478bd9Sstevel@tonic-gate 	    regexp = (char *) malloc((size_t) regexlen+1);
239*7c478bd9Sstevel@tonic-gate 	    kret = ENOMEM;
240*7c478bd9Sstevel@tonic-gate 	    if (regexp) {
241*7c478bd9Sstevel@tonic-gate 		strncpy(regexp, startp, regexlen);
242*7c478bd9Sstevel@tonic-gate 		regexp[regexlen] = '\0';
243*7c478bd9Sstevel@tonic-gate 		kret = KRB5_LNAME_NOTRANS;
244*7c478bd9Sstevel@tonic-gate 		/*
245*7c478bd9Sstevel@tonic-gate 		 * Perform the match.
246*7c478bd9Sstevel@tonic-gate 		 */
247*7c478bd9Sstevel@tonic-gate #if	HAVE_REGCOMP
248*7c478bd9Sstevel@tonic-gate 		if (!regcomp(&match_exp, regexp, REG_EXTENDED) &&
249*7c478bd9Sstevel@tonic-gate 		    !regexec(&match_exp, string, 1, &match_match, 0)) {
250*7c478bd9Sstevel@tonic-gate 		    if ((match_match.rm_so == 0) &&
251*7c478bd9Sstevel@tonic-gate 			(match_match.rm_eo == strlen(string)))
252*7c478bd9Sstevel@tonic-gate 			kret = 0;
253*7c478bd9Sstevel@tonic-gate 		}
254*7c478bd9Sstevel@tonic-gate 		regfree(&match_exp);
255*7c478bd9Sstevel@tonic-gate #elif	HAVE_REGEXPR_H
256*7c478bd9Sstevel@tonic-gate 		compile(regexp,
257*7c478bd9Sstevel@tonic-gate 			regexp_buffer,
258*7c478bd9Sstevel@tonic-gate 			&regexp_buffer[RE_BUF_SIZE],
259*7c478bd9Sstevel@tonic-gate 			'\0');
260*7c478bd9Sstevel@tonic-gate 		if (step(string, regexp_buffer)) {
261*7c478bd9Sstevel@tonic-gate 		    if ((loc1 == string) &&
262*7c478bd9Sstevel@tonic-gate 			(loc2 == &string[strlen(string)]))
263*7c478bd9Sstevel@tonic-gate 			kret = 0;
264*7c478bd9Sstevel@tonic-gate 		}
265*7c478bd9Sstevel@tonic-gate #elif	HAVE_RE_COMP
266*7c478bd9Sstevel@tonic-gate 		if (!re_comp(regexp) && re_exec(string))
267*7c478bd9Sstevel@tonic-gate 		    kret = 0;
268*7c478bd9Sstevel@tonic-gate #else	/* HAVE_RE_COMP */
269*7c478bd9Sstevel@tonic-gate 		kret = 0;
270*7c478bd9Sstevel@tonic-gate #endif	/* HAVE_RE_COMP */
271*7c478bd9Sstevel@tonic-gate 		free(regexp);
272*7c478bd9Sstevel@tonic-gate 	    }
273*7c478bd9Sstevel@tonic-gate 	    endp++;
274*7c478bd9Sstevel@tonic-gate 	}
275*7c478bd9Sstevel@tonic-gate 	else
276*7c478bd9Sstevel@tonic-gate 	    endp = startp;
277*7c478bd9Sstevel@tonic-gate     }
278*7c478bd9Sstevel@tonic-gate     *contextp = endp;
279*7c478bd9Sstevel@tonic-gate     return(kret);
280*7c478bd9Sstevel@tonic-gate }
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate /*
283*7c478bd9Sstevel@tonic-gate  * do_replacement()	- Replace the regular expression with the specified
284*7c478bd9Sstevel@tonic-gate  * 			  replacement.
285*7c478bd9Sstevel@tonic-gate  *
286*7c478bd9Sstevel@tonic-gate  * If "doall" is set, it's a global replacement, otherwise, just a oneshot
287*7c478bd9Sstevel@tonic-gate  * deal.
288*7c478bd9Sstevel@tonic-gate  * If no regcomp() then just return the input string verbatim in the output
289*7c478bd9Sstevel@tonic-gate  * string.
290*7c478bd9Sstevel@tonic-gate  */
291*7c478bd9Sstevel@tonic-gate #define use_bytes(x) \
292*7c478bd9Sstevel@tonic-gate 	out_used += (x); \
293*7c478bd9Sstevel@tonic-gate 	if (out_used > MAX_FORMAT_BUFFER) goto mem_err
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate static int
296*7c478bd9Sstevel@tonic-gate do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
297*7c478bd9Sstevel@tonic-gate {
298*7c478bd9Sstevel@tonic-gate     size_t out_used = 0;
299*7c478bd9Sstevel@tonic-gate #if	HAVE_REGCOMP
300*7c478bd9Sstevel@tonic-gate     regex_t	match_exp;
301*7c478bd9Sstevel@tonic-gate     regmatch_t	match_match;
302*7c478bd9Sstevel@tonic-gate     int		matched;
303*7c478bd9Sstevel@tonic-gate     char	*cp;
304*7c478bd9Sstevel@tonic-gate     char	*op;
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate     if (!regcomp(&match_exp, regexp, REG_EXTENDED)) {
307*7c478bd9Sstevel@tonic-gate 	cp = in;
308*7c478bd9Sstevel@tonic-gate 	op = out;
309*7c478bd9Sstevel@tonic-gate 	matched = 0;
310*7c478bd9Sstevel@tonic-gate 	do {
311*7c478bd9Sstevel@tonic-gate 	    if (!regexec(&match_exp, cp, 1, &match_match, 0)) {
312*7c478bd9Sstevel@tonic-gate 		if (match_match.rm_so) {
313*7c478bd9Sstevel@tonic-gate 		    use_bytes(match_match.rm_so);
314*7c478bd9Sstevel@tonic-gate 		    strncpy(op, cp, match_match.rm_so);
315*7c478bd9Sstevel@tonic-gate 		    op += match_match.rm_so;
316*7c478bd9Sstevel@tonic-gate 		}
317*7c478bd9Sstevel@tonic-gate 		use_bytes(strlen(repl));
318*7c478bd9Sstevel@tonic-gate 		strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
319*7c478bd9Sstevel@tonic-gate 		op += strlen(op);
320*7c478bd9Sstevel@tonic-gate 		cp += match_match.rm_eo;
321*7c478bd9Sstevel@tonic-gate 		if (!doall) {
322*7c478bd9Sstevel@tonic-gate 		    use_bytes(strlen(cp));
323*7c478bd9Sstevel@tonic-gate 		    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
324*7c478bd9Sstevel@tonic-gate 		}
325*7c478bd9Sstevel@tonic-gate 		matched = 1;
326*7c478bd9Sstevel@tonic-gate 	    }
327*7c478bd9Sstevel@tonic-gate 	    else {
328*7c478bd9Sstevel@tonic-gate 		use_bytes(strlen(cp));
329*7c478bd9Sstevel@tonic-gate 		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
330*7c478bd9Sstevel@tonic-gate 		matched = 0;
331*7c478bd9Sstevel@tonic-gate 	    }
332*7c478bd9Sstevel@tonic-gate 	} while (doall && matched);
333*7c478bd9Sstevel@tonic-gate 	regfree(&match_exp);
334*7c478bd9Sstevel@tonic-gate     }
335*7c478bd9Sstevel@tonic-gate #elif	HAVE_REGEXPR_H
336*7c478bd9Sstevel@tonic-gate     int		matched;
337*7c478bd9Sstevel@tonic-gate     char	*cp;
338*7c478bd9Sstevel@tonic-gate     char	*op;
339*7c478bd9Sstevel@tonic-gate     char	regexp_buffer[RE_BUF_SIZE];
340*7c478bd9Sstevel@tonic-gate     size_t	sdispl, edispl;
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate     compile(regexp,
343*7c478bd9Sstevel@tonic-gate 	    regexp_buffer,
344*7c478bd9Sstevel@tonic-gate 	    &regexp_buffer[RE_BUF_SIZE],
345*7c478bd9Sstevel@tonic-gate 	    '\0');
346*7c478bd9Sstevel@tonic-gate     cp = in;
347*7c478bd9Sstevel@tonic-gate     op = out;
348*7c478bd9Sstevel@tonic-gate     matched = 0;
349*7c478bd9Sstevel@tonic-gate     do {
350*7c478bd9Sstevel@tonic-gate 	if (step(cp, regexp_buffer)) {
351*7c478bd9Sstevel@tonic-gate 	    sdispl = (size_t) (loc1 - cp);
352*7c478bd9Sstevel@tonic-gate 	    edispl = (size_t) (loc2 - cp);
353*7c478bd9Sstevel@tonic-gate 	    if (sdispl) {
354*7c478bd9Sstevel@tonic-gate 		use_bytes(sdispl);
355*7c478bd9Sstevel@tonic-gate 		strncpy(op, cp, sdispl);
356*7c478bd9Sstevel@tonic-gate 		op += sdispl;
357*7c478bd9Sstevel@tonic-gate 	    }
358*7c478bd9Sstevel@tonic-gate 	    use_bytes(strlen(repl));
359*7c478bd9Sstevel@tonic-gate 	    strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
360*7c478bd9Sstevel@tonic-gate 	    op += strlen(repl);
361*7c478bd9Sstevel@tonic-gate 	    cp += edispl;
362*7c478bd9Sstevel@tonic-gate 	    if (!doall) {
363*7c478bd9Sstevel@tonic-gate 		use_bytes(strlen(cp));
364*7c478bd9Sstevel@tonic-gate 		strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
365*7c478bd9Sstevel@tonic-gate 	    }
366*7c478bd9Sstevel@tonic-gate 	    matched = 1;
367*7c478bd9Sstevel@tonic-gate 	}
368*7c478bd9Sstevel@tonic-gate 	else {
369*7c478bd9Sstevel@tonic-gate 	    use_bytes(strlen(cp));
370*7c478bd9Sstevel@tonic-gate 	    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
371*7c478bd9Sstevel@tonic-gate 	    matched = 0;
372*7c478bd9Sstevel@tonic-gate 	}
373*7c478bd9Sstevel@tonic-gate     } while (doall && matched);
374*7c478bd9Sstevel@tonic-gate #else	/* HAVE_REGEXP_H */
375*7c478bd9Sstevel@tonic-gate     memcpy(out, in, MAX_FORMAT_BUFFER);
376*7c478bd9Sstevel@tonic-gate #endif	/* HAVE_REGCOMP */
377*7c478bd9Sstevel@tonic-gate     return 1;
378*7c478bd9Sstevel@tonic-gate  mem_err:
379*7c478bd9Sstevel@tonic-gate #ifdef HAVE_REGCMP
380*7c478bd9Sstevel@tonic-gate     	regfree(&match_exp);
381*7c478bd9Sstevel@tonic-gate #endif
382*7c478bd9Sstevel@tonic-gate 	return 0;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate }
385*7c478bd9Sstevel@tonic-gate #undef use_bytes
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate /*
388*7c478bd9Sstevel@tonic-gate  * aname_replacer()	- Perform the specified substitutions on the input
389*7c478bd9Sstevel@tonic-gate  *			  string and return the result.
390*7c478bd9Sstevel@tonic-gate  *
391*7c478bd9Sstevel@tonic-gate  * This routine enforces the "s/<pattern>/<replacement>/[g]" syntax.
392*7c478bd9Sstevel@tonic-gate  */
393*7c478bd9Sstevel@tonic-gate static krb5_error_code
394*7c478bd9Sstevel@tonic-gate aname_replacer(char *string, char **contextp, char **result)
395*7c478bd9Sstevel@tonic-gate {
396*7c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
397*7c478bd9Sstevel@tonic-gate     char		*in;
398*7c478bd9Sstevel@tonic-gate     char		*out;
399*7c478bd9Sstevel@tonic-gate     char		*cp, *ep, *tp;
400*7c478bd9Sstevel@tonic-gate     char		*rule, *repl;
401*7c478bd9Sstevel@tonic-gate     size_t		rule_size, repl_size;
402*7c478bd9Sstevel@tonic-gate     int			doglobal;
403*7c478bd9Sstevel@tonic-gate     char		sep;
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate     kret = ENOMEM;
406*7c478bd9Sstevel@tonic-gate     *result = (char *) NULL;
407*7c478bd9Sstevel@tonic-gate     /* Allocate the formatting buffers */
408*7c478bd9Sstevel@tonic-gate     if (((in = (char *) malloc(MAX_FORMAT_BUFFER)) != NULL) &&
409*7c478bd9Sstevel@tonic-gate 	((out = (char *) malloc(MAX_FORMAT_BUFFER)) != NULL)) {
410*7c478bd9Sstevel@tonic-gate 	/*
411*7c478bd9Sstevel@tonic-gate 	 * Prime the buffers.  Copy input string to "out" to simulate it
412*7c478bd9Sstevel@tonic-gate 	 * being the result of an initial iteration.
413*7c478bd9Sstevel@tonic-gate 	 */
414*7c478bd9Sstevel@tonic-gate 	strncpy(out, string, MAX_FORMAT_BUFFER - 1);
415*7c478bd9Sstevel@tonic-gate 	out[MAX_FORMAT_BUFFER - 1] = '\0';
416*7c478bd9Sstevel@tonic-gate 	in[0] = '\0';
417*7c478bd9Sstevel@tonic-gate 	kret = 0;
418*7c478bd9Sstevel@tonic-gate 	/*
419*7c478bd9Sstevel@tonic-gate 	 * Pound through the expression until we're done.
420*7c478bd9Sstevel@tonic-gate 	 */
421*7c478bd9Sstevel@tonic-gate 	for (cp = *contextp; *cp; ) {
422*7c478bd9Sstevel@tonic-gate 	    /* Skip leading whitespace */
423*7c478bd9Sstevel@tonic-gate 	    while (isspace(*cp))
424*7c478bd9Sstevel@tonic-gate 		cp++;
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 	    /*
427*7c478bd9Sstevel@tonic-gate 	     * Find our separators.  First two characters must be "s<sep>"
428*7c478bd9Sstevel@tonic-gate 	     * We must also find another "<sep>" followed by another * "<sep>".
429*7c478bd9Sstevel@tonic-gate 	     */
430*7c478bd9Sstevel@tonic-gate 	    if (cp[0] != 's') {
431*7c478bd9Sstevel@tonic-gate 		/* Bad syntax */
432*7c478bd9Sstevel@tonic-gate 		kret = KRB5_CONFIG_BADFORMAT;
433*7c478bd9Sstevel@tonic-gate 		break;
434*7c478bd9Sstevel@tonic-gate 	    }
435*7c478bd9Sstevel@tonic-gate 	    if (strspn(cp + 1, ",/;|!%") < 1) {
436*7c478bd9Sstevel@tonic-gate 		/* Bad syntax */
437*7c478bd9Sstevel@tonic-gate 		kret = KRB5_CONFIG_BADFORMAT;
438*7c478bd9Sstevel@tonic-gate 		break;
439*7c478bd9Sstevel@tonic-gate 	    }
440*7c478bd9Sstevel@tonic-gate 	    sep = cp[1];
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	    if (((ep = strchr(&cp[2], sep)) != NULL) &&
443*7c478bd9Sstevel@tonic-gate 		((tp = strchr(&ep[1], sep)) != NULL)) {
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 		/* Figure out sizes of strings and allocate them */
446*7c478bd9Sstevel@tonic-gate 		rule_size = (size_t) (ep - &cp[2]);
447*7c478bd9Sstevel@tonic-gate 		repl_size = (size_t) (tp - &ep[1]);
448*7c478bd9Sstevel@tonic-gate 		if (((rule = (char *) malloc(rule_size+1)) != NULL) &&
449*7c478bd9Sstevel@tonic-gate 		    ((repl = (char *) malloc(repl_size+1)) != NULL)) {
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 		    /* Copy the strings */
452*7c478bd9Sstevel@tonic-gate 		    strncpy(rule, &cp[2], rule_size);
453*7c478bd9Sstevel@tonic-gate 		    strncpy(repl, &ep[1], repl_size);
454*7c478bd9Sstevel@tonic-gate 		    rule[rule_size] = repl[repl_size] = '\0';
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 		    /* Check for trailing "g" */
457*7c478bd9Sstevel@tonic-gate 		    doglobal = (tp[1] == 'g') ? 1 : 0;
458*7c478bd9Sstevel@tonic-gate 		    if (doglobal)
459*7c478bd9Sstevel@tonic-gate 			tp++;
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 		    /* Swap previous in and out buffers */
462*7c478bd9Sstevel@tonic-gate 		    ep = in;
463*7c478bd9Sstevel@tonic-gate 		    in = out;
464*7c478bd9Sstevel@tonic-gate 		    out = ep;
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 		    /* Do the replacemenbt */
467*7c478bd9Sstevel@tonic-gate 		    memset(out, '\0', MAX_FORMAT_BUFFER);
468*7c478bd9Sstevel@tonic-gate 		    if (!do_replacement(rule, repl, doglobal, in, out)) {
469*7c478bd9Sstevel@tonic-gate 			free(rule);
470*7c478bd9Sstevel@tonic-gate 		    free(repl);
471*7c478bd9Sstevel@tonic-gate 			kret = KRB5_LNAME_NOTRANS;
472*7c478bd9Sstevel@tonic-gate 			break;
473*7c478bd9Sstevel@tonic-gate 		    }
474*7c478bd9Sstevel@tonic-gate 		    free(rule);
475*7c478bd9Sstevel@tonic-gate 		    free(repl);
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 		    /* If we have no output buffer left, this can't be good */
478*7c478bd9Sstevel@tonic-gate 		    if (strlen(out) == 0) {
479*7c478bd9Sstevel@tonic-gate 			kret = KRB5_LNAME_NOTRANS;
480*7c478bd9Sstevel@tonic-gate 			break;
481*7c478bd9Sstevel@tonic-gate 		    }
482*7c478bd9Sstevel@tonic-gate 		}
483*7c478bd9Sstevel@tonic-gate 		else {
484*7c478bd9Sstevel@tonic-gate 		    /* No memory for copies */
485*7c478bd9Sstevel@tonic-gate 		    kret = ENOMEM;
486*7c478bd9Sstevel@tonic-gate 		    break;
487*7c478bd9Sstevel@tonic-gate 		}
488*7c478bd9Sstevel@tonic-gate 	    }
489*7c478bd9Sstevel@tonic-gate 	    else {
490*7c478bd9Sstevel@tonic-gate 		/* Bad syntax */
491*7c478bd9Sstevel@tonic-gate 		kret = KRB5_CONFIG_BADFORMAT;
492*7c478bd9Sstevel@tonic-gate 		break;
493*7c478bd9Sstevel@tonic-gate 	    }
494*7c478bd9Sstevel@tonic-gate 	    /* Advance past trailer */
495*7c478bd9Sstevel@tonic-gate 	    cp = &tp[1];
496*7c478bd9Sstevel@tonic-gate 	}
497*7c478bd9Sstevel@tonic-gate 	free(in);
498*7c478bd9Sstevel@tonic-gate 	if (!kret)
499*7c478bd9Sstevel@tonic-gate 	    *result = out;
500*7c478bd9Sstevel@tonic-gate 	else
501*7c478bd9Sstevel@tonic-gate 	    free(out);
502*7c478bd9Sstevel@tonic-gate     }
503*7c478bd9Sstevel@tonic-gate     return(kret);
504*7c478bd9Sstevel@tonic-gate }
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate /*
507*7c478bd9Sstevel@tonic-gate  * rule_an_to_ln()	- Handle aname to lname translations for RULE rules.
508*7c478bd9Sstevel@tonic-gate  *
509*7c478bd9Sstevel@tonic-gate  * The initial part of this routine handles the formulation of the strings from
510*7c478bd9Sstevel@tonic-gate  * the principal name.
511*7c478bd9Sstevel@tonic-gate  */
512*7c478bd9Sstevel@tonic-gate static krb5_error_code
513*7c478bd9Sstevel@tonic-gate rule_an_to_ln(krb5_context context, char *rule,
514*7c478bd9Sstevel@tonic-gate 	krb5_const_principal aname, const int lnsize, char *lname)
515*7c478bd9Sstevel@tonic-gate {
516*7c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
517*7c478bd9Sstevel@tonic-gate     char		*current;
518*7c478bd9Sstevel@tonic-gate     char		*fprincname;
519*7c478bd9Sstevel@tonic-gate     char		*selstring = 0;
520*7c478bd9Sstevel@tonic-gate     int			num_comps, compind;
521*7c478bd9Sstevel@tonic-gate     size_t selstring_used;
522*7c478bd9Sstevel@tonic-gate     char		*cout;
523*7c478bd9Sstevel@tonic-gate     krb5_const krb5_data *datap;
524*7c478bd9Sstevel@tonic-gate     char		*outstring;
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate     /*
527*7c478bd9Sstevel@tonic-gate      * First flatten the name.
528*7c478bd9Sstevel@tonic-gate      */
529*7c478bd9Sstevel@tonic-gate     current = rule;
530*7c478bd9Sstevel@tonic-gate     if (!(kret = krb5_unparse_name(context, aname, &fprincname))) {
531*7c478bd9Sstevel@tonic-gate 	/*
532*7c478bd9Sstevel@tonic-gate 	 * First part.
533*7c478bd9Sstevel@tonic-gate 	 */
534*7c478bd9Sstevel@tonic-gate 	if (*current == '[') {
535*7c478bd9Sstevel@tonic-gate 	    if (sscanf(current+1,"%d:", &num_comps) == 1) {
536*7c478bd9Sstevel@tonic-gate 		if (num_comps == aname->length) {
537*7c478bd9Sstevel@tonic-gate 		    /*
538*7c478bd9Sstevel@tonic-gate 		     * We have a match based on the number of components.
539*7c478bd9Sstevel@tonic-gate 		     */
540*7c478bd9Sstevel@tonic-gate 		    current = strchr(current, ':');
541*7c478bd9Sstevel@tonic-gate 		    selstring = (char *) malloc(MAX_FORMAT_BUFFER);
542*7c478bd9Sstevel@tonic-gate 		    selstring_used = 0;
543*7c478bd9Sstevel@tonic-gate 		    if (current && selstring) {
544*7c478bd9Sstevel@tonic-gate 			current++;
545*7c478bd9Sstevel@tonic-gate 			cout = selstring;
546*7c478bd9Sstevel@tonic-gate 			/*
547*7c478bd9Sstevel@tonic-gate 			 * Plow through the string.
548*7c478bd9Sstevel@tonic-gate 			 */
549*7c478bd9Sstevel@tonic-gate 			while ((*current != ']') &&
550*7c478bd9Sstevel@tonic-gate 			       (*current != '\0')) {
551*7c478bd9Sstevel@tonic-gate 			    /*
552*7c478bd9Sstevel@tonic-gate 			     * Expand to a component.
553*7c478bd9Sstevel@tonic-gate 			     */
554*7c478bd9Sstevel@tonic-gate 			    if (*current == '$') {
555*7c478bd9Sstevel@tonic-gate 				if ((sscanf(current+1, "%d", &compind) == 1) &&
556*7c478bd9Sstevel@tonic-gate 				    (compind <= num_comps) &&
557*7c478bd9Sstevel@tonic-gate 				    (datap = (compind > 0) ?
558*7c478bd9Sstevel@tonic-gate 					krb5_princ_component(context, aname, compind-1) :
559*7c478bd9Sstevel@tonic-gate 					krb5_princ_realm(context, aname))) {
560*7c478bd9Sstevel@tonic-gate 				    if ((datap->length < MAX_FORMAT_BUFFER)
561*7c478bd9Sstevel@tonic-gate 					&&  (selstring_used+datap->length
562*7c478bd9Sstevel@tonic-gate 					     < MAX_FORMAT_BUFFER)) {
563*7c478bd9Sstevel@tonic-gate 					selstring_used += datap->length;
564*7c478bd9Sstevel@tonic-gate 				    } else {
565*7c478bd9Sstevel@tonic-gate 					kret = KRB5_LNAME_NOTRANS;
566*7c478bd9Sstevel@tonic-gate 					goto errout;
567*7c478bd9Sstevel@tonic-gate 				    }
568*7c478bd9Sstevel@tonic-gate 				    strncpy(cout,
569*7c478bd9Sstevel@tonic-gate 					    datap->data,
570*7c478bd9Sstevel@tonic-gate 					    datap->length);
571*7c478bd9Sstevel@tonic-gate 				    cout += datap->length;
572*7c478bd9Sstevel@tonic-gate 				    *cout = '\0';
573*7c478bd9Sstevel@tonic-gate 				    current++;
574*7c478bd9Sstevel@tonic-gate 				    /* Point past number */
575*7c478bd9Sstevel@tonic-gate 				    while (isdigit(*current))
576*7c478bd9Sstevel@tonic-gate 					current++;
577*7c478bd9Sstevel@tonic-gate 				}
578*7c478bd9Sstevel@tonic-gate 				else
579*7c478bd9Sstevel@tonic-gate 				    kret = KRB5_CONFIG_BADFORMAT;
580*7c478bd9Sstevel@tonic-gate 			    }
581*7c478bd9Sstevel@tonic-gate 			    else {
582*7c478bd9Sstevel@tonic-gate 				/* Copy in verbatim. */
583*7c478bd9Sstevel@tonic-gate 				*cout = *current;
584*7c478bd9Sstevel@tonic-gate 				cout++;
585*7c478bd9Sstevel@tonic-gate 				*cout = '\0';
586*7c478bd9Sstevel@tonic-gate 				current++;
587*7c478bd9Sstevel@tonic-gate 			    }
588*7c478bd9Sstevel@tonic-gate 			}
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate 			/*
591*7c478bd9Sstevel@tonic-gate 			 * Advance past separator if appropriate.
592*7c478bd9Sstevel@tonic-gate 			 */
593*7c478bd9Sstevel@tonic-gate 			if (*current == ']')
594*7c478bd9Sstevel@tonic-gate 			    current++;
595*7c478bd9Sstevel@tonic-gate 			else
596*7c478bd9Sstevel@tonic-gate 			    kret = KRB5_CONFIG_BADFORMAT;
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 			errout: if (kret)
599*7c478bd9Sstevel@tonic-gate 			    free(selstring);
600*7c478bd9Sstevel@tonic-gate 		    }
601*7c478bd9Sstevel@tonic-gate 		}
602*7c478bd9Sstevel@tonic-gate 		else
603*7c478bd9Sstevel@tonic-gate 		    kret = KRB5_LNAME_NOTRANS;
604*7c478bd9Sstevel@tonic-gate 	    }
605*7c478bd9Sstevel@tonic-gate 	    else
606*7c478bd9Sstevel@tonic-gate 		kret = KRB5_CONFIG_BADFORMAT;
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 	else {
609*7c478bd9Sstevel@tonic-gate 	    if (!(selstring = aname_full_to_mapping_name(fprincname)))
610*7c478bd9Sstevel@tonic-gate 		kret = ENOMEM;
611*7c478bd9Sstevel@tonic-gate 	}
612*7c478bd9Sstevel@tonic-gate 	krb5_xfree(fprincname);
613*7c478bd9Sstevel@tonic-gate     }
614*7c478bd9Sstevel@tonic-gate     if (!kret) {
615*7c478bd9Sstevel@tonic-gate 	/*
616*7c478bd9Sstevel@tonic-gate 	 * Second part
617*7c478bd9Sstevel@tonic-gate 	 */
618*7c478bd9Sstevel@tonic-gate 	if (*current == '(')
619*7c478bd9Sstevel@tonic-gate 	    kret = aname_do_match(selstring, &current);
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 	/*
622*7c478bd9Sstevel@tonic-gate 	 * Third part.
623*7c478bd9Sstevel@tonic-gate 	 */
624*7c478bd9Sstevel@tonic-gate 	if (!kret) {
625*7c478bd9Sstevel@tonic-gate 	    outstring = (char *) NULL;
626*7c478bd9Sstevel@tonic-gate 	    kret = aname_replacer(selstring, &current, &outstring);
627*7c478bd9Sstevel@tonic-gate 	    if (outstring) {
628*7c478bd9Sstevel@tonic-gate 		/* Copy out the value if there's enough room */
629*7c478bd9Sstevel@tonic-gate 		if (strlen(outstring)+1 <= (size_t) lnsize)
630*7c478bd9Sstevel@tonic-gate 		    strcpy(lname, outstring);
631*7c478bd9Sstevel@tonic-gate 		else
632*7c478bd9Sstevel@tonic-gate 		    kret = KRB5_CONFIG_NOTENUFSPACE;
633*7c478bd9Sstevel@tonic-gate 		free(outstring);
634*7c478bd9Sstevel@tonic-gate 	    }
635*7c478bd9Sstevel@tonic-gate 	}
636*7c478bd9Sstevel@tonic-gate 	free(selstring);
637*7c478bd9Sstevel@tonic-gate     }
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate     return(kret);
640*7c478bd9Sstevel@tonic-gate }
641*7c478bd9Sstevel@tonic-gate #endif	/* AN_TO_LN_RULES */
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate /*
644*7c478bd9Sstevel@tonic-gate  * Solaris Kerberos
645*7c478bd9Sstevel@tonic-gate  * Return true (1) if the princ's realm matches any of the
646*7c478bd9Sstevel@tonic-gate  * 'auth_to_local_realm' relations in the default realm section.
647*7c478bd9Sstevel@tonic-gate  */
648*7c478bd9Sstevel@tonic-gate static int
649*7c478bd9Sstevel@tonic-gate an_to_ln_realm_chk(
650*7c478bd9Sstevel@tonic-gate 	krb5_context context,
651*7c478bd9Sstevel@tonic-gate 	krb5_const_principal aname,
652*7c478bd9Sstevel@tonic-gate 	char *def_realm,
653*7c478bd9Sstevel@tonic-gate 	int realm_length)
654*7c478bd9Sstevel@tonic-gate {
655*7c478bd9Sstevel@tonic-gate 	char        **values, **cpp;
656*7c478bd9Sstevel@tonic-gate 	const char  *realm_names[4];
657*7c478bd9Sstevel@tonic-gate 	krb5_error_code     retval;
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	realm_names[0] = "realms";
660*7c478bd9Sstevel@tonic-gate 	realm_names[1] = def_realm;
661*7c478bd9Sstevel@tonic-gate 	realm_names[2] = "auth_to_local_realm";
662*7c478bd9Sstevel@tonic-gate 	realm_names[3] = 0;
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate 	if (context->profile == 0)
665*7c478bd9Sstevel@tonic-gate 		return (0);
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	retval = profile_get_values(context->profile, realm_names,
668*7c478bd9Sstevel@tonic-gate 				    &values);
669*7c478bd9Sstevel@tonic-gate 	if (retval)
670*7c478bd9Sstevel@tonic-gate 		return (0);
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate 	for (cpp = values; *cpp; cpp++) {
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate 		if (((size_t) realm_length == strlen(*cpp)) &&
675*7c478bd9Sstevel@tonic-gate 		    (memcmp(*cpp, krb5_princ_realm(context, aname)->data,
676*7c478bd9Sstevel@tonic-gate 			    realm_length) == 0)) {
677*7c478bd9Sstevel@tonic-gate 
678*7c478bd9Sstevel@tonic-gate 			profile_free_list(values);
679*7c478bd9Sstevel@tonic-gate 			return (1); /* success */
680*7c478bd9Sstevel@tonic-gate 		}
681*7c478bd9Sstevel@tonic-gate 	}
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 	profile_free_list(values);
684*7c478bd9Sstevel@tonic-gate 	return (0);
685*7c478bd9Sstevel@tonic-gate }
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate /*
688*7c478bd9Sstevel@tonic-gate  * Implementation:  This version checks the realm to see if it is the local
689*7c478bd9Sstevel@tonic-gate  * realm; if so, and there is exactly one non-realm component to the name,
690*7c478bd9Sstevel@tonic-gate  * that name is returned as the lname.
691*7c478bd9Sstevel@tonic-gate  */
692*7c478bd9Sstevel@tonic-gate static krb5_error_code
693*7c478bd9Sstevel@tonic-gate default_an_to_ln(krb5_context context, krb5_const_principal aname,
694*7c478bd9Sstevel@tonic-gate 	const int lnsize, char *lname)
695*7c478bd9Sstevel@tonic-gate {
696*7c478bd9Sstevel@tonic-gate     krb5_error_code retval;
697*7c478bd9Sstevel@tonic-gate     char *def_realm;
698*7c478bd9Sstevel@tonic-gate     int realm_length;
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate     realm_length = krb5_princ_realm(context, aname)->length;
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate     if ((retval = krb5_get_default_realm(context, &def_realm))) {
704*7c478bd9Sstevel@tonic-gate 	return(retval);
705*7c478bd9Sstevel@tonic-gate     }
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate     /* compare against default realm and auth_to_local_realm(s) */
708*7c478bd9Sstevel@tonic-gate     if ((((size_t) realm_length != strlen(def_realm)) ||
709*7c478bd9Sstevel@tonic-gate         (memcmp(def_realm, krb5_princ_realm(context, aname)->data,
710*7c478bd9Sstevel@tonic-gate 		realm_length))) &&
711*7c478bd9Sstevel@tonic-gate 	!an_to_ln_realm_chk(context, aname, def_realm,
712*7c478bd9Sstevel@tonic-gate 			    realm_length)) {
713*7c478bd9Sstevel@tonic-gate         free(def_realm);
714*7c478bd9Sstevel@tonic-gate         return KRB5_LNAME_NOTRANS;
715*7c478bd9Sstevel@tonic-gate     }
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate     if (krb5_princ_size(context, aname) != 1) {
718*7c478bd9Sstevel@tonic-gate         if (krb5_princ_size(context, aname) == 2 ) {
719*7c478bd9Sstevel@tonic-gate            /* Check to see if 2nd component is the local realm. */
720*7c478bd9Sstevel@tonic-gate             if (strncmp(krb5_princ_component(context, aname, 1)->data,
721*7c478bd9Sstevel@tonic-gate 			def_realm, realm_length) ||
722*7c478bd9Sstevel@tonic-gate 		realm_length !=
723*7c478bd9Sstevel@tonic-gate 		    krb5_princ_component(context, aname, 1)->length)
724*7c478bd9Sstevel@tonic-gate 		    /* XXX an_to_ln_realm_chk ? */
725*7c478bd9Sstevel@tonic-gate                 return KRB5_LNAME_NOTRANS;
726*7c478bd9Sstevel@tonic-gate         }
727*7c478bd9Sstevel@tonic-gate         else
728*7c478bd9Sstevel@tonic-gate            /* no components or more than one component to non-realm part of name
729*7c478bd9Sstevel@tonic-gate            --no translation. */
730*7c478bd9Sstevel@tonic-gate             return KRB5_LNAME_NOTRANS;
731*7c478bd9Sstevel@tonic-gate     }
732*7c478bd9Sstevel@tonic-gate 
733*7c478bd9Sstevel@tonic-gate     free(def_realm);
734*7c478bd9Sstevel@tonic-gate     strncpy(lname, krb5_princ_component(context, aname,0)->data,
735*7c478bd9Sstevel@tonic-gate 	    min(krb5_princ_component(context, aname,0)->length,lnsize));
736*7c478bd9Sstevel@tonic-gate     if (lnsize <= krb5_princ_component(context, aname,0)->length ) {
737*7c478bd9Sstevel@tonic-gate 	retval = KRB5_CONFIG_NOTENUFSPACE;
738*7c478bd9Sstevel@tonic-gate     } else {
739*7c478bd9Sstevel@tonic-gate 	lname[krb5_princ_component(context, aname,0)->length] = '\0';
740*7c478bd9Sstevel@tonic-gate 	retval = 0;
741*7c478bd9Sstevel@tonic-gate     }
742*7c478bd9Sstevel@tonic-gate     return retval;
743*7c478bd9Sstevel@tonic-gate }
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate /*
746*7c478bd9Sstevel@tonic-gate  Converts an authentication name to a local name suitable for use by
747*7c478bd9Sstevel@tonic-gate  programs wishing a translation to an environment-specific name (e.g.
748*7c478bd9Sstevel@tonic-gate  user account name).
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate  lnsize specifies the maximum length name that is to be filled into
751*7c478bd9Sstevel@tonic-gate  lname.
752*7c478bd9Sstevel@tonic-gate  The translation will be null terminated in all non-error returns.
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate  returns system errors, NOT_ENOUGH_SPACE
755*7c478bd9Sstevel@tonic-gate */
756*7c478bd9Sstevel@tonic-gate 
757*7c478bd9Sstevel@tonic-gate krb5_error_code
758*7c478bd9Sstevel@tonic-gate krb5_aname_to_localname(krb5_context context,
759*7c478bd9Sstevel@tonic-gate 	krb5_const_principal aname, const int lnsize, char *lname)
760*7c478bd9Sstevel@tonic-gate {
761*7c478bd9Sstevel@tonic-gate     krb5_error_code	kret;
762*7c478bd9Sstevel@tonic-gate     char		*realm;
763*7c478bd9Sstevel@tonic-gate     char		*pname;
764*7c478bd9Sstevel@tonic-gate     char		*mname;
765*7c478bd9Sstevel@tonic-gate     const char		*hierarchy[5];
766*7c478bd9Sstevel@tonic-gate     char		**mapping_values;
767*7c478bd9Sstevel@tonic-gate     int			i, nvalid;
768*7c478bd9Sstevel@tonic-gate     char		*cp, *s;
769*7c478bd9Sstevel@tonic-gate     char		*typep, *argp;
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate     if (lnsize < 0)
772*7c478bd9Sstevel@tonic-gate 	return KRB5_CONFIG_NOTENUFSPACE;
773*7c478bd9Sstevel@tonic-gate 
774*7c478bd9Sstevel@tonic-gate     /*
775*7c478bd9Sstevel@tonic-gate      * First get the default realm.
776*7c478bd9Sstevel@tonic-gate      */
777*7c478bd9Sstevel@tonic-gate     if (!(kret = krb5_get_default_realm(context, &realm))) {
778*7c478bd9Sstevel@tonic-gate 	/* Flatten the name */
779*7c478bd9Sstevel@tonic-gate 	if (!(kret = krb5_unparse_name(context, aname, &pname))) {
780*7c478bd9Sstevel@tonic-gate 	    if ((mname = aname_full_to_mapping_name(pname))) {
781*7c478bd9Sstevel@tonic-gate 		/*
782*7c478bd9Sstevel@tonic-gate 		 * Search first for explicit mappings of the form:
783*7c478bd9Sstevel@tonic-gate 		 *
784*7c478bd9Sstevel@tonic-gate 		 * [realms]->realm->"auth_to_local_names"->mapping_name
785*7c478bd9Sstevel@tonic-gate 		 */
786*7c478bd9Sstevel@tonic-gate 		hierarchy[0] = "realms";
787*7c478bd9Sstevel@tonic-gate 		hierarchy[1] = realm;
788*7c478bd9Sstevel@tonic-gate 		hierarchy[2] = "auth_to_local_names";
789*7c478bd9Sstevel@tonic-gate 		hierarchy[3] = mname;
790*7c478bd9Sstevel@tonic-gate 		hierarchy[4] = (char *) NULL;
791*7c478bd9Sstevel@tonic-gate 		if (!(kret = profile_get_values(context->profile,
792*7c478bd9Sstevel@tonic-gate 						hierarchy,
793*7c478bd9Sstevel@tonic-gate 						&mapping_values))) {
794*7c478bd9Sstevel@tonic-gate 		    /* We found one or more explicit mappings. */
795*7c478bd9Sstevel@tonic-gate 		    for (nvalid=0; mapping_values[nvalid]; nvalid++);
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate 		    /* Just use the last one. */
798*7c478bd9Sstevel@tonic-gate 		    /* Trim the value. */
799*7c478bd9Sstevel@tonic-gate 		    s = mapping_values[nvalid-1];
800*7c478bd9Sstevel@tonic-gate 		    cp = s + strlen(s);
801*7c478bd9Sstevel@tonic-gate 		    while (cp > s) {
802*7c478bd9Sstevel@tonic-gate 			cp--;
803*7c478bd9Sstevel@tonic-gate 			if (!isspace((int)(*cp)))
804*7c478bd9Sstevel@tonic-gate 			    break;
805*7c478bd9Sstevel@tonic-gate 			*cp = '\0';
806*7c478bd9Sstevel@tonic-gate 		    }
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 		    /* Copy out the value if there's enough room */
809*7c478bd9Sstevel@tonic-gate 		    if (strlen(mapping_values[nvalid-1])+1 <= (size_t) lnsize)
810*7c478bd9Sstevel@tonic-gate 			strcpy(lname, mapping_values[nvalid-1]);
811*7c478bd9Sstevel@tonic-gate 		    else
812*7c478bd9Sstevel@tonic-gate 			kret = KRB5_CONFIG_NOTENUFSPACE;
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 		    /* Free residue */
815*7c478bd9Sstevel@tonic-gate 		    profile_free_list(mapping_values);
816*7c478bd9Sstevel@tonic-gate 		}
817*7c478bd9Sstevel@tonic-gate 		else {
818*7c478bd9Sstevel@tonic-gate 		    /*
819*7c478bd9Sstevel@tonic-gate 		     * OK - There's no explicit mapping.  Now check for
820*7c478bd9Sstevel@tonic-gate 		     * general auth_to_local rules of the form:
821*7c478bd9Sstevel@tonic-gate 		     *
822*7c478bd9Sstevel@tonic-gate 		     * [realms]->realm->"auth_to_local"
823*7c478bd9Sstevel@tonic-gate 		     *
824*7c478bd9Sstevel@tonic-gate 		     * This can have one or more of the following kinds of
825*7c478bd9Sstevel@tonic-gate 		     * values:
826*7c478bd9Sstevel@tonic-gate 		     *	DB:<filename>	- Look up principal in aname database.
827*7c478bd9Sstevel@tonic-gate 		     *	RULE:<sed-exp>	- Formulate lname from sed-exp.
828*7c478bd9Sstevel@tonic-gate 		     *	DEFAULT		- Use default rule.
829*7c478bd9Sstevel@tonic-gate 		     * The first rule to find a match is used.
830*7c478bd9Sstevel@tonic-gate 		     */
831*7c478bd9Sstevel@tonic-gate 		    hierarchy[0] = "realms";
832*7c478bd9Sstevel@tonic-gate 		    hierarchy[1] = realm;
833*7c478bd9Sstevel@tonic-gate 		    hierarchy[2] = "auth_to_local";
834*7c478bd9Sstevel@tonic-gate 		    hierarchy[3] = (char *) NULL;
835*7c478bd9Sstevel@tonic-gate 		    if (!(kret = profile_get_values(context->profile,
836*7c478bd9Sstevel@tonic-gate 						    hierarchy,
837*7c478bd9Sstevel@tonic-gate 						    &mapping_values))) {
838*7c478bd9Sstevel@tonic-gate 			/*
839*7c478bd9Sstevel@tonic-gate 			 * Loop through all the mapping values.
840*7c478bd9Sstevel@tonic-gate 			 */
841*7c478bd9Sstevel@tonic-gate 			for (i=0; mapping_values[i]; i++) {
842*7c478bd9Sstevel@tonic-gate 			    typep = mapping_values[i];
843*7c478bd9Sstevel@tonic-gate 			    argp = strchr(typep, ':');
844*7c478bd9Sstevel@tonic-gate 			    if (argp) {
845*7c478bd9Sstevel@tonic-gate 				*argp = '\0';
846*7c478bd9Sstevel@tonic-gate 				argp++;
847*7c478bd9Sstevel@tonic-gate 			    }
848*7c478bd9Sstevel@tonic-gate #ifdef ANAME_DB
849*7c478bd9Sstevel@tonic-gate 			    if (!strcmp(typep, "DB") && argp) {
850*7c478bd9Sstevel@tonic-gate 				kret = db_an_to_ln(context,
851*7c478bd9Sstevel@tonic-gate 						   argp,
852*7c478bd9Sstevel@tonic-gate 						   aname,
853*7c478bd9Sstevel@tonic-gate 						   lnsize,
854*7c478bd9Sstevel@tonic-gate 						   lname);
855*7c478bd9Sstevel@tonic-gate 				if (kret != KRB5_LNAME_NOTRANS)
856*7c478bd9Sstevel@tonic-gate 				    break;
857*7c478bd9Sstevel@tonic-gate 			    }
858*7c478bd9Sstevel@tonic-gate 			    else
859*7c478bd9Sstevel@tonic-gate #endif
860*7c478bd9Sstevel@tonic-gate #ifdef	AN_TO_LN_RULES
861*7c478bd9Sstevel@tonic-gate 			    if (!strcmp(typep, "RULE") && argp) {
862*7c478bd9Sstevel@tonic-gate 				kret = rule_an_to_ln(context,
863*7c478bd9Sstevel@tonic-gate 						     argp,
864*7c478bd9Sstevel@tonic-gate 						     aname,
865*7c478bd9Sstevel@tonic-gate 						     lnsize,
866*7c478bd9Sstevel@tonic-gate 						     lname);
867*7c478bd9Sstevel@tonic-gate 				if (kret != KRB5_LNAME_NOTRANS)
868*7c478bd9Sstevel@tonic-gate 				    break;
869*7c478bd9Sstevel@tonic-gate 			    }
870*7c478bd9Sstevel@tonic-gate 			    else
871*7c478bd9Sstevel@tonic-gate #endif	/* AN_TO_LN_RULES */
872*7c478bd9Sstevel@tonic-gate 			    if (!strcmp(typep, "DEFAULT") && !argp) {
873*7c478bd9Sstevel@tonic-gate 				kret = default_an_to_ln(context,
874*7c478bd9Sstevel@tonic-gate 							aname,
875*7c478bd9Sstevel@tonic-gate 							lnsize,
876*7c478bd9Sstevel@tonic-gate 							lname);
877*7c478bd9Sstevel@tonic-gate 				if (kret != KRB5_LNAME_NOTRANS)
878*7c478bd9Sstevel@tonic-gate 				    break;
879*7c478bd9Sstevel@tonic-gate 			    }
880*7c478bd9Sstevel@tonic-gate 			    else {
881*7c478bd9Sstevel@tonic-gate 				kret = KRB5_CONFIG_BADFORMAT;
882*7c478bd9Sstevel@tonic-gate 				break;
883*7c478bd9Sstevel@tonic-gate 			    }
884*7c478bd9Sstevel@tonic-gate 			}
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate 			/* We're done, clean up the droppings. */
887*7c478bd9Sstevel@tonic-gate 			profile_free_list(mapping_values);
888*7c478bd9Sstevel@tonic-gate 		    }
889*7c478bd9Sstevel@tonic-gate 		    else {
890*7c478bd9Sstevel@tonic-gate 			/*
891*7c478bd9Sstevel@tonic-gate 			 * No profile relation found, try default mapping.
892*7c478bd9Sstevel@tonic-gate 			 */
893*7c478bd9Sstevel@tonic-gate 			kret = default_an_to_ln(context,
894*7c478bd9Sstevel@tonic-gate 						aname,
895*7c478bd9Sstevel@tonic-gate 						lnsize,
896*7c478bd9Sstevel@tonic-gate 						lname);
897*7c478bd9Sstevel@tonic-gate 		    }
898*7c478bd9Sstevel@tonic-gate 		}
899*7c478bd9Sstevel@tonic-gate 		free(mname);
900*7c478bd9Sstevel@tonic-gate 	    }
901*7c478bd9Sstevel@tonic-gate 	    else
902*7c478bd9Sstevel@tonic-gate 		kret = ENOMEM;
903*7c478bd9Sstevel@tonic-gate 	    krb5_xfree(pname);
904*7c478bd9Sstevel@tonic-gate 	}
905*7c478bd9Sstevel@tonic-gate 	krb5_xfree(realm);
906*7c478bd9Sstevel@tonic-gate     }
907*7c478bd9Sstevel@tonic-gate     return(kret);
908*7c478bd9Sstevel@tonic-gate }
909