155682Smarkm/*
2233294Sstas * Copyright (c) 1997-2007 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
2055682Smarkm *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
34233294Sstas/**
35233294Sstas * @page krb5_principal_intro The principal handing functions.
36233294Sstas *
37233294Sstas * A Kerberos principal is a email address looking string that
38233294Sstas * contains to parts separeted by a @.  The later part is the kerbero
39233294Sstas * realm the principal belongs to and the former is a list of 0 or
40233294Sstas * more components. For example
41233294Sstas * @verbatim
42233294Sstaslha@SU.SE
43233294Sstashost/hummel.it.su.se@SU.SE
44233294Sstashost/admin@H5L.ORG
45233294Sstas@endverbatim
46233294Sstas *
47233294Sstas * See the library functions here: @ref krb5_principal
48233294Sstas */
49233294Sstas
5055682Smarkm#include "krb5_locl.h"
5155682Smarkm#ifdef HAVE_RES_SEARCH
5255682Smarkm#define USE_RESOLVER
5355682Smarkm#endif
5455682Smarkm#ifdef HAVE_ARPA_NAMESER_H
5555682Smarkm#include <arpa/nameser.h>
5655682Smarkm#endif
5772445Sassar#include <fnmatch.h>
5855682Smarkm#include "resolve.h"
5955682Smarkm
6055682Smarkm#define princ_num_comp(P) ((P)->name.name_string.len)
6155682Smarkm#define princ_type(P) ((P)->name.name_type)
6255682Smarkm#define princ_comp(P) ((P)->name.name_string.val)
6355682Smarkm#define princ_ncomp(P, N) ((P)->name.name_string.val[(N)])
6455682Smarkm#define princ_realm(P) ((P)->realm)
6555682Smarkm
66233294Sstas/**
67233294Sstas * Frees a Kerberos principal allocated by the library with
68233294Sstas * krb5_parse_name(), krb5_make_principal() or any other related
69233294Sstas * principal functions.
70233294Sstas *
71233294Sstas * @param context A Kerberos context.
72233294Sstas * @param p a principal to free.
73233294Sstas *
74233294Sstas * @return An krb5 error code, see krb5_get_error_message().
75233294Sstas *
76233294Sstas * @ingroup krb5_principal
77233294Sstas */
78233294Sstas
79233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL
8055682Smarkmkrb5_free_principal(krb5_context context,
8155682Smarkm		    krb5_principal p)
8255682Smarkm{
8355682Smarkm    if(p){
8455682Smarkm	free_Principal(p);
8555682Smarkm	free(p);
8655682Smarkm    }
8755682Smarkm}
8855682Smarkm
89233294Sstas/**
90233294Sstas * Set the type of the principal
91233294Sstas *
92233294Sstas * @param context A Kerberos context.
93233294Sstas * @param principal principal to set the type for
94233294Sstas * @param type the new type
95233294Sstas *
96233294Sstas * @return An krb5 error code, see krb5_get_error_message().
97233294Sstas *
98233294Sstas * @ingroup krb5_principal
99233294Sstas */
100233294Sstas
101233294SstasKRB5_LIB_FUNCTION void KRB5_LIB_CALL
102178825Sdfrkrb5_principal_set_type(krb5_context context,
103178825Sdfr			krb5_principal principal,
104178825Sdfr			int type)
105178825Sdfr{
106178825Sdfr    princ_type(principal) = type;
107178825Sdfr}
108178825Sdfr
109233294Sstas/**
110233294Sstas * Get the type of the principal
111233294Sstas *
112233294Sstas * @param context A Kerberos context.
113233294Sstas * @param principal principal to get the type for
114233294Sstas *
115233294Sstas * @return the type of principal
116233294Sstas *
117233294Sstas * @ingroup krb5_principal
118233294Sstas */
119233294Sstas
120233294SstasKRB5_LIB_FUNCTION int KRB5_LIB_CALL
12190926Snectarkrb5_principal_get_type(krb5_context context,
122178825Sdfr			krb5_const_principal principal)
12390926Snectar{
12490926Snectar    return princ_type(principal);
12590926Snectar}
12690926Snectar
127233294Sstas/**
128233294Sstas * Get the realm of the principal
129233294Sstas *
130233294Sstas * @param context A Kerberos context.
131233294Sstas * @param principal principal to get the realm for
132233294Sstas *
133233294Sstas * @return realm of the principal, don't free or use after krb5_principal is freed
134233294Sstas *
135233294Sstas * @ingroup krb5_principal
136233294Sstas */
137233294Sstas
138233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
13990926Snectarkrb5_principal_get_realm(krb5_context context,
140178825Sdfr			 krb5_const_principal principal)
14190926Snectar{
14290926Snectar    return princ_realm(principal);
143233294Sstas}
14490926Snectar
145233294SstasKRB5_LIB_FUNCTION const char* KRB5_LIB_CALL
14690926Snectarkrb5_principal_get_comp_string(krb5_context context,
147178825Sdfr			       krb5_const_principal principal,
14890926Snectar			       unsigned int component)
14990926Snectar{
15090926Snectar    if(component >= princ_num_comp(principal))
15190926Snectar       return NULL;
15290926Snectar    return princ_ncomp(principal, component);
15390926Snectar}
15490926Snectar
155233294Sstas/**
156233294Sstas * Get number of component is principal.
157233294Sstas *
158233294Sstas * @param context Kerberos 5 context
159233294Sstas * @param principal principal to query
160233294Sstas *
161233294Sstas * @return number of components in string
162233294Sstas *
163233294Sstas * @ingroup krb5_principal
164233294Sstas */
165233294Sstas
166233294SstasKRB5_LIB_FUNCTION unsigned int KRB5_LIB_CALL
167233294Sstaskrb5_principal_get_num_comp(krb5_context context,
168233294Sstas			    krb5_const_principal principal)
169233294Sstas{
170233294Sstas    return princ_num_comp(principal);
171233294Sstas}
172233294Sstas
173233294Sstas/**
174233294Sstas * Parse a name into a krb5_principal structure, flags controls the behavior.
175233294Sstas *
176233294Sstas * @param context Kerberos 5 context
177233294Sstas * @param name name to parse into a Kerberos principal
178233294Sstas * @param flags flags to control the behavior
179233294Sstas * @param principal returned principal, free with krb5_free_principal().
180233294Sstas *
181233294Sstas * @return An krb5 error code, see krb5_get_error_message().
182233294Sstas *
183233294Sstas * @ingroup krb5_principal
184233294Sstas */
185233294Sstas
186233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
187178825Sdfrkrb5_parse_name_flags(krb5_context context,
188178825Sdfr		      const char *name,
189178825Sdfr		      int flags,
190178825Sdfr		      krb5_principal *principal)
19155682Smarkm{
19255682Smarkm    krb5_error_code ret;
193178825Sdfr    heim_general_string *comp;
194178825Sdfr    heim_general_string realm = NULL;
19555682Smarkm    int ncomp;
19655682Smarkm
197102644Snectar    const char *p;
19855682Smarkm    char *q;
19955682Smarkm    char *s;
20055682Smarkm    char *start;
20155682Smarkm
20255682Smarkm    int n;
20355682Smarkm    char c;
20455682Smarkm    int got_realm = 0;
205178825Sdfr    int first_at = 1;
206178825Sdfr    int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE);
207233294Sstas
208178825Sdfr    *principal = NULL;
209178825Sdfr
210233294Sstas#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_REQUIRE_REALM)
211178825Sdfr
212178825Sdfr    if ((flags & RFLAGS) == RFLAGS) {
213233294Sstas	krb5_set_error_message(context, KRB5_ERR_NO_SERVICE,
214233294Sstas			       N_("Can't require both realm and "
215233294Sstas				  "no realm at the same time", ""));
216178825Sdfr	return KRB5_ERR_NO_SERVICE;
217178825Sdfr    }
218178825Sdfr#undef RFLAGS
219178825Sdfr
220178825Sdfr    /* count number of component,
221178825Sdfr     * enterprise names only have one component
222178825Sdfr     */
22355682Smarkm    ncomp = 1;
224178825Sdfr    if (!enterprise) {
225178825Sdfr	for(p = name; *p; p++){
226178825Sdfr	    if(*p=='\\'){
227178825Sdfr		if(!p[1]) {
228233294Sstas		    krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
229233294Sstas					   N_("trailing \\ in principal name", ""));
230178825Sdfr		    return KRB5_PARSE_MALFORMED;
231178825Sdfr		}
232178825Sdfr		p++;
233178825Sdfr	    } else if(*p == '/')
234178825Sdfr		ncomp++;
235178825Sdfr	    else if(*p == '@')
236178825Sdfr		break;
237178825Sdfr	}
23855682Smarkm    }
23955682Smarkm    comp = calloc(ncomp, sizeof(*comp));
24078527Sassar    if (comp == NULL) {
241233294Sstas	krb5_set_error_message(context, ENOMEM,
242233294Sstas			       N_("malloc: out of memory", ""));
24355682Smarkm	return ENOMEM;
24478527Sassar    }
245233294Sstas
24655682Smarkm    n = 0;
247102644Snectar    p = start = q = s = strdup(name);
24855682Smarkm    if (start == NULL) {
24955682Smarkm	free (comp);
250233294Sstas	krb5_set_error_message(context, ENOMEM,
251233294Sstas			       N_("malloc: out of memory", ""));
25255682Smarkm	return ENOMEM;
25355682Smarkm    }
25455682Smarkm    while(*p){
25555682Smarkm	c = *p++;
25655682Smarkm	if(c == '\\'){
25755682Smarkm	    c = *p++;
25855682Smarkm	    if(c == 'n')
25955682Smarkm		c = '\n';
26055682Smarkm	    else if(c == 't')
26155682Smarkm		c = '\t';
26255682Smarkm	    else if(c == 'b')
26355682Smarkm		c = '\b';
26455682Smarkm	    else if(c == '0')
26555682Smarkm		c = '\0';
266107207Snectar	    else if(c == '\0') {
267107207Snectar		ret = KRB5_PARSE_MALFORMED;
268233294Sstas		krb5_set_error_message(context, ret,
269233294Sstas				       N_("trailing \\ in principal name", ""));
270107207Snectar		goto exit;
271107207Snectar	    }
272178825Sdfr	}else if(enterprise && first_at) {
273178825Sdfr	    if (c == '@')
274178825Sdfr		first_at = 0;
275178825Sdfr	}else if((c == '/' && !enterprise) || c == '@'){
27655682Smarkm	    if(got_realm){
27755682Smarkm		ret = KRB5_PARSE_MALFORMED;
278233294Sstas		krb5_set_error_message(context, ret,
279233294Sstas				       N_("part after realm in principal name", ""));
28055682Smarkm		goto exit;
28155682Smarkm	    }else{
28255682Smarkm		comp[n] = malloc(q - start + 1);
28355682Smarkm		if (comp[n] == NULL) {
28455682Smarkm		    ret = ENOMEM;
285233294Sstas		    krb5_set_error_message(context, ret,
286233294Sstas					   N_("malloc: out of memory", ""));
28755682Smarkm		    goto exit;
28855682Smarkm		}
28957416Smarkm		memcpy(comp[n], start, q - start);
29055682Smarkm		comp[n][q - start] = 0;
29155682Smarkm		n++;
29255682Smarkm	    }
29355682Smarkm	    if(c == '@')
29455682Smarkm		got_realm = 1;
29555682Smarkm	    start = q;
29655682Smarkm	    continue;
29755682Smarkm	}
298233294Sstas	if(got_realm && (c == '/' || c == '\0')) {
29955682Smarkm	    ret = KRB5_PARSE_MALFORMED;
300233294Sstas	    krb5_set_error_message(context, ret,
301233294Sstas				   N_("part after realm in principal name", ""));
30255682Smarkm	    goto exit;
30355682Smarkm	}
30455682Smarkm	*q++ = c;
30555682Smarkm    }
30655682Smarkm    if(got_realm){
307178825Sdfr	if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
308178825Sdfr	    ret = KRB5_PARSE_MALFORMED;
309233294Sstas	    krb5_set_error_message(context, ret,
310233294Sstas				   N_("realm found in 'short' principal "
311233294Sstas				      "expected to be without one", ""));
312178825Sdfr	    goto exit;
313178825Sdfr	}
31455682Smarkm	realm = malloc(q - start + 1);
31555682Smarkm	if (realm == NULL) {
31655682Smarkm	    ret = ENOMEM;
317233294Sstas	    krb5_set_error_message(context, ret,
318233294Sstas				   N_("malloc: out of memory", ""));
31955682Smarkm	    goto exit;
32055682Smarkm	}
32157416Smarkm	memcpy(realm, start, q - start);
32255682Smarkm	realm[q - start] = 0;
32355682Smarkm    }else{
324233294Sstas	if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) {
325178825Sdfr	    ret = KRB5_PARSE_MALFORMED;
326233294Sstas	    krb5_set_error_message(context, ret,
327233294Sstas				   N_("realm NOT found in principal "
328233294Sstas				      "expected to be with one", ""));
32955682Smarkm	    goto exit;
330178825Sdfr	} else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) {
331178825Sdfr	    realm = NULL;
332178825Sdfr	} else {
333178825Sdfr	    ret = krb5_get_default_realm (context, &realm);
334178825Sdfr	    if (ret)
335178825Sdfr		goto exit;
336178825Sdfr	}
33755682Smarkm
33855682Smarkm	comp[n] = malloc(q - start + 1);
33955682Smarkm	if (comp[n] == NULL) {
34055682Smarkm	    ret = ENOMEM;
341233294Sstas	    krb5_set_error_message(context, ret,
342233294Sstas				   N_("malloc: out of memory", ""));
34355682Smarkm	    goto exit;
34455682Smarkm	}
34557416Smarkm	memcpy(comp[n], start, q - start);
34655682Smarkm	comp[n][q - start] = 0;
34755682Smarkm	n++;
34855682Smarkm    }
34955682Smarkm    *principal = malloc(sizeof(**principal));
35055682Smarkm    if (*principal == NULL) {
35155682Smarkm	ret = ENOMEM;
352233294Sstas	krb5_set_error_message(context, ret,
353233294Sstas			       N_("malloc: out of memory", ""));
35455682Smarkm	goto exit;
35555682Smarkm    }
356178825Sdfr    if (enterprise)
357178825Sdfr	(*principal)->name.name_type = KRB5_NT_ENTERPRISE_PRINCIPAL;
358178825Sdfr    else
359178825Sdfr	(*principal)->name.name_type = KRB5_NT_PRINCIPAL;
36055682Smarkm    (*principal)->name.name_string.val = comp;
36155682Smarkm    princ_num_comp(*principal) = n;
36255682Smarkm    (*principal)->realm = realm;
36355682Smarkm    free(s);
36455682Smarkm    return 0;
36555682Smarkmexit:
36655682Smarkm    while(n>0){
36755682Smarkm	free(comp[--n]);
36855682Smarkm    }
36955682Smarkm    free(comp);
370178825Sdfr    free(realm);
37155682Smarkm    free(s);
37255682Smarkm    return ret;
37355682Smarkm}
37455682Smarkm
375233294Sstas/**
376233294Sstas * Parse a name into a krb5_principal structure
377233294Sstas *
378233294Sstas * @param context Kerberos 5 context
379233294Sstas * @param name name to parse into a Kerberos principal
380233294Sstas * @param principal returned principal, free with krb5_free_principal().
381233294Sstas *
382233294Sstas * @return An krb5 error code, see krb5_get_error_message().
383233294Sstas *
384233294Sstas * @ingroup krb5_principal
385233294Sstas */
386233294Sstas
387233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
388178825Sdfrkrb5_parse_name(krb5_context context,
389178825Sdfr		const char *name,
390178825Sdfr		krb5_principal *principal)
391178825Sdfr{
392178825Sdfr    return krb5_parse_name_flags(context, name, 0, principal);
393178825Sdfr}
394178825Sdfr
39557416Smarkmstatic const char quotable_chars[] = " \n\t\b\\/@";
39657416Smarkmstatic const char replace_chars[] = " ntb\\/@";
397178825Sdfrstatic const char nq_chars[] = "    \\/@";
39855682Smarkm
39955682Smarkm#define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0);
40055682Smarkm
40155682Smarkmstatic size_t
402178825Sdfrquote_string(const char *s, char *out, size_t idx, size_t len, int display)
40355682Smarkm{
40455682Smarkm    const char *p, *q;
405178825Sdfr    for(p = s; *p && idx < len; p++){
406178825Sdfr	q = strchr(quotable_chars, *p);
407178825Sdfr	if (q && display) {
408178825Sdfr	    add_char(out, idx, len, replace_chars[q - quotable_chars]);
409178825Sdfr	} else if (q) {
410178825Sdfr	    add_char(out, idx, len, '\\');
411178825Sdfr	    add_char(out, idx, len, replace_chars[q - quotable_chars]);
41255682Smarkm	}else
413178825Sdfr	    add_char(out, idx, len, *p);
41455682Smarkm    }
415178825Sdfr    if(idx < len)
416178825Sdfr	out[idx] = '\0';
417178825Sdfr    return idx;
41855682Smarkm}
41955682Smarkm
42055682Smarkm
42155682Smarkmstatic krb5_error_code
42255682Smarkmunparse_name_fixed(krb5_context context,
42355682Smarkm		   krb5_const_principal principal,
42455682Smarkm		   char *name,
42555682Smarkm		   size_t len,
426178825Sdfr		   int flags)
42755682Smarkm{
428178825Sdfr    size_t idx = 0;
429233294Sstas    size_t i;
430178825Sdfr    int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0;
431178825Sdfr    int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0;
432178825Sdfr    int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0;
433178825Sdfr
434178825Sdfr    if (!no_realm && princ_realm(principal) == NULL) {
435233294Sstas	krb5_set_error_message(context, ERANGE,
436233294Sstas			       N_("Realm missing from principal, "
437233294Sstas				  "can't unparse", ""));
438178825Sdfr	return ERANGE;
439178825Sdfr    }
440178825Sdfr
44155682Smarkm    for(i = 0; i < princ_num_comp(principal); i++){
44255682Smarkm	if(i)
443178825Sdfr	    add_char(name, idx, len, '/');
444178825Sdfr	idx = quote_string(princ_ncomp(principal, i), name, idx, len, display);
445178825Sdfr	if(idx == len) {
446233294Sstas	    krb5_set_error_message(context, ERANGE,
447233294Sstas				   N_("Out of space printing principal", ""));
44855682Smarkm	    return ERANGE;
449178825Sdfr	}
450233294Sstas    }
45155682Smarkm    /* add realm if different from default realm */
452178825Sdfr    if(short_form && !no_realm) {
45355682Smarkm	krb5_realm r;
45455682Smarkm	krb5_error_code ret;
45555682Smarkm	ret = krb5_get_default_realm(context, &r);
45655682Smarkm	if(ret)
45755682Smarkm	    return ret;
45855682Smarkm	if(strcmp(princ_realm(principal), r) != 0)
45955682Smarkm	    short_form = 0;
46055682Smarkm	free(r);
46155682Smarkm    }
462178825Sdfr    if(!short_form && !no_realm) {
463178825Sdfr	add_char(name, idx, len, '@');
464178825Sdfr	idx = quote_string(princ_realm(principal), name, idx, len, display);
465178825Sdfr	if(idx == len) {
466233294Sstas	    krb5_set_error_message(context, ERANGE,
467233294Sstas				   N_("Out of space printing "
468233294Sstas				      "realm of principal", ""));
46955682Smarkm	    return ERANGE;
470178825Sdfr	}
47155682Smarkm    }
47255682Smarkm    return 0;
47355682Smarkm}
47455682Smarkm
475233294Sstas/**
476233294Sstas * Unparse the principal name to a fixed buffer
477233294Sstas *
478233294Sstas * @param context A Kerberos context.
479233294Sstas * @param principal principal to unparse
480233294Sstas * @param name buffer to write name to
481233294Sstas * @param len length of buffer
482233294Sstas *
483233294Sstas * @return An krb5 error code, see krb5_get_error_message().
484233294Sstas *
485233294Sstas * @ingroup krb5_principal
486233294Sstas */
487233294Sstas
488233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
48955682Smarkmkrb5_unparse_name_fixed(krb5_context context,
49055682Smarkm			krb5_const_principal principal,
49155682Smarkm			char *name,
49255682Smarkm			size_t len)
49355682Smarkm{
494178825Sdfr    return unparse_name_fixed(context, principal, name, len, 0);
49555682Smarkm}
49655682Smarkm
497233294Sstas/**
498233294Sstas * Unparse the principal name to a fixed buffer. The realm is skipped
499233294Sstas * if its a default realm.
500233294Sstas *
501233294Sstas * @param context A Kerberos context.
502233294Sstas * @param principal principal to unparse
503233294Sstas * @param name buffer to write name to
504233294Sstas * @param len length of buffer
505233294Sstas *
506233294Sstas * @return An krb5 error code, see krb5_get_error_message().
507233294Sstas *
508233294Sstas * @ingroup krb5_principal
509233294Sstas */
510233294Sstas
511233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
51255682Smarkmkrb5_unparse_name_fixed_short(krb5_context context,
51355682Smarkm			      krb5_const_principal principal,
51455682Smarkm			      char *name,
51555682Smarkm			      size_t len)
51655682Smarkm{
517233294Sstas    return unparse_name_fixed(context, principal, name, len,
518178825Sdfr			      KRB5_PRINCIPAL_UNPARSE_SHORT);
51955682Smarkm}
52055682Smarkm
521233294Sstas/**
522233294Sstas * Unparse the principal name with unparse flags to a fixed buffer.
523233294Sstas *
524233294Sstas * @param context A Kerberos context.
525233294Sstas * @param principal principal to unparse
526233294Sstas * @param flags unparse flags
527233294Sstas * @param name buffer to write name to
528233294Sstas * @param len length of buffer
529233294Sstas *
530233294Sstas * @return An krb5 error code, see krb5_get_error_message().
531233294Sstas *
532233294Sstas * @ingroup krb5_principal
533233294Sstas */
534233294Sstas
535233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
536178825Sdfrkrb5_unparse_name_fixed_flags(krb5_context context,
537178825Sdfr			      krb5_const_principal principal,
538178825Sdfr			      int flags,
539178825Sdfr			      char *name,
540178825Sdfr			      size_t len)
541178825Sdfr{
542178825Sdfr    return unparse_name_fixed(context, principal, name, len, flags);
543178825Sdfr}
544178825Sdfr
54555682Smarkmstatic krb5_error_code
54655682Smarkmunparse_name(krb5_context context,
54755682Smarkm	     krb5_const_principal principal,
54855682Smarkm	     char **name,
549178825Sdfr	     int flags)
55055682Smarkm{
55155682Smarkm    size_t len = 0, plen;
552233294Sstas    size_t i;
55355682Smarkm    krb5_error_code ret;
55455682Smarkm    /* count length */
555178825Sdfr    if (princ_realm(principal)) {
556178825Sdfr	plen = strlen(princ_realm(principal));
557178825Sdfr
558178825Sdfr	if(strcspn(princ_realm(principal), quotable_chars) == plen)
559178825Sdfr	    len += plen;
560178825Sdfr	else
561178825Sdfr	    len += 2*plen;
562178825Sdfr	len++; /* '@' */
563178825Sdfr    }
56455682Smarkm    for(i = 0; i < princ_num_comp(principal); i++){
56555682Smarkm	plen = strlen(princ_ncomp(principal, i));
56655682Smarkm	if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen)
56755682Smarkm	    len += plen;
56855682Smarkm	else
56955682Smarkm	    len += 2*plen;
57055682Smarkm	len++;
57155682Smarkm    }
572178825Sdfr    len++; /* '\0' */
57355682Smarkm    *name = malloc(len);
574127808Snectar    if(*name == NULL) {
575233294Sstas	krb5_set_error_message(context, ENOMEM,
576233294Sstas			       N_("malloc: out of memory", ""));
57755682Smarkm	return ENOMEM;
57878527Sassar    }
579178825Sdfr    ret = unparse_name_fixed(context, principal, *name, len, flags);
580127808Snectar    if(ret) {
58155682Smarkm	free(*name);
582127808Snectar	*name = NULL;
583127808Snectar    }
58455682Smarkm    return ret;
58555682Smarkm}
58655682Smarkm
587233294Sstas/**
588233294Sstas * Unparse the Kerberos name into a string
589233294Sstas *
590233294Sstas * @param context Kerberos 5 context
591233294Sstas * @param principal principal to query
592233294Sstas * @param name resulting string, free with krb5_xfree()
593233294Sstas *
594233294Sstas * @return An krb5 error code, see krb5_get_error_message().
595233294Sstas *
596233294Sstas * @ingroup krb5_principal
597233294Sstas */
598233294Sstas
599233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
60055682Smarkmkrb5_unparse_name(krb5_context context,
60155682Smarkm		  krb5_const_principal principal,
60255682Smarkm		  char **name)
60355682Smarkm{
604178825Sdfr    return unparse_name(context, principal, name, 0);
60555682Smarkm}
60655682Smarkm
607233294Sstas/**
608233294Sstas * Unparse the Kerberos name into a string
609233294Sstas *
610233294Sstas * @param context Kerberos 5 context
611233294Sstas * @param principal principal to query
612233294Sstas * @param flags flag to determine the behavior
613233294Sstas * @param name resulting string, free with krb5_xfree()
614233294Sstas *
615233294Sstas * @return An krb5 error code, see krb5_get_error_message().
616233294Sstas *
617233294Sstas * @ingroup krb5_principal
618233294Sstas */
619233294Sstas
620233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
621178825Sdfrkrb5_unparse_name_flags(krb5_context context,
622178825Sdfr			krb5_const_principal principal,
623178825Sdfr			int flags,
624178825Sdfr			char **name)
625178825Sdfr{
626178825Sdfr    return unparse_name(context, principal, name, flags);
627178825Sdfr}
628178825Sdfr
629233294Sstas/**
630233294Sstas * Unparse the principal name to a allocated buffer. The realm is
631233294Sstas * skipped if its a default realm.
632233294Sstas *
633233294Sstas * @param context A Kerberos context.
634233294Sstas * @param principal principal to unparse
635233294Sstas * @param name returned buffer, free with krb5_xfree()
636233294Sstas *
637233294Sstas * @return An krb5 error code, see krb5_get_error_message().
638233294Sstas *
639233294Sstas * @ingroup krb5_principal
640233294Sstas */
641233294Sstas
642233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
64355682Smarkmkrb5_unparse_name_short(krb5_context context,
64455682Smarkm			krb5_const_principal principal,
64555682Smarkm			char **name)
64655682Smarkm{
647178825Sdfr    return unparse_name(context, principal, name, KRB5_PRINCIPAL_UNPARSE_SHORT);
64855682Smarkm}
64955682Smarkm
650233294Sstas/**
651233294Sstas * Set a new realm for a principal, and as a side-effect free the
652233294Sstas * previous realm.
653233294Sstas *
654233294Sstas * @param context A Kerberos context.
655233294Sstas * @param principal principal set the realm for
656233294Sstas * @param realm the new realm to set
657233294Sstas *
658233294Sstas * @return An krb5 error code, see krb5_get_error_message().
659233294Sstas *
660233294Sstas * @ingroup krb5_principal
661233294Sstas */
66255682Smarkm
663233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
664233294Sstaskrb5_principal_set_realm(krb5_context context,
665233294Sstas			 krb5_principal principal,
666233294Sstas			 krb5_const_realm realm)
66755682Smarkm{
668233294Sstas    if (princ_realm(principal))
669233294Sstas	free(princ_realm(principal));
67055682Smarkm
671233294Sstas    princ_realm(principal) = strdup(realm);
672233294Sstas    if (princ_realm(principal) == NULL) {
673233294Sstas	krb5_set_error_message(context, ENOMEM,
674233294Sstas			       N_("malloc: out of memory", ""));
675233294Sstas	return ENOMEM;
676233294Sstas    }
677233294Sstas    return 0;
67855682Smarkm}
67955682Smarkm
680233294Sstas#ifndef HEIMDAL_SMALLER
681233294Sstas/**
682233294Sstas * Build a principal using vararg style building
683233294Sstas *
684233294Sstas * @param context A Kerberos context.
685233294Sstas * @param principal returned principal
686233294Sstas * @param rlen length of realm
687233294Sstas * @param realm realm name
688233294Sstas * @param ... a list of components ended with NULL.
689233294Sstas *
690233294Sstas * @return An krb5 error code, see krb5_get_error_message().
691233294Sstas *
692233294Sstas * @ingroup krb5_principal
693233294Sstas */
69455682Smarkm
695233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
69655682Smarkmkrb5_build_principal(krb5_context context,
69755682Smarkm		     krb5_principal *principal,
69855682Smarkm		     int rlen,
69955682Smarkm		     krb5_const_realm realm,
70055682Smarkm		     ...)
70155682Smarkm{
70255682Smarkm    krb5_error_code ret;
70355682Smarkm    va_list ap;
70455682Smarkm    va_start(ap, realm);
70555682Smarkm    ret = krb5_build_principal_va(context, principal, rlen, realm, ap);
70655682Smarkm    va_end(ap);
70755682Smarkm    return ret;
70855682Smarkm}
709233294Sstas#endif
71055682Smarkm
711233294Sstas/**
712233294Sstas * Build a principal using vararg style building
713233294Sstas *
714233294Sstas * @param context A Kerberos context.
715233294Sstas * @param principal returned principal
716233294Sstas * @param realm realm name
717233294Sstas * @param ... a list of components ended with NULL.
718233294Sstas *
719233294Sstas * @return An krb5 error code, see krb5_get_error_message().
720233294Sstas *
721233294Sstas * @ingroup krb5_principal
722233294Sstas */
723233294Sstas
724233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
725233294Sstaskrb5_make_principal(krb5_context context,
726233294Sstas		    krb5_principal *principal,
727233294Sstas		    krb5_const_realm realm,
728233294Sstas		    ...)
729233294Sstas{
730233294Sstas    krb5_error_code ret;
731233294Sstas    krb5_realm r = NULL;
732233294Sstas    va_list ap;
733233294Sstas    if(realm == NULL) {
734233294Sstas	ret = krb5_get_default_realm(context, &r);
735233294Sstas	if(ret)
736233294Sstas	    return ret;
737233294Sstas	realm = r;
738233294Sstas    }
739233294Sstas    va_start(ap, realm);
740233294Sstas    ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
741233294Sstas    va_end(ap);
742233294Sstas    if(r)
743233294Sstas	free(r);
744233294Sstas    return ret;
745233294Sstas}
746233294Sstas
74755682Smarkmstatic krb5_error_code
748233294Sstasappend_component(krb5_context context, krb5_principal p,
74957416Smarkm		 const char *comp,
75055682Smarkm		 size_t comp_len)
75155682Smarkm{
752178825Sdfr    heim_general_string *tmp;
75355682Smarkm    size_t len = princ_num_comp(p);
75457416Smarkm
75555682Smarkm    tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp));
75678527Sassar    if(tmp == NULL) {
757233294Sstas	krb5_set_error_message(context, ENOMEM,
758233294Sstas			       N_("malloc: out of memory", ""));
75955682Smarkm	return ENOMEM;
76078527Sassar    }
76155682Smarkm    princ_comp(p) = tmp;
76255682Smarkm    princ_ncomp(p, len) = malloc(comp_len + 1);
76378527Sassar    if (princ_ncomp(p, len) == NULL) {
764233294Sstas	krb5_set_error_message(context, ENOMEM,
765233294Sstas			       N_("malloc: out of memory", ""));
76657416Smarkm	return ENOMEM;
76778527Sassar    }
76855682Smarkm    memcpy (princ_ncomp(p, len), comp, comp_len);
76955682Smarkm    princ_ncomp(p, len)[comp_len] = '\0';
77055682Smarkm    princ_num_comp(p)++;
77155682Smarkm    return 0;
77255682Smarkm}
77355682Smarkm
77455682Smarkmstatic void
77555682Smarkmva_ext_princ(krb5_context context, krb5_principal p, va_list ap)
77655682Smarkm{
77755682Smarkm    while(1){
77857416Smarkm	const char *s;
77955682Smarkm	int len;
78055682Smarkm	len = va_arg(ap, int);
78155682Smarkm	if(len == 0)
78255682Smarkm	    break;
78357416Smarkm	s = va_arg(ap, const char*);
78455682Smarkm	append_component(context, p, s, len);
78555682Smarkm    }
78655682Smarkm}
78755682Smarkm
78855682Smarkmstatic void
78955682Smarkmva_princ(krb5_context context, krb5_principal p, va_list ap)
79055682Smarkm{
79155682Smarkm    while(1){
79257416Smarkm	const char *s;
79357416Smarkm	s = va_arg(ap, const char*);
79455682Smarkm	if(s == NULL)
79555682Smarkm	    break;
79655682Smarkm	append_component(context, p, s, strlen(s));
79755682Smarkm    }
79855682Smarkm}
79955682Smarkm
80055682Smarkmstatic krb5_error_code
80155682Smarkmbuild_principal(krb5_context context,
80255682Smarkm		krb5_principal *principal,
80355682Smarkm		int rlen,
80455682Smarkm		krb5_const_realm realm,
80555682Smarkm		void (*func)(krb5_context, krb5_principal, va_list),
80655682Smarkm		va_list ap)
80755682Smarkm{
80855682Smarkm    krb5_principal p;
809233294Sstas
81055682Smarkm    p = calloc(1, sizeof(*p));
81178527Sassar    if (p == NULL) {
812233294Sstas	krb5_set_error_message(context, ENOMEM,
813233294Sstas			       N_("malloc: out of memory", ""));
81455682Smarkm	return ENOMEM;
81578527Sassar    }
81655682Smarkm    princ_type(p) = KRB5_NT_PRINCIPAL;
81755682Smarkm
81855682Smarkm    princ_realm(p) = strdup(realm);
81955682Smarkm    if(p->realm == NULL){
82055682Smarkm	free(p);
821233294Sstas	krb5_set_error_message(context, ENOMEM,
822233294Sstas			       N_("malloc: out of memory", ""));
82355682Smarkm	return ENOMEM;
82455682Smarkm    }
825233294Sstas
82655682Smarkm    (*func)(context, p, ap);
82755682Smarkm    *principal = p;
82855682Smarkm    return 0;
82955682Smarkm}
83055682Smarkm
831233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
832233294Sstaskrb5_build_principal_va(krb5_context context,
833233294Sstas			krb5_principal *principal,
83455682Smarkm			int rlen,
83555682Smarkm			krb5_const_realm realm,
83655682Smarkm			va_list ap)
83755682Smarkm{
83855682Smarkm    return build_principal(context, principal, rlen, realm, va_princ, ap);
83955682Smarkm}
84055682Smarkm
841233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
842233294Sstaskrb5_build_principal_va_ext(krb5_context context,
843233294Sstas			    krb5_principal *principal,
84455682Smarkm			    int rlen,
84555682Smarkm			    krb5_const_realm realm,
84655682Smarkm			    va_list ap)
84755682Smarkm{
84855682Smarkm    return build_principal(context, principal, rlen, realm, va_ext_princ, ap);
84955682Smarkm}
85055682Smarkm
85155682Smarkm
852233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
85355682Smarkmkrb5_build_principal_ext(krb5_context context,
85455682Smarkm			 krb5_principal *principal,
85555682Smarkm			 int rlen,
85655682Smarkm			 krb5_const_realm realm,
85755682Smarkm			 ...)
85855682Smarkm{
85955682Smarkm    krb5_error_code ret;
86055682Smarkm    va_list ap;
86155682Smarkm    va_start(ap, realm);
86255682Smarkm    ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap);
86355682Smarkm    va_end(ap);
86455682Smarkm    return ret;
86555682Smarkm}
86655682Smarkm
867233294Sstas/**
868233294Sstas * Copy a principal
869233294Sstas *
870233294Sstas * @param context A Kerberos context.
871233294Sstas * @param inprinc principal to copy
872233294Sstas * @param outprinc copied principal, free with krb5_free_principal()
873233294Sstas *
874233294Sstas * @return An krb5 error code, see krb5_get_error_message().
875233294Sstas *
876233294Sstas * @ingroup krb5_principal
877233294Sstas */
87855682Smarkm
879233294Sstas
880233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
88155682Smarkmkrb5_copy_principal(krb5_context context,
88255682Smarkm		    krb5_const_principal inprinc,
88355682Smarkm		    krb5_principal *outprinc)
88455682Smarkm{
88555682Smarkm    krb5_principal p = malloc(sizeof(*p));
88678527Sassar    if (p == NULL) {
887233294Sstas	krb5_set_error_message(context, ENOMEM,
888233294Sstas			       N_("malloc: out of memory", ""));
88955682Smarkm	return ENOMEM;
89078527Sassar    }
89178527Sassar    if(copy_Principal(inprinc, p)) {
89278527Sassar	free(p);
893233294Sstas	krb5_set_error_message(context, ENOMEM,
894233294Sstas			       N_("malloc: out of memory", ""));
89555682Smarkm	return ENOMEM;
89678527Sassar    }
89755682Smarkm    *outprinc = p;
89855682Smarkm    return 0;
89955682Smarkm}
90055682Smarkm
901233294Sstas/**
902233294Sstas * Return TRUE iff princ1 == princ2 (without considering the realm)
903233294Sstas *
904233294Sstas * @param context Kerberos 5 context
905233294Sstas * @param princ1 first principal to compare
906233294Sstas * @param princ2 second principal to compare
907233294Sstas *
908233294Sstas * @return non zero if equal, 0 if not
909233294Sstas *
910233294Sstas * @ingroup krb5_principal
911233294Sstas * @see krb5_principal_compare()
912233294Sstas * @see krb5_realm_compare()
91372445Sassar */
91455682Smarkm
915233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
91655682Smarkmkrb5_principal_compare_any_realm(krb5_context context,
91755682Smarkm				 krb5_const_principal princ1,
91855682Smarkm				 krb5_const_principal princ2)
91955682Smarkm{
920233294Sstas    size_t i;
92155682Smarkm    if(princ_num_comp(princ1) != princ_num_comp(princ2))
92255682Smarkm	return FALSE;
92355682Smarkm    for(i = 0; i < princ_num_comp(princ1); i++){
92455682Smarkm	if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0)
92555682Smarkm	    return FALSE;
92655682Smarkm    }
92755682Smarkm    return TRUE;
92855682Smarkm}
92955682Smarkm
930233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
931233294Sstas_krb5_principal_compare_PrincipalName(krb5_context context,
932233294Sstas				      krb5_const_principal princ1,
933233294Sstas				      PrincipalName *princ2)
934233294Sstas{
935233294Sstas    size_t i;
936233294Sstas    if (princ_num_comp(princ1) != princ2->name_string.len)
937233294Sstas	return FALSE;
938233294Sstas    for(i = 0; i < princ_num_comp(princ1); i++){
939233294Sstas	if(strcmp(princ_ncomp(princ1, i), princ2->name_string.val[i]) != 0)
940233294Sstas	    return FALSE;
941233294Sstas    }
942233294Sstas    return TRUE;
943233294Sstas}
944233294Sstas
945233294Sstas
946233294Sstas/**
947233294Sstas * Compares the two principals, including realm of the principals and returns
948233294Sstas * TRUE if they are the same and FALSE if not.
949233294Sstas *
950233294Sstas * @param context Kerberos 5 context
951233294Sstas * @param princ1 first principal to compare
952233294Sstas * @param princ2 second principal to compare
953233294Sstas *
954233294Sstas * @ingroup krb5_principal
955233294Sstas * @see krb5_principal_compare_any_realm()
956233294Sstas * @see krb5_realm_compare()
957233294Sstas */
958233294Sstas
95972445Sassar/*
96072445Sassar * return TRUE iff princ1 == princ2
96172445Sassar */
96272445Sassar
963233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
96455682Smarkmkrb5_principal_compare(krb5_context context,
96555682Smarkm		       krb5_const_principal princ1,
96655682Smarkm		       krb5_const_principal princ2)
96755682Smarkm{
96855682Smarkm    if(!krb5_realm_compare(context, princ1, princ2))
96955682Smarkm	return FALSE;
97055682Smarkm    return krb5_principal_compare_any_realm(context, princ1, princ2);
97155682Smarkm}
97255682Smarkm
973233294Sstas/**
97472445Sassar * return TRUE iff realm(princ1) == realm(princ2)
975233294Sstas *
976233294Sstas * @param context Kerberos 5 context
977233294Sstas * @param princ1 first principal to compare
978233294Sstas * @param princ2 second principal to compare
979233294Sstas *
980233294Sstas * @ingroup krb5_principal
981233294Sstas * @see krb5_principal_compare_any_realm()
982233294Sstas * @see krb5_principal_compare()
98372445Sassar */
98455682Smarkm
985233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
98655682Smarkmkrb5_realm_compare(krb5_context context,
98755682Smarkm		   krb5_const_principal princ1,
98855682Smarkm		   krb5_const_principal princ2)
98955682Smarkm{
99055682Smarkm    return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0;
99155682Smarkm}
99255682Smarkm
993233294Sstas/**
99472445Sassar * return TRUE iff princ matches pattern
995233294Sstas *
996233294Sstas * @ingroup krb5_principal
99772445Sassar */
99872445Sassar
999233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
100072445Sassarkrb5_principal_match(krb5_context context,
100172445Sassar		     krb5_const_principal princ,
100272445Sassar		     krb5_const_principal pattern)
100372445Sassar{
1004233294Sstas    size_t i;
100572445Sassar    if(princ_num_comp(princ) != princ_num_comp(pattern))
100672445Sassar	return FALSE;
100772445Sassar    if(fnmatch(princ_realm(pattern), princ_realm(princ), 0) != 0)
100872445Sassar	return FALSE;
100972445Sassar    for(i = 0; i < princ_num_comp(princ); i++){
101072445Sassar	if(fnmatch(princ_ncomp(pattern, i), princ_ncomp(princ, i), 0) != 0)
101172445Sassar	    return FALSE;
101272445Sassar    }
101372445Sassar    return TRUE;
101472445Sassar}
101572445Sassar
1016233294Sstas/**
1017233294Sstas * Create a principal for the service running on hostname. If
1018233294Sstas * KRB5_NT_SRV_HST is used, the hostname is canonization using DNS (or
1019233294Sstas * some other service), this is potentially insecure.
1020233294Sstas *
1021233294Sstas * @param context A Kerberos context.
1022233294Sstas * @param hostname hostname to use
1023233294Sstas * @param sname Service name to use
1024233294Sstas * @param type name type of pricipal, use KRB5_NT_SRV_HST or KRB5_NT_UNKNOWN.
1025233294Sstas * @param ret_princ return principal, free with krb5_free_principal().
1026233294Sstas *
1027233294Sstas * @return An krb5 error code, see krb5_get_error_message().
1028233294Sstas *
1029233294Sstas * @ingroup krb5_principal
103072445Sassar */
103172445Sassar
1032233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
103355682Smarkmkrb5_sname_to_principal (krb5_context context,
103455682Smarkm			 const char *hostname,
103555682Smarkm			 const char *sname,
103655682Smarkm			 int32_t type,
103755682Smarkm			 krb5_principal *ret_princ)
103855682Smarkm{
103955682Smarkm    krb5_error_code ret;
104072445Sassar    char localhost[MAXHOSTNAMELEN];
104155682Smarkm    char **realms, *host = NULL;
1042233294Sstas
104378527Sassar    if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) {
1044233294Sstas	krb5_set_error_message(context, KRB5_SNAME_UNSUPP_NAMETYPE,
1045233294Sstas			       N_("unsupported name type %d", ""),
1046233294Sstas			       (int)type);
104755682Smarkm	return KRB5_SNAME_UNSUPP_NAMETYPE;
104878527Sassar    }
104955682Smarkm    if(hostname == NULL) {
1050233294Sstas	ret = gethostname(localhost, sizeof(localhost) - 1);
1051233294Sstas	if (ret != 0) {
1052233294Sstas	    ret = errno;
1053233294Sstas	    krb5_set_error_message(context, ret,
1054233294Sstas				   N_("Failed to get local hostname", ""));
1055233294Sstas	    return ret;
1056233294Sstas	}
1057233294Sstas	localhost[sizeof(localhost) - 1] = '\0';
105855682Smarkm	hostname = localhost;
105955682Smarkm    }
106055682Smarkm    if(sname == NULL)
106155682Smarkm	sname = "host";
106255682Smarkm    if(type == KRB5_NT_SRV_HST) {
106357416Smarkm	ret = krb5_expand_hostname_realms (context, hostname,
106457416Smarkm					   &host, &realms);
106555682Smarkm	if (ret)
106655682Smarkm	    return ret;
106755682Smarkm	strlwr(host);
106855682Smarkm	hostname = host;
106957416Smarkm    } else {
107057416Smarkm	ret = krb5_get_host_realm(context, hostname, &realms);
107157416Smarkm	if(ret)
107257416Smarkm	    return ret;
107355682Smarkm    }
107455682Smarkm
107555682Smarkm    ret = krb5_make_principal(context, ret_princ, realms[0], sname,
107655682Smarkm			      hostname, NULL);
107755682Smarkm    if(host)
107855682Smarkm	free(host);
107955682Smarkm    krb5_free_host_realm(context, realms);
108055682Smarkm    return ret;
108155682Smarkm}
1082178825Sdfr
1083178825Sdfrstatic const struct {
1084178825Sdfr    const char *type;
1085178825Sdfr    int32_t value;
1086178825Sdfr} nametypes[] = {
1087178825Sdfr    { "UNKNOWN", KRB5_NT_UNKNOWN },
1088178825Sdfr    { "PRINCIPAL", KRB5_NT_PRINCIPAL },
1089178825Sdfr    { "SRV_INST", KRB5_NT_SRV_INST },
1090178825Sdfr    { "SRV_HST", KRB5_NT_SRV_HST },
1091178825Sdfr    { "SRV_XHST", KRB5_NT_SRV_XHST },
1092178825Sdfr    { "UID", KRB5_NT_UID },
1093178825Sdfr    { "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL },
1094178825Sdfr    { "SMTP_NAME", KRB5_NT_SMTP_NAME },
1095178825Sdfr    { "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL },
1096178825Sdfr    { "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID },
1097178825Sdfr    { "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL },
1098178825Sdfr    { "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID },
1099233294Sstas    { NULL, 0 }
1100178825Sdfr};
1101178825Sdfr
1102233294Sstas/**
1103233294Sstas * Parse nametype string and return a nametype integer
1104233294Sstas *
1105233294Sstas * @ingroup krb5_principal
1106233294Sstas */
1107233294Sstas
1108233294SstasKRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1109178825Sdfrkrb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
1110178825Sdfr{
1111178825Sdfr    size_t i;
1112233294Sstas
1113178825Sdfr    for(i = 0; nametypes[i].type; i++) {
1114178825Sdfr	if (strcasecmp(nametypes[i].type, str) == 0) {
1115178825Sdfr	    *nametype = nametypes[i].value;
1116178825Sdfr	    return 0;
1117178825Sdfr	}
1118178825Sdfr    }
1119233294Sstas    krb5_set_error_message(context, KRB5_PARSE_MALFORMED,
1120233294Sstas			   N_("Failed to find name type %s", ""), str);
1121178825Sdfr    return KRB5_PARSE_MALFORMED;
1122178825Sdfr}
1123233294Sstas
1124233294Sstas/**
1125233294Sstas * Check if the cname part of the principal is a krbtgt principal
1126233294Sstas *
1127233294Sstas * @ingroup krb5_principal
1128233294Sstas */
1129233294Sstas
1130233294SstasKRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
1131233294Sstaskrb5_principal_is_krbtgt(krb5_context context, krb5_const_principal p)
1132233294Sstas{
1133233294Sstas    return p->name.name_string.len == 2 &&
1134233294Sstas	strcmp(p->name.name_string.val[0], KRB5_TGS_NAME) == 0;
1135233294Sstas
1136233294Sstas}
1137