1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34*ae771770SStanislav Sedov /**
35*ae771770SStanislav Sedov * @page krb5_principal_intro The principal handing functions.
36*ae771770SStanislav Sedov *
37*ae771770SStanislav Sedov * A Kerberos principal is a email address looking string that
38*ae771770SStanislav Sedov * contains to parts separeted by a @. The later part is the kerbero
39*ae771770SStanislav Sedov * realm the principal belongs to and the former is a list of 0 or
40*ae771770SStanislav Sedov * more components. For example
41*ae771770SStanislav Sedov * @verbatim
42*ae771770SStanislav Sedov lha@SU.SE
43*ae771770SStanislav Sedov host/hummel.it.su.se@SU.SE
44*ae771770SStanislav Sedov host/admin@H5L.ORG
45*ae771770SStanislav Sedov @endverbatim
46*ae771770SStanislav Sedov *
47*ae771770SStanislav Sedov * See the library functions here: @ref krb5_principal
48*ae771770SStanislav Sedov */
49*ae771770SStanislav Sedov
50b528cefcSMark Murray #include "krb5_locl.h"
51b528cefcSMark Murray #ifdef HAVE_RES_SEARCH
52b528cefcSMark Murray #define USE_RESOLVER
53b528cefcSMark Murray #endif
54b528cefcSMark Murray #ifdef HAVE_ARPA_NAMESER_H
55b528cefcSMark Murray #include <arpa/nameser.h>
56b528cefcSMark Murray #endif
575e9cd1aeSAssar Westerlund #include <fnmatch.h>
58b528cefcSMark Murray #include "resolve.h"
59b528cefcSMark Murray
60b528cefcSMark Murray #define princ_num_comp(P) ((P)->name.name_string.len)
61b528cefcSMark Murray #define princ_type(P) ((P)->name.name_type)
62b528cefcSMark Murray #define princ_comp(P) ((P)->name.name_string.val)
63b528cefcSMark Murray #define princ_ncomp(P, N) ((P)->name.name_string.val[(N)])
64b528cefcSMark Murray #define princ_realm(P) ((P)->realm)
65b528cefcSMark Murray
66*ae771770SStanislav Sedov /**
67*ae771770SStanislav Sedov * Frees a Kerberos principal allocated by the library with
68*ae771770SStanislav Sedov * krb5_parse_name(), krb5_make_principal() or any other related
69*ae771770SStanislav Sedov * principal functions.
70*ae771770SStanislav Sedov *
71*ae771770SStanislav Sedov * @param context A Kerberos context.
72*ae771770SStanislav Sedov * @param p a principal to free.
73*ae771770SStanislav Sedov *
74*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
75*ae771770SStanislav Sedov *
76*ae771770SStanislav Sedov * @ingroup krb5_principal
77*ae771770SStanislav Sedov */
78*ae771770SStanislav Sedov
79*ae771770SStanislav Sedov KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_free_principal(krb5_context context,krb5_principal p)80b528cefcSMark Murray krb5_free_principal(krb5_context context,
81b528cefcSMark Murray krb5_principal p)
82b528cefcSMark Murray {
83b528cefcSMark Murray if(p){
84b528cefcSMark Murray free_Principal(p);
85b528cefcSMark Murray free(p);
86b528cefcSMark Murray }
87b528cefcSMark Murray }
88b528cefcSMark Murray
89*ae771770SStanislav Sedov /**
90*ae771770SStanislav Sedov * Set the type of the principal
91*ae771770SStanislav Sedov *
92*ae771770SStanislav Sedov * @param context A Kerberos context.
93*ae771770SStanislav Sedov * @param principal principal to set the type for
94*ae771770SStanislav Sedov * @param type the new type
95*ae771770SStanislav Sedov *
96*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
97*ae771770SStanislav Sedov *
98*ae771770SStanislav Sedov * @ingroup krb5_principal
99*ae771770SStanislav Sedov */
100*ae771770SStanislav Sedov
101*ae771770SStanislav Sedov KRB5_LIB_FUNCTION void KRB5_LIB_CALL
krb5_principal_set_type(krb5_context context,krb5_principal principal,int type)102c19800e8SDoug Rabson krb5_principal_set_type(krb5_context context,
103c19800e8SDoug Rabson krb5_principal principal,
104c19800e8SDoug Rabson int type)
105c19800e8SDoug Rabson {
106c19800e8SDoug Rabson princ_type(principal) = type;
107c19800e8SDoug Rabson }
108c19800e8SDoug Rabson
109*ae771770SStanislav Sedov /**
110*ae771770SStanislav Sedov * Get the type of the principal
111*ae771770SStanislav Sedov *
112*ae771770SStanislav Sedov * @param context A Kerberos context.
113*ae771770SStanislav Sedov * @param principal principal to get the type for
114*ae771770SStanislav Sedov *
115*ae771770SStanislav Sedov * @return the type of principal
116*ae771770SStanislav Sedov *
117*ae771770SStanislav Sedov * @ingroup krb5_principal
118*ae771770SStanislav Sedov */
119*ae771770SStanislav Sedov
120*ae771770SStanislav Sedov KRB5_LIB_FUNCTION int KRB5_LIB_CALL
krb5_principal_get_type(krb5_context context,krb5_const_principal principal)1214137ff4cSJacques Vidrine krb5_principal_get_type(krb5_context context,
122c19800e8SDoug Rabson krb5_const_principal principal)
1234137ff4cSJacques Vidrine {
1244137ff4cSJacques Vidrine return princ_type(principal);
1254137ff4cSJacques Vidrine }
1264137ff4cSJacques Vidrine
127*ae771770SStanislav Sedov /**
128*ae771770SStanislav Sedov * Get the realm of the principal
129*ae771770SStanislav Sedov *
130*ae771770SStanislav Sedov * @param context A Kerberos context.
131*ae771770SStanislav Sedov * @param principal principal to get the realm for
132*ae771770SStanislav Sedov *
133*ae771770SStanislav Sedov * @return realm of the principal, don't free or use after krb5_principal is freed
134*ae771770SStanislav Sedov *
135*ae771770SStanislav Sedov * @ingroup krb5_principal
136*ae771770SStanislav Sedov */
137*ae771770SStanislav Sedov
138*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
krb5_principal_get_realm(krb5_context context,krb5_const_principal principal)1394137ff4cSJacques Vidrine krb5_principal_get_realm(krb5_context context,
140c19800e8SDoug Rabson krb5_const_principal principal)
1414137ff4cSJacques Vidrine {
1424137ff4cSJacques Vidrine return princ_realm(principal);
1434137ff4cSJacques Vidrine }
1444137ff4cSJacques Vidrine
145*ae771770SStanislav Sedov KRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
krb5_principal_get_comp_string(krb5_context context,krb5_const_principal principal,unsigned int component)1464137ff4cSJacques Vidrine krb5_principal_get_comp_string(krb5_context context,
147c19800e8SDoug Rabson krb5_const_principal principal,
1484137ff4cSJacques Vidrine unsigned int component)
1494137ff4cSJacques Vidrine {
1504137ff4cSJacques Vidrine if(component >= princ_num_comp(principal))
1514137ff4cSJacques Vidrine return NULL;
1524137ff4cSJacques Vidrine return princ_ncomp(principal, component);
1534137ff4cSJacques Vidrine }
1544137ff4cSJacques Vidrine
155*ae771770SStanislav Sedov /**
156*ae771770SStanislav Sedov * Get number of component is principal.
157*ae771770SStanislav Sedov *
158*ae771770SStanislav Sedov * @param context Kerberos 5 context
159*ae771770SStanislav Sedov * @param principal principal to query
160*ae771770SStanislav Sedov *
161*ae771770SStanislav Sedov * @return number of components in string
162*ae771770SStanislav Sedov *
163*ae771770SStanislav Sedov * @ingroup krb5_principal
164*ae771770SStanislav Sedov */
165*ae771770SStanislav Sedov
166*ae771770SStanislav Sedov KRB5_LIB_FUNCTION unsigned int KRB5_LIB_CALL
krb5_principal_get_num_comp(krb5_context context,krb5_const_principal principal)167*ae771770SStanislav Sedov krb5_principal_get_num_comp(krb5_context context,
168*ae771770SStanislav Sedov krb5_const_principal principal)
169*ae771770SStanislav Sedov {
170*ae771770SStanislav Sedov return princ_num_comp(principal);
171*ae771770SStanislav Sedov }
172*ae771770SStanislav Sedov
173*ae771770SStanislav Sedov /**
174*ae771770SStanislav Sedov * Parse a name into a krb5_principal structure, flags controls the behavior.
175*ae771770SStanislav Sedov *
176*ae771770SStanislav Sedov * @param context Kerberos 5 context
177*ae771770SStanislav Sedov * @param name name to parse into a Kerberos principal
178*ae771770SStanislav Sedov * @param flags flags to control the behavior
179*ae771770SStanislav Sedov * @param principal returned principal, free with krb5_free_principal().
180*ae771770SStanislav Sedov *
181*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
182*ae771770SStanislav Sedov *
183*ae771770SStanislav Sedov * @ingroup krb5_principal
184*ae771770SStanislav Sedov */
185*ae771770SStanislav Sedov
186*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_parse_name_flags(krb5_context context,const char * name,int flags,krb5_principal * principal)187c19800e8SDoug Rabson krb5_parse_name_flags(krb5_context context,
188b528cefcSMark Murray const char *name,
189c19800e8SDoug Rabson int flags,
190b528cefcSMark Murray krb5_principal *principal)
191b528cefcSMark Murray {
192b528cefcSMark Murray krb5_error_code ret;
193c19800e8SDoug Rabson heim_general_string *comp;
194c19800e8SDoug Rabson heim_general_string realm = NULL;
195b528cefcSMark Murray int ncomp;
196b528cefcSMark Murray
1978373020dSJacques Vidrine const char *p;
198b528cefcSMark Murray char *q;
199b528cefcSMark Murray char *s;
200b528cefcSMark Murray char *start;
201b528cefcSMark Murray
202b528cefcSMark Murray int n;
203b528cefcSMark Murray char c;
204b528cefcSMark Murray int got_realm = 0;
205c19800e8SDoug Rabson int first_at = 1;
206c19800e8SDoug Rabson int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE);
207b528cefcSMark Murray
208c19800e8SDoug Rabson *principal = NULL;
209c19800e8SDoug Rabson
210*ae771770SStanislav Sedov #define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_REQUIRE_REALM)
211c19800e8SDoug Rabson
212c19800e8SDoug Rabson if ((flags & RFLAGS) == RFLAGS) {
213*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_ERR_NO_SERVICE,
214*ae771770SStanislav Sedov N_("Can't require both realm and "
215*ae771770SStanislav Sedov "no realm at the same time", ""));
216c19800e8SDoug Rabson return KRB5_ERR_NO_SERVICE;
217c19800e8SDoug Rabson }
218c19800e8SDoug Rabson #undef RFLAGS
219c19800e8SDoug Rabson
220c19800e8SDoug Rabson /* count number of component,
221c19800e8SDoug Rabson * enterprise names only have one component
222c19800e8SDoug Rabson */
223b528cefcSMark Murray ncomp = 1;
224c19800e8SDoug Rabson if (!enterprise) {
2258373020dSJacques Vidrine for(p = name; *p; p++){
226b528cefcSMark Murray if(*p=='\\'){
227adb0ddaeSAssar Westerlund if(!p[1]) {
228*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
229*ae771770SStanislav Sedov N_("trailing \\ in principal name", ""));
230b528cefcSMark Murray return KRB5_PARSE_MALFORMED;
231adb0ddaeSAssar Westerlund }
232b528cefcSMark Murray p++;
233b528cefcSMark Murray } else if(*p == '/')
234b528cefcSMark Murray ncomp++;
235c19800e8SDoug Rabson else if(*p == '@')
236c19800e8SDoug Rabson break;
237c19800e8SDoug Rabson }
238b528cefcSMark Murray }
239b528cefcSMark Murray comp = calloc(ncomp, sizeof(*comp));
240adb0ddaeSAssar Westerlund if (comp == NULL) {
241*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
242*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
243b528cefcSMark Murray return ENOMEM;
244adb0ddaeSAssar Westerlund }
245b528cefcSMark Murray
246b528cefcSMark Murray n = 0;
2478373020dSJacques Vidrine p = start = q = s = strdup(name);
248b528cefcSMark Murray if (start == NULL) {
249b528cefcSMark Murray free (comp);
250*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
251*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
252b528cefcSMark Murray return ENOMEM;
253b528cefcSMark Murray }
254b528cefcSMark Murray while(*p){
255b528cefcSMark Murray c = *p++;
256b528cefcSMark Murray if(c == '\\'){
257b528cefcSMark Murray c = *p++;
258b528cefcSMark Murray if(c == 'n')
259b528cefcSMark Murray c = '\n';
260b528cefcSMark Murray else if(c == 't')
261b528cefcSMark Murray c = '\t';
262b528cefcSMark Murray else if(c == 'b')
263b528cefcSMark Murray c = '\b';
264b528cefcSMark Murray else if(c == '0')
265b528cefcSMark Murray c = '\0';
2665bda878eSJacques Vidrine else if(c == '\0') {
2675bda878eSJacques Vidrine ret = KRB5_PARSE_MALFORMED;
268*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
269*ae771770SStanislav Sedov N_("trailing \\ in principal name", ""));
2705bda878eSJacques Vidrine goto exit;
2715bda878eSJacques Vidrine }
272c19800e8SDoug Rabson }else if(enterprise && first_at) {
273c19800e8SDoug Rabson if (c == '@')
274c19800e8SDoug Rabson first_at = 0;
275c19800e8SDoug Rabson }else if((c == '/' && !enterprise) || c == '@'){
276b528cefcSMark Murray if(got_realm){
277b528cefcSMark Murray ret = KRB5_PARSE_MALFORMED;
278*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
279*ae771770SStanislav Sedov N_("part after realm in principal name", ""));
280b528cefcSMark Murray goto exit;
281b528cefcSMark Murray }else{
282b528cefcSMark Murray comp[n] = malloc(q - start + 1);
283b528cefcSMark Murray if (comp[n] == NULL) {
284b528cefcSMark Murray ret = ENOMEM;
285*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
286*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
287b528cefcSMark Murray goto exit;
288b528cefcSMark Murray }
28913e3f4d6SMark Murray memcpy(comp[n], start, q - start);
290b528cefcSMark Murray comp[n][q - start] = 0;
291b528cefcSMark Murray n++;
292b528cefcSMark Murray }
293b528cefcSMark Murray if(c == '@')
294b528cefcSMark Murray got_realm = 1;
295b528cefcSMark Murray start = q;
296b528cefcSMark Murray continue;
297b528cefcSMark Murray }
298*ae771770SStanislav Sedov if(got_realm && (c == '/' || c == '\0')) {
299b528cefcSMark Murray ret = KRB5_PARSE_MALFORMED;
300*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
301*ae771770SStanislav Sedov N_("part after realm in principal name", ""));
302b528cefcSMark Murray goto exit;
303b528cefcSMark Murray }
304b528cefcSMark Murray *q++ = c;
305b528cefcSMark Murray }
306b528cefcSMark Murray if(got_realm){
307c19800e8SDoug Rabson if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
308c19800e8SDoug Rabson ret = KRB5_PARSE_MALFORMED;
309*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
310*ae771770SStanislav Sedov N_("realm found in 'short' principal "
311*ae771770SStanislav Sedov "expected to be without one", ""));
312c19800e8SDoug Rabson goto exit;
313c19800e8SDoug Rabson }
314b528cefcSMark Murray realm = malloc(q - start + 1);
315b528cefcSMark Murray if (realm == NULL) {
316b528cefcSMark Murray ret = ENOMEM;
317*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
318*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
319b528cefcSMark Murray goto exit;
320b528cefcSMark Murray }
32113e3f4d6SMark Murray memcpy(realm, start, q - start);
322b528cefcSMark Murray realm[q - start] = 0;
323b528cefcSMark Murray }else{
324*ae771770SStanislav Sedov if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) {
325c19800e8SDoug Rabson ret = KRB5_PARSE_MALFORMED;
326*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
327*ae771770SStanislav Sedov N_("realm NOT found in principal "
328*ae771770SStanislav Sedov "expected to be with one", ""));
329c19800e8SDoug Rabson goto exit;
330c19800e8SDoug Rabson } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
331c19800e8SDoug Rabson realm = NULL;
332c19800e8SDoug Rabson } else {
333b528cefcSMark Murray ret = krb5_get_default_realm (context, &realm);
334b528cefcSMark Murray if (ret)
335b528cefcSMark Murray goto exit;
336c19800e8SDoug Rabson }
337b528cefcSMark Murray
338b528cefcSMark Murray comp[n] = malloc(q - start + 1);
339b528cefcSMark Murray if (comp[n] == NULL) {
340b528cefcSMark Murray ret = ENOMEM;
341*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
342*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
343b528cefcSMark Murray goto exit;
344b528cefcSMark Murray }
34513e3f4d6SMark Murray memcpy(comp[n], start, q - start);
346b528cefcSMark Murray comp[n][q - start] = 0;
347b528cefcSMark Murray n++;
348b528cefcSMark Murray }
349b528cefcSMark Murray *principal = malloc(sizeof(**principal));
350b528cefcSMark Murray if (*principal == NULL) {
351b528cefcSMark Murray ret = ENOMEM;
352*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
353*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
354b528cefcSMark Murray goto exit;
355b528cefcSMark Murray }
356c19800e8SDoug Rabson if (enterprise)
357c19800e8SDoug Rabson (*principal)->name.name_type = KRB5_NT_ENTERPRISE_PRINCIPAL;
358c19800e8SDoug Rabson else
359b528cefcSMark Murray (*principal)->name.name_type = KRB5_NT_PRINCIPAL;
360b528cefcSMark Murray (*principal)->name.name_string.val = comp;
361b528cefcSMark Murray princ_num_comp(*principal) = n;
362b528cefcSMark Murray (*principal)->realm = realm;
363b528cefcSMark Murray free(s);
364b528cefcSMark Murray return 0;
365b528cefcSMark Murray exit:
366b528cefcSMark Murray while(n>0){
367b528cefcSMark Murray free(comp[--n]);
368b528cefcSMark Murray }
369b528cefcSMark Murray free(comp);
370c19800e8SDoug Rabson free(realm);
371b528cefcSMark Murray free(s);
372b528cefcSMark Murray return ret;
373b528cefcSMark Murray }
374b528cefcSMark Murray
375*ae771770SStanislav Sedov /**
376*ae771770SStanislav Sedov * Parse a name into a krb5_principal structure
377*ae771770SStanislav Sedov *
378*ae771770SStanislav Sedov * @param context Kerberos 5 context
379*ae771770SStanislav Sedov * @param name name to parse into a Kerberos principal
380*ae771770SStanislav Sedov * @param principal returned principal, free with krb5_free_principal().
381*ae771770SStanislav Sedov *
382*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
383*ae771770SStanislav Sedov *
384*ae771770SStanislav Sedov * @ingroup krb5_principal
385*ae771770SStanislav Sedov */
386*ae771770SStanislav Sedov
387*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_parse_name(krb5_context context,const char * name,krb5_principal * principal)388c19800e8SDoug Rabson krb5_parse_name(krb5_context context,
389c19800e8SDoug Rabson const char *name,
390c19800e8SDoug Rabson krb5_principal *principal)
391c19800e8SDoug Rabson {
392c19800e8SDoug Rabson return krb5_parse_name_flags(context, name, 0, principal);
393c19800e8SDoug Rabson }
394c19800e8SDoug Rabson
395b528cefcSMark Murray static const char quotable_chars[] = " \n\t\b\\/@";
396b528cefcSMark Murray static const char replace_chars[] = " ntb\\/@";
397c19800e8SDoug Rabson static const char nq_chars[] = " \\/@";
398b528cefcSMark Murray
399b528cefcSMark Murray #define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0);
400b528cefcSMark Murray
401b528cefcSMark Murray static size_t
quote_string(const char * s,char * out,size_t idx,size_t len,int display)402c19800e8SDoug Rabson quote_string(const char *s, char *out, size_t idx, size_t len, int display)
403b528cefcSMark Murray {
404b528cefcSMark Murray const char *p, *q;
405c19800e8SDoug Rabson for(p = s; *p && idx < len; p++){
406c19800e8SDoug Rabson q = strchr(quotable_chars, *p);
407c19800e8SDoug Rabson if (q && display) {
408c19800e8SDoug Rabson add_char(out, idx, len, replace_chars[q - quotable_chars]);
409c19800e8SDoug Rabson } else if (q) {
410c19800e8SDoug Rabson add_char(out, idx, len, '\\');
411c19800e8SDoug Rabson add_char(out, idx, len, replace_chars[q - quotable_chars]);
412b528cefcSMark Murray }else
413c19800e8SDoug Rabson add_char(out, idx, len, *p);
414b528cefcSMark Murray }
415c19800e8SDoug Rabson if(idx < len)
416c19800e8SDoug Rabson out[idx] = '\0';
417c19800e8SDoug Rabson return idx;
418b528cefcSMark Murray }
419b528cefcSMark Murray
420b528cefcSMark Murray
421b528cefcSMark Murray static krb5_error_code
unparse_name_fixed(krb5_context context,krb5_const_principal principal,char * name,size_t len,int flags)422b528cefcSMark Murray unparse_name_fixed(krb5_context context,
423b528cefcSMark Murray krb5_const_principal principal,
424b528cefcSMark Murray char *name,
425b528cefcSMark Murray size_t len,
426c19800e8SDoug Rabson int flags)
427b528cefcSMark Murray {
428c19800e8SDoug Rabson size_t idx = 0;
429*ae771770SStanislav Sedov size_t i;
430c19800e8SDoug Rabson int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0;
431c19800e8SDoug Rabson int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0;
432c19800e8SDoug Rabson int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0;
433c19800e8SDoug Rabson
434c19800e8SDoug Rabson if (!no_realm && princ_realm(principal) == NULL) {
435*ae771770SStanislav Sedov krb5_set_error_message(context, ERANGE,
436*ae771770SStanislav Sedov N_("Realm missing from principal, "
437*ae771770SStanislav Sedov "can't unparse", ""));
438b528cefcSMark Murray return ERANGE;
439b528cefcSMark Murray }
440c19800e8SDoug Rabson
441c19800e8SDoug Rabson for(i = 0; i < princ_num_comp(principal); i++){
442c19800e8SDoug Rabson if(i)
443c19800e8SDoug Rabson add_char(name, idx, len, '/');
444c19800e8SDoug Rabson idx = quote_string(princ_ncomp(principal, i), name, idx, len, display);
445c19800e8SDoug Rabson if(idx == len) {
446*ae771770SStanislav Sedov krb5_set_error_message(context, ERANGE,
447*ae771770SStanislav Sedov N_("Out of space printing principal", ""));
448c19800e8SDoug Rabson return ERANGE;
449c19800e8SDoug Rabson }
450c19800e8SDoug Rabson }
451b528cefcSMark Murray /* add realm if different from default realm */
452c19800e8SDoug Rabson if(short_form && !no_realm) {
453b528cefcSMark Murray krb5_realm r;
454b528cefcSMark Murray krb5_error_code ret;
455b528cefcSMark Murray ret = krb5_get_default_realm(context, &r);
456b528cefcSMark Murray if(ret)
457b528cefcSMark Murray return ret;
458b528cefcSMark Murray if(strcmp(princ_realm(principal), r) != 0)
459b528cefcSMark Murray short_form = 0;
460b528cefcSMark Murray free(r);
461b528cefcSMark Murray }
462c19800e8SDoug Rabson if(!short_form && !no_realm) {
463c19800e8SDoug Rabson add_char(name, idx, len, '@');
464c19800e8SDoug Rabson idx = quote_string(princ_realm(principal), name, idx, len, display);
465c19800e8SDoug Rabson if(idx == len) {
466*ae771770SStanislav Sedov krb5_set_error_message(context, ERANGE,
467*ae771770SStanislav Sedov N_("Out of space printing "
468*ae771770SStanislav Sedov "realm of principal", ""));
469b528cefcSMark Murray return ERANGE;
470b528cefcSMark Murray }
471c19800e8SDoug Rabson }
472b528cefcSMark Murray return 0;
473b528cefcSMark Murray }
474b528cefcSMark Murray
475*ae771770SStanislav Sedov /**
476*ae771770SStanislav Sedov * Unparse the principal name to a fixed buffer
477*ae771770SStanislav Sedov *
478*ae771770SStanislav Sedov * @param context A Kerberos context.
479*ae771770SStanislav Sedov * @param principal principal to unparse
480*ae771770SStanislav Sedov * @param name buffer to write name to
481*ae771770SStanislav Sedov * @param len length of buffer
482*ae771770SStanislav Sedov *
483*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
484*ae771770SStanislav Sedov *
485*ae771770SStanislav Sedov * @ingroup krb5_principal
486*ae771770SStanislav Sedov */
487*ae771770SStanislav Sedov
488*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_unparse_name_fixed(krb5_context context,krb5_const_principal principal,char * name,size_t len)489b528cefcSMark Murray krb5_unparse_name_fixed(krb5_context context,
490b528cefcSMark Murray krb5_const_principal principal,
491b528cefcSMark Murray char *name,
492b528cefcSMark Murray size_t len)
493b528cefcSMark Murray {
494c19800e8SDoug Rabson return unparse_name_fixed(context, principal, name, len, 0);
495b528cefcSMark Murray }
496b528cefcSMark Murray
497*ae771770SStanislav Sedov /**
498*ae771770SStanislav Sedov * Unparse the principal name to a fixed buffer. The realm is skipped
499*ae771770SStanislav Sedov * if its a default realm.
500*ae771770SStanislav Sedov *
501*ae771770SStanislav Sedov * @param context A Kerberos context.
502*ae771770SStanislav Sedov * @param principal principal to unparse
503*ae771770SStanislav Sedov * @param name buffer to write name to
504*ae771770SStanislav Sedov * @param len length of buffer
505*ae771770SStanislav Sedov *
506*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
507*ae771770SStanislav Sedov *
508*ae771770SStanislav Sedov * @ingroup krb5_principal
509*ae771770SStanislav Sedov */
510*ae771770SStanislav Sedov
511*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_unparse_name_fixed_short(krb5_context context,krb5_const_principal principal,char * name,size_t len)512b528cefcSMark Murray krb5_unparse_name_fixed_short(krb5_context context,
513b528cefcSMark Murray krb5_const_principal principal,
514b528cefcSMark Murray char *name,
515b528cefcSMark Murray size_t len)
516b528cefcSMark Murray {
517c19800e8SDoug Rabson return unparse_name_fixed(context, principal, name, len,
518c19800e8SDoug Rabson KRB5_PRINCIPAL_UNPARSE_SHORT);
519c19800e8SDoug Rabson }
520c19800e8SDoug Rabson
521*ae771770SStanislav Sedov /**
522*ae771770SStanislav Sedov * Unparse the principal name with unparse flags to a fixed buffer.
523*ae771770SStanislav Sedov *
524*ae771770SStanislav Sedov * @param context A Kerberos context.
525*ae771770SStanislav Sedov * @param principal principal to unparse
526*ae771770SStanislav Sedov * @param flags unparse flags
527*ae771770SStanislav Sedov * @param name buffer to write name to
528*ae771770SStanislav Sedov * @param len length of buffer
529*ae771770SStanislav Sedov *
530*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
531*ae771770SStanislav Sedov *
532*ae771770SStanislav Sedov * @ingroup krb5_principal
533*ae771770SStanislav Sedov */
534*ae771770SStanislav Sedov
535*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_unparse_name_fixed_flags(krb5_context context,krb5_const_principal principal,int flags,char * name,size_t len)536c19800e8SDoug Rabson krb5_unparse_name_fixed_flags(krb5_context context,
537c19800e8SDoug Rabson krb5_const_principal principal,
538c19800e8SDoug Rabson int flags,
539c19800e8SDoug Rabson char *name,
540c19800e8SDoug Rabson size_t len)
541c19800e8SDoug Rabson {
542c19800e8SDoug Rabson return unparse_name_fixed(context, principal, name, len, flags);
543b528cefcSMark Murray }
544b528cefcSMark Murray
545b528cefcSMark Murray static krb5_error_code
unparse_name(krb5_context context,krb5_const_principal principal,char ** name,int flags)546b528cefcSMark Murray unparse_name(krb5_context context,
547b528cefcSMark Murray krb5_const_principal principal,
548b528cefcSMark Murray char **name,
549c19800e8SDoug Rabson int flags)
550b528cefcSMark Murray {
551b528cefcSMark Murray size_t len = 0, plen;
552*ae771770SStanislav Sedov size_t i;
553b528cefcSMark Murray krb5_error_code ret;
554b528cefcSMark Murray /* count length */
555c19800e8SDoug Rabson if (princ_realm(principal)) {
556b528cefcSMark Murray plen = strlen(princ_realm(principal));
557c19800e8SDoug Rabson
558b528cefcSMark Murray if(strcspn(princ_realm(principal), quotable_chars) == plen)
559b528cefcSMark Murray len += plen;
560b528cefcSMark Murray else
561b528cefcSMark Murray len += 2*plen;
562c19800e8SDoug Rabson len++; /* '@' */
563c19800e8SDoug Rabson }
564b528cefcSMark Murray for(i = 0; i < princ_num_comp(principal); i++){
565b528cefcSMark Murray plen = strlen(princ_ncomp(principal, i));
566b528cefcSMark Murray if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen)
567b528cefcSMark Murray len += plen;
568b528cefcSMark Murray else
569b528cefcSMark Murray len += 2*plen;
570b528cefcSMark Murray len++;
571b528cefcSMark Murray }
572c19800e8SDoug Rabson len++; /* '\0' */
573b528cefcSMark Murray *name = malloc(len);
5741c43270aSJacques Vidrine if(*name == NULL) {
575*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
576*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
577b528cefcSMark Murray return ENOMEM;
578adb0ddaeSAssar Westerlund }
579c19800e8SDoug Rabson ret = unparse_name_fixed(context, principal, *name, len, flags);
5801c43270aSJacques Vidrine if(ret) {
581b528cefcSMark Murray free(*name);
5821c43270aSJacques Vidrine *name = NULL;
5831c43270aSJacques Vidrine }
584b528cefcSMark Murray return ret;
585b528cefcSMark Murray }
586b528cefcSMark Murray
587*ae771770SStanislav Sedov /**
588*ae771770SStanislav Sedov * Unparse the Kerberos name into a string
589*ae771770SStanislav Sedov *
590*ae771770SStanislav Sedov * @param context Kerberos 5 context
591*ae771770SStanislav Sedov * @param principal principal to query
592*ae771770SStanislav Sedov * @param name resulting string, free with krb5_xfree()
593*ae771770SStanislav Sedov *
594*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
595*ae771770SStanislav Sedov *
596*ae771770SStanislav Sedov * @ingroup krb5_principal
597*ae771770SStanislav Sedov */
598*ae771770SStanislav Sedov
599*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_unparse_name(krb5_context context,krb5_const_principal principal,char ** name)600b528cefcSMark Murray krb5_unparse_name(krb5_context context,
601b528cefcSMark Murray krb5_const_principal principal,
602b528cefcSMark Murray char **name)
603b528cefcSMark Murray {
604c19800e8SDoug Rabson return unparse_name(context, principal, name, 0);
605b528cefcSMark Murray }
606b528cefcSMark Murray
607*ae771770SStanislav Sedov /**
608*ae771770SStanislav Sedov * Unparse the Kerberos name into a string
609*ae771770SStanislav Sedov *
610*ae771770SStanislav Sedov * @param context Kerberos 5 context
611*ae771770SStanislav Sedov * @param principal principal to query
612*ae771770SStanislav Sedov * @param flags flag to determine the behavior
613*ae771770SStanislav Sedov * @param name resulting string, free with krb5_xfree()
614*ae771770SStanislav Sedov *
615*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
616*ae771770SStanislav Sedov *
617*ae771770SStanislav Sedov * @ingroup krb5_principal
618*ae771770SStanislav Sedov */
619*ae771770SStanislav Sedov
620*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_unparse_name_flags(krb5_context context,krb5_const_principal principal,int flags,char ** name)621c19800e8SDoug Rabson krb5_unparse_name_flags(krb5_context context,
622c19800e8SDoug Rabson krb5_const_principal principal,
623c19800e8SDoug Rabson int flags,
624c19800e8SDoug Rabson char **name)
625c19800e8SDoug Rabson {
626c19800e8SDoug Rabson return unparse_name(context, principal, name, flags);
627c19800e8SDoug Rabson }
628c19800e8SDoug Rabson
629*ae771770SStanislav Sedov /**
630*ae771770SStanislav Sedov * Unparse the principal name to a allocated buffer. The realm is
631*ae771770SStanislav Sedov * skipped if its a default realm.
632*ae771770SStanislav Sedov *
633*ae771770SStanislav Sedov * @param context A Kerberos context.
634*ae771770SStanislav Sedov * @param principal principal to unparse
635*ae771770SStanislav Sedov * @param name returned buffer, free with krb5_xfree()
636*ae771770SStanislav Sedov *
637*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
638*ae771770SStanislav Sedov *
639*ae771770SStanislav Sedov * @ingroup krb5_principal
640*ae771770SStanislav Sedov */
641*ae771770SStanislav Sedov
642*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_unparse_name_short(krb5_context context,krb5_const_principal principal,char ** name)643b528cefcSMark Murray krb5_unparse_name_short(krb5_context context,
644b528cefcSMark Murray krb5_const_principal principal,
645b528cefcSMark Murray char **name)
646b528cefcSMark Murray {
647c19800e8SDoug Rabson return unparse_name(context, principal, name, KRB5_PRINCIPAL_UNPARSE_SHORT);
648b528cefcSMark Murray }
649b528cefcSMark Murray
650*ae771770SStanislav Sedov /**
651*ae771770SStanislav Sedov * Set a new realm for a principal, and as a side-effect free the
652*ae771770SStanislav Sedov * previous realm.
653*ae771770SStanislav Sedov *
654*ae771770SStanislav Sedov * @param context A Kerberos context.
655*ae771770SStanislav Sedov * @param principal principal set the realm for
656*ae771770SStanislav Sedov * @param realm the new realm to set
657*ae771770SStanislav Sedov *
658*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
659*ae771770SStanislav Sedov *
660*ae771770SStanislav Sedov * @ingroup krb5_principal
661*ae771770SStanislav Sedov */
662b528cefcSMark Murray
663*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_principal_set_realm(krb5_context context,krb5_principal principal,krb5_const_realm realm)664*ae771770SStanislav Sedov krb5_principal_set_realm(krb5_context context,
665b528cefcSMark Murray krb5_principal principal,
666*ae771770SStanislav Sedov krb5_const_realm realm)
667b528cefcSMark Murray {
668*ae771770SStanislav Sedov if (princ_realm(principal))
669*ae771770SStanislav Sedov free(princ_realm(principal));
670*ae771770SStanislav Sedov
671*ae771770SStanislav Sedov princ_realm(principal) = strdup(realm);
672*ae771770SStanislav Sedov if (princ_realm(principal) == NULL) {
673*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
674*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
675*ae771770SStanislav Sedov return ENOMEM;
676*ae771770SStanislav Sedov }
677*ae771770SStanislav Sedov return 0;
678b528cefcSMark Murray }
679b528cefcSMark Murray
680*ae771770SStanislav Sedov #ifndef HEIMDAL_SMALLER
681*ae771770SStanislav Sedov /**
682*ae771770SStanislav Sedov * Build a principal using vararg style building
683*ae771770SStanislav Sedov *
684*ae771770SStanislav Sedov * @param context A Kerberos context.
685*ae771770SStanislav Sedov * @param principal returned principal
686*ae771770SStanislav Sedov * @param rlen length of realm
687*ae771770SStanislav Sedov * @param realm realm name
688*ae771770SStanislav Sedov * @param ... a list of components ended with NULL.
689*ae771770SStanislav Sedov *
690*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
691*ae771770SStanislav Sedov *
692*ae771770SStanislav Sedov * @ingroup krb5_principal
693*ae771770SStanislav Sedov */
694b528cefcSMark Murray
695*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_build_principal(krb5_context context,krb5_principal * principal,int rlen,krb5_const_realm realm,...)696b528cefcSMark Murray krb5_build_principal(krb5_context context,
697b528cefcSMark Murray krb5_principal *principal,
698b528cefcSMark Murray int rlen,
699b528cefcSMark Murray krb5_const_realm realm,
700b528cefcSMark Murray ...)
701b528cefcSMark Murray {
702b528cefcSMark Murray krb5_error_code ret;
703b528cefcSMark Murray va_list ap;
704b528cefcSMark Murray va_start(ap, realm);
705b528cefcSMark Murray ret = krb5_build_principal_va(context, principal, rlen, realm, ap);
706b528cefcSMark Murray va_end(ap);
707b528cefcSMark Murray return ret;
708b528cefcSMark Murray }
709*ae771770SStanislav Sedov #endif
710*ae771770SStanislav Sedov
711*ae771770SStanislav Sedov /**
712*ae771770SStanislav Sedov * Build a principal using vararg style building
713*ae771770SStanislav Sedov *
714*ae771770SStanislav Sedov * @param context A Kerberos context.
715*ae771770SStanislav Sedov * @param principal returned principal
716*ae771770SStanislav Sedov * @param realm realm name
717*ae771770SStanislav Sedov * @param ... a list of components ended with NULL.
718*ae771770SStanislav Sedov *
719*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
720*ae771770SStanislav Sedov *
721*ae771770SStanislav Sedov * @ingroup krb5_principal
722*ae771770SStanislav Sedov */
723*ae771770SStanislav Sedov
724*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_make_principal(krb5_context context,krb5_principal * principal,krb5_const_realm realm,...)725*ae771770SStanislav Sedov krb5_make_principal(krb5_context context,
726*ae771770SStanislav Sedov krb5_principal *principal,
727*ae771770SStanislav Sedov krb5_const_realm realm,
728*ae771770SStanislav Sedov ...)
729*ae771770SStanislav Sedov {
730*ae771770SStanislav Sedov krb5_error_code ret;
731*ae771770SStanislav Sedov krb5_realm r = NULL;
732*ae771770SStanislav Sedov va_list ap;
733*ae771770SStanislav Sedov if(realm == NULL) {
734*ae771770SStanislav Sedov ret = krb5_get_default_realm(context, &r);
735*ae771770SStanislav Sedov if(ret)
736*ae771770SStanislav Sedov return ret;
737*ae771770SStanislav Sedov realm = r;
738*ae771770SStanislav Sedov }
739*ae771770SStanislav Sedov va_start(ap, realm);
740*ae771770SStanislav Sedov ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
741*ae771770SStanislav Sedov va_end(ap);
742*ae771770SStanislav Sedov if(r)
743*ae771770SStanislav Sedov free(r);
744*ae771770SStanislav Sedov return ret;
745*ae771770SStanislav Sedov }
746b528cefcSMark Murray
747b528cefcSMark Murray static krb5_error_code
append_component(krb5_context context,krb5_principal p,const char * comp,size_t comp_len)748b528cefcSMark Murray append_component(krb5_context context, krb5_principal p,
74913e3f4d6SMark Murray const char *comp,
750b528cefcSMark Murray size_t comp_len)
751b528cefcSMark Murray {
752c19800e8SDoug Rabson heim_general_string *tmp;
753b528cefcSMark Murray size_t len = princ_num_comp(p);
75413e3f4d6SMark Murray
755b528cefcSMark Murray tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp));
756adb0ddaeSAssar Westerlund if(tmp == NULL) {
757*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
758*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
759b528cefcSMark Murray return ENOMEM;
760adb0ddaeSAssar Westerlund }
761b528cefcSMark Murray princ_comp(p) = tmp;
762b528cefcSMark Murray princ_ncomp(p, len) = malloc(comp_len + 1);
763adb0ddaeSAssar Westerlund if (princ_ncomp(p, len) == NULL) {
764*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
765*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
76613e3f4d6SMark Murray return ENOMEM;
767adb0ddaeSAssar Westerlund }
768b528cefcSMark Murray memcpy (princ_ncomp(p, len), comp, comp_len);
769b528cefcSMark Murray princ_ncomp(p, len)[comp_len] = '\0';
770b528cefcSMark Murray princ_num_comp(p)++;
771b528cefcSMark Murray return 0;
772b528cefcSMark Murray }
773b528cefcSMark Murray
774b528cefcSMark Murray static void
va_ext_princ(krb5_context context,krb5_principal p,va_list ap)775b528cefcSMark Murray va_ext_princ(krb5_context context, krb5_principal p, va_list ap)
776b528cefcSMark Murray {
777b528cefcSMark Murray while(1){
77813e3f4d6SMark Murray const char *s;
779b528cefcSMark Murray int len;
780b528cefcSMark Murray len = va_arg(ap, int);
781b528cefcSMark Murray if(len == 0)
782b528cefcSMark Murray break;
78313e3f4d6SMark Murray s = va_arg(ap, const char*);
784b528cefcSMark Murray append_component(context, p, s, len);
785b528cefcSMark Murray }
786b528cefcSMark Murray }
787b528cefcSMark Murray
788b528cefcSMark Murray static void
va_princ(krb5_context context,krb5_principal p,va_list ap)789b528cefcSMark Murray va_princ(krb5_context context, krb5_principal p, va_list ap)
790b528cefcSMark Murray {
791b528cefcSMark Murray while(1){
79213e3f4d6SMark Murray const char *s;
79313e3f4d6SMark Murray s = va_arg(ap, const char*);
794b528cefcSMark Murray if(s == NULL)
795b528cefcSMark Murray break;
796b528cefcSMark Murray append_component(context, p, s, strlen(s));
797b528cefcSMark Murray }
798b528cefcSMark Murray }
799b528cefcSMark Murray
800b528cefcSMark Murray static krb5_error_code
build_principal(krb5_context context,krb5_principal * principal,int rlen,krb5_const_realm realm,void (* func)(krb5_context,krb5_principal,va_list),va_list ap)801b528cefcSMark Murray build_principal(krb5_context context,
802b528cefcSMark Murray krb5_principal *principal,
803b528cefcSMark Murray int rlen,
804b528cefcSMark Murray krb5_const_realm realm,
805b528cefcSMark Murray void (*func)(krb5_context, krb5_principal, va_list),
806b528cefcSMark Murray va_list ap)
807b528cefcSMark Murray {
808b528cefcSMark Murray krb5_principal p;
809b528cefcSMark Murray
810b528cefcSMark Murray p = calloc(1, sizeof(*p));
811adb0ddaeSAssar Westerlund if (p == NULL) {
812*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
813*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
814b528cefcSMark Murray return ENOMEM;
815adb0ddaeSAssar Westerlund }
816b528cefcSMark Murray princ_type(p) = KRB5_NT_PRINCIPAL;
817b528cefcSMark Murray
818b528cefcSMark Murray princ_realm(p) = strdup(realm);
819b528cefcSMark Murray if(p->realm == NULL){
820b528cefcSMark Murray free(p);
821*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
822*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
823b528cefcSMark Murray return ENOMEM;
824b528cefcSMark Murray }
825b528cefcSMark Murray
826b528cefcSMark Murray (*func)(context, p, ap);
827b528cefcSMark Murray *principal = p;
828b528cefcSMark Murray return 0;
829b528cefcSMark Murray }
830b528cefcSMark Murray
831*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_build_principal_va(krb5_context context,krb5_principal * principal,int rlen,krb5_const_realm realm,va_list ap)832b528cefcSMark Murray krb5_build_principal_va(krb5_context context,
833b528cefcSMark Murray krb5_principal *principal,
834b528cefcSMark Murray int rlen,
835b528cefcSMark Murray krb5_const_realm realm,
836b528cefcSMark Murray va_list ap)
837b528cefcSMark Murray {
838b528cefcSMark Murray return build_principal(context, principal, rlen, realm, va_princ, ap);
839b528cefcSMark Murray }
840b528cefcSMark Murray
841*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_build_principal_va_ext(krb5_context context,krb5_principal * principal,int rlen,krb5_const_realm realm,va_list ap)842b528cefcSMark Murray krb5_build_principal_va_ext(krb5_context context,
843b528cefcSMark Murray krb5_principal *principal,
844b528cefcSMark Murray int rlen,
845b528cefcSMark Murray krb5_const_realm realm,
846b528cefcSMark Murray va_list ap)
847b528cefcSMark Murray {
848b528cefcSMark Murray return build_principal(context, principal, rlen, realm, va_ext_princ, ap);
849b528cefcSMark Murray }
850b528cefcSMark Murray
851b528cefcSMark Murray
852*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_build_principal_ext(krb5_context context,krb5_principal * principal,int rlen,krb5_const_realm realm,...)853b528cefcSMark Murray krb5_build_principal_ext(krb5_context context,
854b528cefcSMark Murray krb5_principal *principal,
855b528cefcSMark Murray int rlen,
856b528cefcSMark Murray krb5_const_realm realm,
857b528cefcSMark Murray ...)
858b528cefcSMark Murray {
859b528cefcSMark Murray krb5_error_code ret;
860b528cefcSMark Murray va_list ap;
861b528cefcSMark Murray va_start(ap, realm);
862b528cefcSMark Murray ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap);
863b528cefcSMark Murray va_end(ap);
864b528cefcSMark Murray return ret;
865b528cefcSMark Murray }
866b528cefcSMark Murray
867*ae771770SStanislav Sedov /**
868*ae771770SStanislav Sedov * Copy a principal
869*ae771770SStanislav Sedov *
870*ae771770SStanislav Sedov * @param context A Kerberos context.
871*ae771770SStanislav Sedov * @param inprinc principal to copy
872*ae771770SStanislav Sedov * @param outprinc copied principal, free with krb5_free_principal()
873*ae771770SStanislav Sedov *
874*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
875*ae771770SStanislav Sedov *
876*ae771770SStanislav Sedov * @ingroup krb5_principal
877*ae771770SStanislav Sedov */
878b528cefcSMark Murray
879*ae771770SStanislav Sedov
880*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_copy_principal(krb5_context context,krb5_const_principal inprinc,krb5_principal * outprinc)881b528cefcSMark Murray krb5_copy_principal(krb5_context context,
882b528cefcSMark Murray krb5_const_principal inprinc,
883b528cefcSMark Murray krb5_principal *outprinc)
884b528cefcSMark Murray {
885b528cefcSMark Murray krb5_principal p = malloc(sizeof(*p));
886adb0ddaeSAssar Westerlund if (p == NULL) {
887*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
888*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
889b528cefcSMark Murray return ENOMEM;
890adb0ddaeSAssar Westerlund }
891adb0ddaeSAssar Westerlund if(copy_Principal(inprinc, p)) {
892adb0ddaeSAssar Westerlund free(p);
893*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM,
894*ae771770SStanislav Sedov N_("malloc: out of memory", ""));
895b528cefcSMark Murray return ENOMEM;
896adb0ddaeSAssar Westerlund }
897b528cefcSMark Murray *outprinc = p;
898b528cefcSMark Murray return 0;
899b528cefcSMark Murray }
900b528cefcSMark Murray
901*ae771770SStanislav Sedov /**
902*ae771770SStanislav Sedov * Return TRUE iff princ1 == princ2 (without considering the realm)
903*ae771770SStanislav Sedov *
904*ae771770SStanislav Sedov * @param context Kerberos 5 context
905*ae771770SStanislav Sedov * @param princ1 first principal to compare
906*ae771770SStanislav Sedov * @param princ2 second principal to compare
907*ae771770SStanislav Sedov *
908*ae771770SStanislav Sedov * @return non zero if equal, 0 if not
909*ae771770SStanislav Sedov *
910*ae771770SStanislav Sedov * @ingroup krb5_principal
911*ae771770SStanislav Sedov * @see krb5_principal_compare()
912*ae771770SStanislav Sedov * @see krb5_realm_compare()
9135e9cd1aeSAssar Westerlund */
914b528cefcSMark Murray
915*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_principal_compare_any_realm(krb5_context context,krb5_const_principal princ1,krb5_const_principal princ2)916b528cefcSMark Murray krb5_principal_compare_any_realm(krb5_context context,
917b528cefcSMark Murray krb5_const_principal princ1,
918b528cefcSMark Murray krb5_const_principal princ2)
919b528cefcSMark Murray {
920*ae771770SStanislav Sedov size_t i;
921b528cefcSMark Murray if(princ_num_comp(princ1) != princ_num_comp(princ2))
922b528cefcSMark Murray return FALSE;
923b528cefcSMark Murray for(i = 0; i < princ_num_comp(princ1); i++){
924b528cefcSMark Murray if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0)
925b528cefcSMark Murray return FALSE;
926b528cefcSMark Murray }
927b528cefcSMark Murray return TRUE;
928b528cefcSMark Murray }
929b528cefcSMark Murray
930*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
_krb5_principal_compare_PrincipalName(krb5_context context,krb5_const_principal princ1,PrincipalName * princ2)931*ae771770SStanislav Sedov _krb5_principal_compare_PrincipalName(krb5_context context,
932*ae771770SStanislav Sedov krb5_const_principal princ1,
933*ae771770SStanislav Sedov PrincipalName *princ2)
934*ae771770SStanislav Sedov {
935*ae771770SStanislav Sedov size_t i;
936*ae771770SStanislav Sedov if (princ_num_comp(princ1) != princ2->name_string.len)
937*ae771770SStanislav Sedov return FALSE;
938*ae771770SStanislav Sedov for(i = 0; i < princ_num_comp(princ1); i++){
939*ae771770SStanislav Sedov if(strcmp(princ_ncomp(princ1, i), princ2->name_string.val[i]) != 0)
940*ae771770SStanislav Sedov return FALSE;
941*ae771770SStanislav Sedov }
942*ae771770SStanislav Sedov return TRUE;
943*ae771770SStanislav Sedov }
944*ae771770SStanislav Sedov
945*ae771770SStanislav Sedov
946*ae771770SStanislav Sedov /**
947*ae771770SStanislav Sedov * Compares the two principals, including realm of the principals and returns
948*ae771770SStanislav Sedov * TRUE if they are the same and FALSE if not.
949*ae771770SStanislav Sedov *
950*ae771770SStanislav Sedov * @param context Kerberos 5 context
951*ae771770SStanislav Sedov * @param princ1 first principal to compare
952*ae771770SStanislav Sedov * @param princ2 second principal to compare
953*ae771770SStanislav Sedov *
954*ae771770SStanislav Sedov * @ingroup krb5_principal
955*ae771770SStanislav Sedov * @see krb5_principal_compare_any_realm()
956*ae771770SStanislav Sedov * @see krb5_realm_compare()
957*ae771770SStanislav Sedov */
958*ae771770SStanislav Sedov
9595e9cd1aeSAssar Westerlund /*
9605e9cd1aeSAssar Westerlund * return TRUE iff princ1 == princ2
9615e9cd1aeSAssar Westerlund */
9625e9cd1aeSAssar Westerlund
963*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_principal_compare(krb5_context context,krb5_const_principal princ1,krb5_const_principal princ2)964b528cefcSMark Murray krb5_principal_compare(krb5_context context,
965b528cefcSMark Murray krb5_const_principal princ1,
966b528cefcSMark Murray krb5_const_principal princ2)
967b528cefcSMark Murray {
968b528cefcSMark Murray if(!krb5_realm_compare(context, princ1, princ2))
969b528cefcSMark Murray return FALSE;
970b528cefcSMark Murray return krb5_principal_compare_any_realm(context, princ1, princ2);
971b528cefcSMark Murray }
972b528cefcSMark Murray
973*ae771770SStanislav Sedov /**
9745e9cd1aeSAssar Westerlund * return TRUE iff realm(princ1) == realm(princ2)
975*ae771770SStanislav Sedov *
976*ae771770SStanislav Sedov * @param context Kerberos 5 context
977*ae771770SStanislav Sedov * @param princ1 first principal to compare
978*ae771770SStanislav Sedov * @param princ2 second principal to compare
979*ae771770SStanislav Sedov *
980*ae771770SStanislav Sedov * @ingroup krb5_principal
981*ae771770SStanislav Sedov * @see krb5_principal_compare_any_realm()
982*ae771770SStanislav Sedov * @see krb5_principal_compare()
9835e9cd1aeSAssar Westerlund */
984b528cefcSMark Murray
985*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_realm_compare(krb5_context context,krb5_const_principal princ1,krb5_const_principal princ2)986b528cefcSMark Murray krb5_realm_compare(krb5_context context,
987b528cefcSMark Murray krb5_const_principal princ1,
988b528cefcSMark Murray krb5_const_principal princ2)
989b528cefcSMark Murray {
990b528cefcSMark Murray return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0;
991b528cefcSMark Murray }
992b528cefcSMark Murray
993*ae771770SStanislav Sedov /**
9945e9cd1aeSAssar Westerlund * return TRUE iff princ matches pattern
995*ae771770SStanislav Sedov *
996*ae771770SStanislav Sedov * @ingroup krb5_principal
9975e9cd1aeSAssar Westerlund */
9985e9cd1aeSAssar Westerlund
999*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_principal_match(krb5_context context,krb5_const_principal princ,krb5_const_principal pattern)10005e9cd1aeSAssar Westerlund krb5_principal_match(krb5_context context,
10015e9cd1aeSAssar Westerlund krb5_const_principal princ,
10025e9cd1aeSAssar Westerlund krb5_const_principal pattern)
10035e9cd1aeSAssar Westerlund {
1004*ae771770SStanislav Sedov size_t i;
10055e9cd1aeSAssar Westerlund if(princ_num_comp(princ) != princ_num_comp(pattern))
10065e9cd1aeSAssar Westerlund return FALSE;
10075e9cd1aeSAssar Westerlund if(fnmatch(princ_realm(pattern), princ_realm(princ), 0) != 0)
10085e9cd1aeSAssar Westerlund return FALSE;
10095e9cd1aeSAssar Westerlund for(i = 0; i < princ_num_comp(princ); i++){
10105e9cd1aeSAssar Westerlund if(fnmatch(princ_ncomp(pattern, i), princ_ncomp(princ, i), 0) != 0)
10115e9cd1aeSAssar Westerlund return FALSE;
10125e9cd1aeSAssar Westerlund }
10135e9cd1aeSAssar Westerlund return TRUE;
10145e9cd1aeSAssar Westerlund }
10155e9cd1aeSAssar Westerlund
1016*ae771770SStanislav Sedov /**
1017*ae771770SStanislav Sedov * Create a principal for the service running on hostname. If
1018*ae771770SStanislav Sedov * KRB5_NT_SRV_HST is used, the hostname is canonization using DNS (or
1019*ae771770SStanislav Sedov * some other service), this is potentially insecure.
1020*ae771770SStanislav Sedov *
1021*ae771770SStanislav Sedov * @param context A Kerberos context.
1022*ae771770SStanislav Sedov * @param hostname hostname to use
1023*ae771770SStanislav Sedov * @param sname Service name to use
1024*ae771770SStanislav Sedov * @param type name type of pricipal, use KRB5_NT_SRV_HST or KRB5_NT_UNKNOWN.
1025*ae771770SStanislav Sedov * @param ret_princ return principal, free with krb5_free_principal().
1026*ae771770SStanislav Sedov *
1027*ae771770SStanislav Sedov * @return An krb5 error code, see krb5_get_error_message().
1028*ae771770SStanislav Sedov *
1029*ae771770SStanislav Sedov * @ingroup krb5_principal
10305e9cd1aeSAssar Westerlund */
10315e9cd1aeSAssar Westerlund
1032*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_sname_to_principal(krb5_context context,const char * hostname,const char * sname,int32_t type,krb5_principal * ret_princ)1033b528cefcSMark Murray krb5_sname_to_principal (krb5_context context,
1034b528cefcSMark Murray const char *hostname,
1035b528cefcSMark Murray const char *sname,
1036b528cefcSMark Murray int32_t type,
1037b528cefcSMark Murray krb5_principal *ret_princ)
1038b528cefcSMark Murray {
1039b528cefcSMark Murray krb5_error_code ret;
10405e9cd1aeSAssar Westerlund char localhost[MAXHOSTNAMELEN];
1041b528cefcSMark Murray char **realms, *host = NULL;
1042b528cefcSMark Murray
1043adb0ddaeSAssar Westerlund if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) {
1044*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_SNAME_UNSUPP_NAMETYPE,
1045*ae771770SStanislav Sedov N_("unsupported name type %d", ""),
1046*ae771770SStanislav Sedov (int)type);
1047b528cefcSMark Murray return KRB5_SNAME_UNSUPP_NAMETYPE;
1048adb0ddaeSAssar Westerlund }
1049b528cefcSMark Murray if(hostname == NULL) {
1050*ae771770SStanislav Sedov ret = gethostname(localhost, sizeof(localhost) - 1);
1051*ae771770SStanislav Sedov if (ret != 0) {
1052*ae771770SStanislav Sedov ret = errno;
1053*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
1054*ae771770SStanislav Sedov N_("Failed to get local hostname", ""));
1055*ae771770SStanislav Sedov return ret;
1056*ae771770SStanislav Sedov }
1057*ae771770SStanislav Sedov localhost[sizeof(localhost) - 1] = '\0';
1058b528cefcSMark Murray hostname = localhost;
1059b528cefcSMark Murray }
1060b528cefcSMark Murray if(sname == NULL)
1061b528cefcSMark Murray sname = "host";
1062b528cefcSMark Murray if(type == KRB5_NT_SRV_HST) {
106313e3f4d6SMark Murray ret = krb5_expand_hostname_realms (context, hostname,
106413e3f4d6SMark Murray &host, &realms);
1065b528cefcSMark Murray if (ret)
1066b528cefcSMark Murray return ret;
1067b528cefcSMark Murray strlwr(host);
1068b528cefcSMark Murray hostname = host;
106913e3f4d6SMark Murray } else {
1070b528cefcSMark Murray ret = krb5_get_host_realm(context, hostname, &realms);
1071b528cefcSMark Murray if(ret)
1072b528cefcSMark Murray return ret;
107313e3f4d6SMark Murray }
1074b528cefcSMark Murray
1075b528cefcSMark Murray ret = krb5_make_principal(context, ret_princ, realms[0], sname,
1076b528cefcSMark Murray hostname, NULL);
1077b528cefcSMark Murray if(host)
1078b528cefcSMark Murray free(host);
1079b528cefcSMark Murray krb5_free_host_realm(context, realms);
1080b528cefcSMark Murray return ret;
1081b528cefcSMark Murray }
1082c19800e8SDoug Rabson
1083c19800e8SDoug Rabson static const struct {
1084c19800e8SDoug Rabson const char *type;
1085c19800e8SDoug Rabson int32_t value;
1086c19800e8SDoug Rabson } nametypes[] = {
1087c19800e8SDoug Rabson { "UNKNOWN", KRB5_NT_UNKNOWN },
1088c19800e8SDoug Rabson { "PRINCIPAL", KRB5_NT_PRINCIPAL },
1089c19800e8SDoug Rabson { "SRV_INST", KRB5_NT_SRV_INST },
1090c19800e8SDoug Rabson { "SRV_HST", KRB5_NT_SRV_HST },
1091c19800e8SDoug Rabson { "SRV_XHST", KRB5_NT_SRV_XHST },
1092c19800e8SDoug Rabson { "UID", KRB5_NT_UID },
1093c19800e8SDoug Rabson { "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL },
1094c19800e8SDoug Rabson { "SMTP_NAME", KRB5_NT_SMTP_NAME },
1095c19800e8SDoug Rabson { "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL },
1096c19800e8SDoug Rabson { "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID },
1097c19800e8SDoug Rabson { "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL },
1098c19800e8SDoug Rabson { "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID },
1099*ae771770SStanislav Sedov { NULL, 0 }
1100c19800e8SDoug Rabson };
1101c19800e8SDoug Rabson
1102*ae771770SStanislav Sedov /**
1103*ae771770SStanislav Sedov * Parse nametype string and return a nametype integer
1104*ae771770SStanislav Sedov *
1105*ae771770SStanislav Sedov * @ingroup krb5_principal
1106*ae771770SStanislav Sedov */
1107*ae771770SStanislav Sedov
1108*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_parse_nametype(krb5_context context,const char * str,int32_t * nametype)1109c19800e8SDoug Rabson krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
1110c19800e8SDoug Rabson {
1111c19800e8SDoug Rabson size_t i;
1112c19800e8SDoug Rabson
1113c19800e8SDoug Rabson for(i = 0; nametypes[i].type; i++) {
1114c19800e8SDoug Rabson if (strcasecmp(nametypes[i].type, str) == 0) {
1115c19800e8SDoug Rabson *nametype = nametypes[i].value;
1116c19800e8SDoug Rabson return 0;
1117c19800e8SDoug Rabson }
1118c19800e8SDoug Rabson }
1119*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
1120*ae771770SStanislav Sedov N_("Failed to find name type %s", ""), str);
1121c19800e8SDoug Rabson return KRB5_PARSE_MALFORMED;
1122c19800e8SDoug Rabson }
1123*ae771770SStanislav Sedov
1124*ae771770SStanislav Sedov /**
1125*ae771770SStanislav Sedov * Check if the cname part of the principal is a krbtgt principal
1126*ae771770SStanislav Sedov *
1127*ae771770SStanislav Sedov * @ingroup krb5_principal
1128*ae771770SStanislav Sedov */
1129*ae771770SStanislav Sedov
1130*ae771770SStanislav Sedov KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_principal_is_krbtgt(krb5_context context,krb5_const_principal p)1131*ae771770SStanislav Sedov krb5_principal_is_krbtgt(krb5_context context, krb5_const_principal p)
1132*ae771770SStanislav Sedov {
1133*ae771770SStanislav Sedov return p->name.name_string.len == 2 &&
1134*ae771770SStanislav Sedov strcmp(p->name.name_string.val[0], KRB5_TGS_NAME) == 0;
1135*ae771770SStanislav Sedov
1136*ae771770SStanislav Sedov }
1137