155682Smarkm/* 2178825Sdfr * Copyright (c) 1997-2007 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 3555682Smarkm#ifdef HAVE_RES_SEARCH 3655682Smarkm#define USE_RESOLVER 3755682Smarkm#endif 3855682Smarkm#ifdef HAVE_ARPA_NAMESER_H 3955682Smarkm#include <arpa/nameser.h> 4055682Smarkm#endif 4172445Sassar#include <fnmatch.h> 4255682Smarkm#include "resolve.h" 4355682Smarkm 44178825SdfrRCSID("$Id: principal.c 21741 2007-07-31 16:00:37Z lha $"); 4555682Smarkm 4655682Smarkm#define princ_num_comp(P) ((P)->name.name_string.len) 4755682Smarkm#define princ_type(P) ((P)->name.name_type) 4855682Smarkm#define princ_comp(P) ((P)->name.name_string.val) 4955682Smarkm#define princ_ncomp(P, N) ((P)->name.name_string.val[(N)]) 5055682Smarkm#define princ_realm(P) ((P)->realm) 5155682Smarkm 52178825Sdfrvoid KRB5_LIB_FUNCTION 5355682Smarkmkrb5_free_principal(krb5_context context, 5455682Smarkm krb5_principal p) 5555682Smarkm{ 5655682Smarkm if(p){ 5755682Smarkm free_Principal(p); 5855682Smarkm free(p); 5955682Smarkm } 6055682Smarkm} 6155682Smarkm 62178825Sdfrvoid KRB5_LIB_FUNCTION 63178825Sdfrkrb5_principal_set_type(krb5_context context, 64178825Sdfr krb5_principal principal, 65178825Sdfr int type) 66178825Sdfr{ 67178825Sdfr princ_type(principal) = type; 68178825Sdfr} 69178825Sdfr 70178825Sdfrint KRB5_LIB_FUNCTION 7190926Snectarkrb5_principal_get_type(krb5_context context, 72178825Sdfr krb5_const_principal principal) 7390926Snectar{ 7490926Snectar return princ_type(principal); 7590926Snectar} 7690926Snectar 77178825Sdfrconst char* KRB5_LIB_FUNCTION 7890926Snectarkrb5_principal_get_realm(krb5_context context, 79178825Sdfr krb5_const_principal principal) 8090926Snectar{ 8190926Snectar return princ_realm(principal); 8290926Snectar} 8390926Snectar 84178825Sdfrconst char* KRB5_LIB_FUNCTION 8590926Snectarkrb5_principal_get_comp_string(krb5_context context, 86178825Sdfr krb5_const_principal principal, 8790926Snectar unsigned int component) 8890926Snectar{ 8990926Snectar if(component >= princ_num_comp(principal)) 9090926Snectar return NULL; 9190926Snectar return princ_ncomp(principal, component); 9290926Snectar} 9390926Snectar 94178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 95178825Sdfrkrb5_parse_name_flags(krb5_context context, 96178825Sdfr const char *name, 97178825Sdfr int flags, 98178825Sdfr krb5_principal *principal) 9955682Smarkm{ 10055682Smarkm krb5_error_code ret; 101178825Sdfr heim_general_string *comp; 102178825Sdfr heim_general_string realm = NULL; 10355682Smarkm int ncomp; 10455682Smarkm 105102644Snectar const char *p; 10655682Smarkm char *q; 10755682Smarkm char *s; 10855682Smarkm char *start; 10955682Smarkm 11055682Smarkm int n; 11155682Smarkm char c; 11255682Smarkm int got_realm = 0; 113178825Sdfr int first_at = 1; 114178825Sdfr int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE); 11555682Smarkm 116178825Sdfr *principal = NULL; 117178825Sdfr 118178825Sdfr#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_MUST_REALM) 119178825Sdfr 120178825Sdfr if ((flags & RFLAGS) == RFLAGS) { 121178825Sdfr krb5_set_error_string(context, "Can't require both realm and " 122178825Sdfr "no realm at the same time"); 123178825Sdfr return KRB5_ERR_NO_SERVICE; 124178825Sdfr } 125178825Sdfr#undef RFLAGS 126178825Sdfr 127178825Sdfr /* count number of component, 128178825Sdfr * enterprise names only have one component 129178825Sdfr */ 13055682Smarkm ncomp = 1; 131178825Sdfr if (!enterprise) { 132178825Sdfr for(p = name; *p; p++){ 133178825Sdfr if(*p=='\\'){ 134178825Sdfr if(!p[1]) { 135178825Sdfr krb5_set_error_string (context, 136178825Sdfr "trailing \\ in principal name"); 137178825Sdfr return KRB5_PARSE_MALFORMED; 138178825Sdfr } 139178825Sdfr p++; 140178825Sdfr } else if(*p == '/') 141178825Sdfr ncomp++; 142178825Sdfr else if(*p == '@') 143178825Sdfr break; 144178825Sdfr } 14555682Smarkm } 14655682Smarkm comp = calloc(ncomp, sizeof(*comp)); 14778527Sassar if (comp == NULL) { 14878527Sassar krb5_set_error_string (context, "malloc: out of memory"); 14955682Smarkm return ENOMEM; 15078527Sassar } 15155682Smarkm 15255682Smarkm n = 0; 153102644Snectar p = start = q = s = strdup(name); 15455682Smarkm if (start == NULL) { 15555682Smarkm free (comp); 15678527Sassar krb5_set_error_string (context, "malloc: out of memory"); 15755682Smarkm return ENOMEM; 15855682Smarkm } 15955682Smarkm while(*p){ 16055682Smarkm c = *p++; 16155682Smarkm if(c == '\\'){ 16255682Smarkm c = *p++; 16355682Smarkm if(c == 'n') 16455682Smarkm c = '\n'; 16555682Smarkm else if(c == 't') 16655682Smarkm c = '\t'; 16755682Smarkm else if(c == 'b') 16855682Smarkm c = '\b'; 16955682Smarkm else if(c == '0') 17055682Smarkm c = '\0'; 171107207Snectar else if(c == '\0') { 172107207Snectar krb5_set_error_string (context, 173107207Snectar "trailing \\ in principal name"); 174107207Snectar ret = KRB5_PARSE_MALFORMED; 175107207Snectar goto exit; 176107207Snectar } 177178825Sdfr }else if(enterprise && first_at) { 178178825Sdfr if (c == '@') 179178825Sdfr first_at = 0; 180178825Sdfr }else if((c == '/' && !enterprise) || c == '@'){ 18155682Smarkm if(got_realm){ 18278527Sassar krb5_set_error_string (context, 18378527Sassar "part after realm in principal name"); 18455682Smarkm ret = KRB5_PARSE_MALFORMED; 18555682Smarkm goto exit; 18655682Smarkm }else{ 18755682Smarkm comp[n] = malloc(q - start + 1); 18855682Smarkm if (comp[n] == NULL) { 18978527Sassar krb5_set_error_string (context, "malloc: out of memory"); 19055682Smarkm ret = ENOMEM; 19155682Smarkm goto exit; 19255682Smarkm } 19357416Smarkm memcpy(comp[n], start, q - start); 19455682Smarkm comp[n][q - start] = 0; 19555682Smarkm n++; 19655682Smarkm } 19755682Smarkm if(c == '@') 19855682Smarkm got_realm = 1; 19955682Smarkm start = q; 20055682Smarkm continue; 20155682Smarkm } 20255682Smarkm if(got_realm && (c == ':' || c == '/' || c == '\0')) { 20378527Sassar krb5_set_error_string (context, 20478527Sassar "part after realm in principal name"); 20555682Smarkm ret = KRB5_PARSE_MALFORMED; 20655682Smarkm goto exit; 20755682Smarkm } 20855682Smarkm *q++ = c; 20955682Smarkm } 21055682Smarkm if(got_realm){ 211178825Sdfr if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { 212178825Sdfr krb5_set_error_string (context, "realm found in 'short' principal " 213178825Sdfr "expected to be without one"); 214178825Sdfr ret = KRB5_PARSE_MALFORMED; 215178825Sdfr goto exit; 216178825Sdfr } 21755682Smarkm realm = malloc(q - start + 1); 21855682Smarkm if (realm == NULL) { 21978527Sassar krb5_set_error_string (context, "malloc: out of memory"); 22055682Smarkm ret = ENOMEM; 22155682Smarkm goto exit; 22255682Smarkm } 22357416Smarkm memcpy(realm, start, q - start); 22455682Smarkm realm[q - start] = 0; 22555682Smarkm }else{ 226178825Sdfr if (flags & KRB5_PRINCIPAL_PARSE_MUST_REALM) { 227178825Sdfr krb5_set_error_string (context, "realm NOT found in principal " 228178825Sdfr "expected to be with one"); 229178825Sdfr ret = KRB5_PARSE_MALFORMED; 23055682Smarkm goto exit; 231178825Sdfr } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { 232178825Sdfr realm = NULL; 233178825Sdfr } else { 234178825Sdfr ret = krb5_get_default_realm (context, &realm); 235178825Sdfr if (ret) 236178825Sdfr goto exit; 237178825Sdfr } 23855682Smarkm 23955682Smarkm comp[n] = malloc(q - start + 1); 24055682Smarkm if (comp[n] == NULL) { 24178527Sassar krb5_set_error_string (context, "malloc: out of memory"); 24255682Smarkm ret = ENOMEM; 24355682Smarkm goto exit; 24455682Smarkm } 24557416Smarkm memcpy(comp[n], start, q - start); 24655682Smarkm comp[n][q - start] = 0; 24755682Smarkm n++; 24855682Smarkm } 24955682Smarkm *principal = malloc(sizeof(**principal)); 25055682Smarkm if (*principal == NULL) { 25178527Sassar krb5_set_error_string (context, "malloc: out of memory"); 25255682Smarkm ret = ENOMEM; 25355682Smarkm goto exit; 25455682Smarkm } 255178825Sdfr if (enterprise) 256178825Sdfr (*principal)->name.name_type = KRB5_NT_ENTERPRISE_PRINCIPAL; 257178825Sdfr else 258178825Sdfr (*principal)->name.name_type = KRB5_NT_PRINCIPAL; 25955682Smarkm (*principal)->name.name_string.val = comp; 26055682Smarkm princ_num_comp(*principal) = n; 26155682Smarkm (*principal)->realm = realm; 26255682Smarkm free(s); 26355682Smarkm return 0; 26455682Smarkmexit: 26555682Smarkm while(n>0){ 26655682Smarkm free(comp[--n]); 26755682Smarkm } 26855682Smarkm free(comp); 269178825Sdfr free(realm); 27055682Smarkm free(s); 27155682Smarkm return ret; 27255682Smarkm} 27355682Smarkm 274178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 275178825Sdfrkrb5_parse_name(krb5_context context, 276178825Sdfr const char *name, 277178825Sdfr krb5_principal *principal) 278178825Sdfr{ 279178825Sdfr return krb5_parse_name_flags(context, name, 0, principal); 280178825Sdfr} 281178825Sdfr 28257416Smarkmstatic const char quotable_chars[] = " \n\t\b\\/@"; 28357416Smarkmstatic const char replace_chars[] = " ntb\\/@"; 284178825Sdfrstatic const char nq_chars[] = " \\/@"; 28555682Smarkm 28655682Smarkm#define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0); 28755682Smarkm 28855682Smarkmstatic size_t 289178825Sdfrquote_string(const char *s, char *out, size_t idx, size_t len, int display) 29055682Smarkm{ 29155682Smarkm const char *p, *q; 292178825Sdfr for(p = s; *p && idx < len; p++){ 293178825Sdfr q = strchr(quotable_chars, *p); 294178825Sdfr if (q && display) { 295178825Sdfr add_char(out, idx, len, replace_chars[q - quotable_chars]); 296178825Sdfr } else if (q) { 297178825Sdfr add_char(out, idx, len, '\\'); 298178825Sdfr add_char(out, idx, len, replace_chars[q - quotable_chars]); 29955682Smarkm }else 300178825Sdfr add_char(out, idx, len, *p); 30155682Smarkm } 302178825Sdfr if(idx < len) 303178825Sdfr out[idx] = '\0'; 304178825Sdfr return idx; 30555682Smarkm} 30655682Smarkm 30755682Smarkm 30855682Smarkmstatic krb5_error_code 30955682Smarkmunparse_name_fixed(krb5_context context, 31055682Smarkm krb5_const_principal principal, 31155682Smarkm char *name, 31255682Smarkm size_t len, 313178825Sdfr int flags) 31455682Smarkm{ 315178825Sdfr size_t idx = 0; 31655682Smarkm int i; 317178825Sdfr int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0; 318178825Sdfr int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0; 319178825Sdfr int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0; 320178825Sdfr 321178825Sdfr if (!no_realm && princ_realm(principal) == NULL) { 322178825Sdfr krb5_set_error_string(context, "Realm missing from principal, " 323178825Sdfr "can't unparse"); 324178825Sdfr return ERANGE; 325178825Sdfr } 326178825Sdfr 32755682Smarkm for(i = 0; i < princ_num_comp(principal); i++){ 32855682Smarkm if(i) 329178825Sdfr add_char(name, idx, len, '/'); 330178825Sdfr idx = quote_string(princ_ncomp(principal, i), name, idx, len, display); 331178825Sdfr if(idx == len) { 332178825Sdfr krb5_set_error_string(context, "Out of space printing principal"); 33355682Smarkm return ERANGE; 334178825Sdfr } 33555682Smarkm } 33655682Smarkm /* add realm if different from default realm */ 337178825Sdfr if(short_form && !no_realm) { 33855682Smarkm krb5_realm r; 33955682Smarkm krb5_error_code ret; 34055682Smarkm ret = krb5_get_default_realm(context, &r); 34155682Smarkm if(ret) 34255682Smarkm return ret; 34355682Smarkm if(strcmp(princ_realm(principal), r) != 0) 34455682Smarkm short_form = 0; 34555682Smarkm free(r); 34655682Smarkm } 347178825Sdfr if(!short_form && !no_realm) { 348178825Sdfr add_char(name, idx, len, '@'); 349178825Sdfr idx = quote_string(princ_realm(principal), name, idx, len, display); 350178825Sdfr if(idx == len) { 351178825Sdfr krb5_set_error_string(context, 352178825Sdfr "Out of space printing realm of principal"); 35355682Smarkm return ERANGE; 354178825Sdfr } 35555682Smarkm } 35655682Smarkm return 0; 35755682Smarkm} 35855682Smarkm 359178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 36055682Smarkmkrb5_unparse_name_fixed(krb5_context context, 36155682Smarkm krb5_const_principal principal, 36255682Smarkm char *name, 36355682Smarkm size_t len) 36455682Smarkm{ 365178825Sdfr return unparse_name_fixed(context, principal, name, len, 0); 36655682Smarkm} 36755682Smarkm 368178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 36955682Smarkmkrb5_unparse_name_fixed_short(krb5_context context, 37055682Smarkm krb5_const_principal principal, 37155682Smarkm char *name, 37255682Smarkm size_t len) 37355682Smarkm{ 374178825Sdfr return unparse_name_fixed(context, principal, name, len, 375178825Sdfr KRB5_PRINCIPAL_UNPARSE_SHORT); 37655682Smarkm} 37755682Smarkm 378178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 379178825Sdfrkrb5_unparse_name_fixed_flags(krb5_context context, 380178825Sdfr krb5_const_principal principal, 381178825Sdfr int flags, 382178825Sdfr char *name, 383178825Sdfr size_t len) 384178825Sdfr{ 385178825Sdfr return unparse_name_fixed(context, principal, name, len, flags); 386178825Sdfr} 387178825Sdfr 38855682Smarkmstatic krb5_error_code 38955682Smarkmunparse_name(krb5_context context, 39055682Smarkm krb5_const_principal principal, 39155682Smarkm char **name, 392178825Sdfr int flags) 39355682Smarkm{ 39455682Smarkm size_t len = 0, plen; 39555682Smarkm int i; 39655682Smarkm krb5_error_code ret; 39755682Smarkm /* count length */ 398178825Sdfr if (princ_realm(principal)) { 399178825Sdfr plen = strlen(princ_realm(principal)); 400178825Sdfr 401178825Sdfr if(strcspn(princ_realm(principal), quotable_chars) == plen) 402178825Sdfr len += plen; 403178825Sdfr else 404178825Sdfr len += 2*plen; 405178825Sdfr len++; /* '@' */ 406178825Sdfr } 40755682Smarkm for(i = 0; i < princ_num_comp(principal); i++){ 40855682Smarkm plen = strlen(princ_ncomp(principal, i)); 40955682Smarkm if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen) 41055682Smarkm len += plen; 41155682Smarkm else 41255682Smarkm len += 2*plen; 41355682Smarkm len++; 41455682Smarkm } 415178825Sdfr len++; /* '\0' */ 41655682Smarkm *name = malloc(len); 417127808Snectar if(*name == NULL) { 41878527Sassar krb5_set_error_string (context, "malloc: out of memory"); 41955682Smarkm return ENOMEM; 42078527Sassar } 421178825Sdfr ret = unparse_name_fixed(context, principal, *name, len, flags); 422127808Snectar if(ret) { 42355682Smarkm free(*name); 424127808Snectar *name = NULL; 425127808Snectar } 42655682Smarkm return ret; 42755682Smarkm} 42855682Smarkm 429178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 43055682Smarkmkrb5_unparse_name(krb5_context context, 43155682Smarkm krb5_const_principal principal, 43255682Smarkm char **name) 43355682Smarkm{ 434178825Sdfr return unparse_name(context, principal, name, 0); 43555682Smarkm} 43655682Smarkm 437178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 438178825Sdfrkrb5_unparse_name_flags(krb5_context context, 439178825Sdfr krb5_const_principal principal, 440178825Sdfr int flags, 441178825Sdfr char **name) 442178825Sdfr{ 443178825Sdfr return unparse_name(context, principal, name, flags); 444178825Sdfr} 445178825Sdfr 446178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 44755682Smarkmkrb5_unparse_name_short(krb5_context context, 44855682Smarkm krb5_const_principal principal, 44955682Smarkm char **name) 45055682Smarkm{ 451178825Sdfr return unparse_name(context, principal, name, KRB5_PRINCIPAL_UNPARSE_SHORT); 45255682Smarkm} 45355682Smarkm 45455682Smarkm#if 0 /* not implemented */ 45555682Smarkm 456178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 45755682Smarkmkrb5_unparse_name_ext(krb5_context context, 45855682Smarkm krb5_const_principal principal, 45955682Smarkm char **name, 46055682Smarkm size_t *size) 46155682Smarkm{ 46255682Smarkm krb5_abortx(context, "unimplemented krb5_unparse_name_ext called"); 46355682Smarkm} 46455682Smarkm 46555682Smarkm#endif 46655682Smarkm 467178825Sdfrkrb5_realm * KRB5_LIB_FUNCTION 46855682Smarkmkrb5_princ_realm(krb5_context context, 46955682Smarkm krb5_principal principal) 47055682Smarkm{ 47155682Smarkm return &princ_realm(principal); 47255682Smarkm} 47355682Smarkm 47455682Smarkm 475178825Sdfrvoid KRB5_LIB_FUNCTION 47655682Smarkmkrb5_princ_set_realm(krb5_context context, 47755682Smarkm krb5_principal principal, 47855682Smarkm krb5_realm *realm) 47955682Smarkm{ 48055682Smarkm princ_realm(principal) = *realm; 48155682Smarkm} 48255682Smarkm 48355682Smarkm 484178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 48555682Smarkmkrb5_build_principal(krb5_context context, 48655682Smarkm krb5_principal *principal, 48755682Smarkm int rlen, 48855682Smarkm krb5_const_realm realm, 48955682Smarkm ...) 49055682Smarkm{ 49155682Smarkm krb5_error_code ret; 49255682Smarkm va_list ap; 49355682Smarkm va_start(ap, realm); 49455682Smarkm ret = krb5_build_principal_va(context, principal, rlen, realm, ap); 49555682Smarkm va_end(ap); 49655682Smarkm return ret; 49755682Smarkm} 49855682Smarkm 49955682Smarkmstatic krb5_error_code 50055682Smarkmappend_component(krb5_context context, krb5_principal p, 50157416Smarkm const char *comp, 50255682Smarkm size_t comp_len) 50355682Smarkm{ 504178825Sdfr heim_general_string *tmp; 50555682Smarkm size_t len = princ_num_comp(p); 50657416Smarkm 50755682Smarkm tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp)); 50878527Sassar if(tmp == NULL) { 50978527Sassar krb5_set_error_string (context, "malloc: out of memory"); 51055682Smarkm return ENOMEM; 51178527Sassar } 51255682Smarkm princ_comp(p) = tmp; 51355682Smarkm princ_ncomp(p, len) = malloc(comp_len + 1); 51478527Sassar if (princ_ncomp(p, len) == NULL) { 51578527Sassar krb5_set_error_string (context, "malloc: out of memory"); 51657416Smarkm return ENOMEM; 51778527Sassar } 51855682Smarkm memcpy (princ_ncomp(p, len), comp, comp_len); 51955682Smarkm princ_ncomp(p, len)[comp_len] = '\0'; 52055682Smarkm princ_num_comp(p)++; 52155682Smarkm return 0; 52255682Smarkm} 52355682Smarkm 52455682Smarkmstatic void 52555682Smarkmva_ext_princ(krb5_context context, krb5_principal p, va_list ap) 52655682Smarkm{ 52755682Smarkm while(1){ 52857416Smarkm const char *s; 52955682Smarkm int len; 53055682Smarkm len = va_arg(ap, int); 53155682Smarkm if(len == 0) 53255682Smarkm break; 53357416Smarkm s = va_arg(ap, const char*); 53455682Smarkm append_component(context, p, s, len); 53555682Smarkm } 53655682Smarkm} 53755682Smarkm 53855682Smarkmstatic void 53955682Smarkmva_princ(krb5_context context, krb5_principal p, va_list ap) 54055682Smarkm{ 54155682Smarkm while(1){ 54257416Smarkm const char *s; 54357416Smarkm s = va_arg(ap, const char*); 54455682Smarkm if(s == NULL) 54555682Smarkm break; 54655682Smarkm append_component(context, p, s, strlen(s)); 54755682Smarkm } 54855682Smarkm} 54955682Smarkm 55055682Smarkm 55155682Smarkmstatic krb5_error_code 55255682Smarkmbuild_principal(krb5_context context, 55355682Smarkm krb5_principal *principal, 55455682Smarkm int rlen, 55555682Smarkm krb5_const_realm realm, 55655682Smarkm void (*func)(krb5_context, krb5_principal, va_list), 55755682Smarkm va_list ap) 55855682Smarkm{ 55955682Smarkm krb5_principal p; 56055682Smarkm 56155682Smarkm p = calloc(1, sizeof(*p)); 56278527Sassar if (p == NULL) { 56378527Sassar krb5_set_error_string (context, "malloc: out of memory"); 56455682Smarkm return ENOMEM; 56578527Sassar } 56655682Smarkm princ_type(p) = KRB5_NT_PRINCIPAL; 56755682Smarkm 56855682Smarkm princ_realm(p) = strdup(realm); 56955682Smarkm if(p->realm == NULL){ 57055682Smarkm free(p); 57178527Sassar krb5_set_error_string (context, "malloc: out of memory"); 57255682Smarkm return ENOMEM; 57355682Smarkm } 57455682Smarkm 57555682Smarkm (*func)(context, p, ap); 57655682Smarkm *principal = p; 57755682Smarkm return 0; 57855682Smarkm} 57955682Smarkm 580178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 58155682Smarkmkrb5_make_principal(krb5_context context, 58255682Smarkm krb5_principal *principal, 58355682Smarkm krb5_const_realm realm, 58455682Smarkm ...) 58555682Smarkm{ 58655682Smarkm krb5_error_code ret; 58755682Smarkm krb5_realm r = NULL; 58855682Smarkm va_list ap; 58955682Smarkm if(realm == NULL) { 59055682Smarkm ret = krb5_get_default_realm(context, &r); 59155682Smarkm if(ret) 59255682Smarkm return ret; 59355682Smarkm realm = r; 59455682Smarkm } 59555682Smarkm va_start(ap, realm); 59655682Smarkm ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap); 59755682Smarkm va_end(ap); 59855682Smarkm if(r) 59955682Smarkm free(r); 60055682Smarkm return ret; 60155682Smarkm} 60255682Smarkm 603178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 60455682Smarkmkrb5_build_principal_va(krb5_context context, 60555682Smarkm krb5_principal *principal, 60655682Smarkm int rlen, 60755682Smarkm krb5_const_realm realm, 60855682Smarkm va_list ap) 60955682Smarkm{ 61055682Smarkm return build_principal(context, principal, rlen, realm, va_princ, ap); 61155682Smarkm} 61255682Smarkm 613178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 61455682Smarkmkrb5_build_principal_va_ext(krb5_context context, 61555682Smarkm krb5_principal *principal, 61655682Smarkm int rlen, 61755682Smarkm krb5_const_realm realm, 61855682Smarkm va_list ap) 61955682Smarkm{ 62055682Smarkm return build_principal(context, principal, rlen, realm, va_ext_princ, ap); 62155682Smarkm} 62255682Smarkm 62355682Smarkm 624178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 62555682Smarkmkrb5_build_principal_ext(krb5_context context, 62655682Smarkm krb5_principal *principal, 62755682Smarkm int rlen, 62855682Smarkm krb5_const_realm realm, 62955682Smarkm ...) 63055682Smarkm{ 63155682Smarkm krb5_error_code ret; 63255682Smarkm va_list ap; 63355682Smarkm va_start(ap, realm); 63455682Smarkm ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap); 63555682Smarkm va_end(ap); 63655682Smarkm return ret; 63755682Smarkm} 63855682Smarkm 63955682Smarkm 640178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 64155682Smarkmkrb5_copy_principal(krb5_context context, 64255682Smarkm krb5_const_principal inprinc, 64355682Smarkm krb5_principal *outprinc) 64455682Smarkm{ 64555682Smarkm krb5_principal p = malloc(sizeof(*p)); 64678527Sassar if (p == NULL) { 64778527Sassar krb5_set_error_string (context, "malloc: out of memory"); 64855682Smarkm return ENOMEM; 64978527Sassar } 65078527Sassar if(copy_Principal(inprinc, p)) { 65178527Sassar free(p); 65278527Sassar krb5_set_error_string (context, "malloc: out of memory"); 65355682Smarkm return ENOMEM; 65478527Sassar } 65555682Smarkm *outprinc = p; 65655682Smarkm return 0; 65755682Smarkm} 65855682Smarkm 65972445Sassar/* 66072445Sassar * return TRUE iff princ1 == princ2 (without considering the realm) 66172445Sassar */ 66255682Smarkm 663178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION 66455682Smarkmkrb5_principal_compare_any_realm(krb5_context context, 66555682Smarkm krb5_const_principal princ1, 66655682Smarkm krb5_const_principal princ2) 66755682Smarkm{ 66855682Smarkm int i; 66955682Smarkm if(princ_num_comp(princ1) != princ_num_comp(princ2)) 67055682Smarkm return FALSE; 67155682Smarkm for(i = 0; i < princ_num_comp(princ1); i++){ 67255682Smarkm if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0) 67355682Smarkm return FALSE; 67455682Smarkm } 67555682Smarkm return TRUE; 67655682Smarkm} 67755682Smarkm 67872445Sassar/* 67972445Sassar * return TRUE iff princ1 == princ2 68072445Sassar */ 68172445Sassar 682178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION 68355682Smarkmkrb5_principal_compare(krb5_context context, 68455682Smarkm krb5_const_principal princ1, 68555682Smarkm krb5_const_principal princ2) 68655682Smarkm{ 68755682Smarkm if(!krb5_realm_compare(context, princ1, princ2)) 68855682Smarkm return FALSE; 68955682Smarkm return krb5_principal_compare_any_realm(context, princ1, princ2); 69055682Smarkm} 69155682Smarkm 69272445Sassar/* 69372445Sassar * return TRUE iff realm(princ1) == realm(princ2) 69472445Sassar */ 69555682Smarkm 696178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION 69755682Smarkmkrb5_realm_compare(krb5_context context, 69855682Smarkm krb5_const_principal princ1, 69955682Smarkm krb5_const_principal princ2) 70055682Smarkm{ 70155682Smarkm return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0; 70255682Smarkm} 70355682Smarkm 70472445Sassar/* 70572445Sassar * return TRUE iff princ matches pattern 70672445Sassar */ 70772445Sassar 708178825Sdfrkrb5_boolean KRB5_LIB_FUNCTION 70972445Sassarkrb5_principal_match(krb5_context context, 71072445Sassar krb5_const_principal princ, 71172445Sassar krb5_const_principal pattern) 71272445Sassar{ 71372445Sassar int i; 71472445Sassar if(princ_num_comp(princ) != princ_num_comp(pattern)) 71572445Sassar return FALSE; 71672445Sassar if(fnmatch(princ_realm(pattern), princ_realm(princ), 0) != 0) 71772445Sassar return FALSE; 71872445Sassar for(i = 0; i < princ_num_comp(princ); i++){ 71972445Sassar if(fnmatch(princ_ncomp(pattern, i), princ_ncomp(princ, i), 0) != 0) 72072445Sassar return FALSE; 72172445Sassar } 72272445Sassar return TRUE; 72372445Sassar} 72472445Sassar 72572445Sassar 726178825Sdfrstatic struct v4_name_convert { 72755682Smarkm const char *from; 72855682Smarkm const char *to; 72955682Smarkm} default_v4_name_convert[] = { 73072445Sassar { "ftp", "ftp" }, 73172445Sassar { "hprop", "hprop" }, 73272445Sassar { "pop", "pop" }, 73372445Sassar { "imap", "imap" }, 73472445Sassar { "rcmd", "host" }, 73590926Snectar { "smtp", "smtp" }, 73655682Smarkm { NULL, NULL } 73755682Smarkm}; 73855682Smarkm 73972445Sassar/* 74072445Sassar * return the converted instance name of `name' in `realm'. 74172445Sassar * look in the configuration file and then in the default set above. 74272445Sassar * return NULL if no conversion is appropriate. 74372445Sassar */ 74472445Sassar 74555682Smarkmstatic const char* 74655682Smarkmget_name_conversion(krb5_context context, const char *realm, const char *name) 74755682Smarkm{ 74855682Smarkm struct v4_name_convert *q; 74955682Smarkm const char *p; 75072445Sassar 75155682Smarkm p = krb5_config_get_string(context, NULL, "realms", realm, 75255682Smarkm "v4_name_convert", "host", name, NULL); 75355682Smarkm if(p == NULL) 75455682Smarkm p = krb5_config_get_string(context, NULL, "libdefaults", 75555682Smarkm "v4_name_convert", "host", name, NULL); 75655682Smarkm if(p) 75755682Smarkm return p; 75855682Smarkm 75955682Smarkm /* XXX should be possible to override default list */ 76055682Smarkm p = krb5_config_get_string(context, NULL, 76155682Smarkm "realms", 76255682Smarkm realm, 76355682Smarkm "v4_name_convert", 76455682Smarkm "plain", 76555682Smarkm name, 76655682Smarkm NULL); 76755682Smarkm if(p) 76855682Smarkm return NULL; 76955682Smarkm p = krb5_config_get_string(context, NULL, 77055682Smarkm "libdefaults", 77155682Smarkm "v4_name_convert", 77255682Smarkm "plain", 77355682Smarkm name, 77455682Smarkm NULL); 77555682Smarkm if(p) 77655682Smarkm return NULL; 77755682Smarkm for(q = default_v4_name_convert; q->from; q++) 77855682Smarkm if(strcmp(q->from, name) == 0) 77955682Smarkm return q->to; 78055682Smarkm return NULL; 78155682Smarkm} 78255682Smarkm 78372445Sassar/* 78472445Sassar * convert the v4 principal `name.instance@realm' to a v5 principal in `princ'. 78572445Sassar * if `resolve', use DNS. 78672445Sassar * if `func', use that function for validating the conversion 78772445Sassar */ 78872445Sassar 789178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 790178825Sdfrkrb5_425_conv_principal_ext2(krb5_context context, 791178825Sdfr const char *name, 792178825Sdfr const char *instance, 793178825Sdfr const char *realm, 794178825Sdfr krb5_boolean (*func)(krb5_context, 795178825Sdfr void *, krb5_principal), 796178825Sdfr void *funcctx, 797178825Sdfr krb5_boolean resolve, 798178825Sdfr krb5_principal *princ) 79955682Smarkm{ 80055682Smarkm const char *p; 80155682Smarkm krb5_error_code ret; 80255682Smarkm krb5_principal pr; 80372445Sassar char host[MAXHOSTNAMELEN]; 80490926Snectar char local_hostname[MAXHOSTNAMELEN]; 80555682Smarkm 80655682Smarkm /* do the following: if the name is found in the 807178825Sdfr `v4_name_convert:host' part, is assumed to be a `host' type 80855682Smarkm principal, and the instance is looked up in the 80955682Smarkm `v4_instance_convert' part. if not found there the name is 81055682Smarkm (optionally) looked up as a hostname, and if that doesn't yield 81155682Smarkm anything, the `default_domain' is appended to the instance 81255682Smarkm */ 81355682Smarkm 81455682Smarkm if(instance == NULL) 81555682Smarkm goto no_host; 81655682Smarkm if(instance[0] == 0){ 81755682Smarkm instance = NULL; 81855682Smarkm goto no_host; 81955682Smarkm } 82055682Smarkm p = get_name_conversion(context, realm, name); 82155682Smarkm if(p == NULL) 82255682Smarkm goto no_host; 82355682Smarkm name = p; 82455682Smarkm p = krb5_config_get_string(context, NULL, "realms", realm, 82555682Smarkm "v4_instance_convert", instance, NULL); 82655682Smarkm if(p){ 82755682Smarkm instance = p; 82855682Smarkm ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); 829178825Sdfr if(func == NULL || (*func)(context, funcctx, pr)){ 83055682Smarkm *princ = pr; 83155682Smarkm return 0; 83255682Smarkm } 83355682Smarkm krb5_free_principal(context, pr); 83455682Smarkm *princ = NULL; 83578527Sassar krb5_clear_error_string (context); 83655682Smarkm return HEIM_ERR_V4_PRINC_NO_CONV; 83755682Smarkm } 83855682Smarkm if(resolve){ 839102644Snectar krb5_boolean passed = FALSE; 840102644Snectar char *inst = NULL; 84155682Smarkm#ifdef USE_RESOLVER 84255682Smarkm struct dns_reply *r; 84372445Sassar 844102644Snectar r = dns_lookup(instance, "aaaa"); 845178825Sdfr if (r) { 846178825Sdfr if (r->head && r->head->type == T_AAAA) { 847178825Sdfr inst = strdup(r->head->domain); 848178825Sdfr passed = TRUE; 849178825Sdfr } 850102644Snectar dns_free_data(r); 851102644Snectar } else { 852102644Snectar r = dns_lookup(instance, "a"); 853178825Sdfr if (r) { 854178825Sdfr if(r->head && r->head->type == T_A) { 855178825Sdfr inst = strdup(r->head->domain); 856178825Sdfr passed = TRUE; 857178825Sdfr } 85872445Sassar dns_free_data(r); 859102644Snectar } 860102644Snectar } 861102644Snectar#else 862102644Snectar struct addrinfo hints, *ai; 863102644Snectar 864102644Snectar memset (&hints, 0, sizeof(hints)); 865102644Snectar hints.ai_flags = AI_CANONNAME; 866102644Snectar ret = getaddrinfo(instance, NULL, &hints, &ai); 867102644Snectar if (ret == 0) { 868102644Snectar const struct addrinfo *a; 869102644Snectar for (a = ai; a != NULL; a = a->ai_next) { 870102644Snectar if (a->ai_canonname != NULL) { 871102644Snectar inst = strdup (a->ai_canonname); 872102644Snectar passed = TRUE; 873102644Snectar break; 874102644Snectar } 875102644Snectar } 876102644Snectar freeaddrinfo (ai); 877102644Snectar } 87872445Sassar#endif 879102644Snectar if (passed) { 880102644Snectar if (inst == NULL) { 88178527Sassar krb5_set_error_string (context, "malloc: out of memory"); 88272445Sassar return ENOMEM; 88372445Sassar } 884102644Snectar strlwr(inst); 885102644Snectar ret = krb5_make_principal(context, &pr, realm, name, inst, 88672445Sassar NULL); 887102644Snectar free (inst); 88855682Smarkm if(ret == 0) { 889178825Sdfr if(func == NULL || (*func)(context, funcctx, pr)){ 89055682Smarkm *princ = pr; 89155682Smarkm return 0; 89255682Smarkm } 89355682Smarkm krb5_free_principal(context, pr); 89455682Smarkm } 89555682Smarkm } 89655682Smarkm } 89790926Snectar if(func != NULL) { 89890926Snectar snprintf(host, sizeof(host), "%s.%s", instance, realm); 89990926Snectar strlwr(host); 90090926Snectar ret = krb5_make_principal(context, &pr, realm, name, host, NULL); 901178825Sdfr if((*func)(context, funcctx, pr)){ 90290926Snectar *princ = pr; 90390926Snectar return 0; 90490926Snectar } 90590926Snectar krb5_free_principal(context, pr); 90690926Snectar } 90790926Snectar 90890926Snectar /* 90990926Snectar * if the instance is the first component of the local hostname, 91090926Snectar * the converted host should be the long hostname. 91190926Snectar */ 91290926Snectar 91390926Snectar if (func == NULL && 91490926Snectar gethostname (local_hostname, sizeof(local_hostname)) == 0 && 91590926Snectar strncmp(instance, local_hostname, strlen(instance)) == 0 && 91690926Snectar local_hostname[strlen(instance)] == '.') { 91790926Snectar strlcpy(host, local_hostname, sizeof(host)); 91890926Snectar goto local_host; 91990926Snectar } 92090926Snectar 92155682Smarkm { 92255682Smarkm char **domains, **d; 92355682Smarkm domains = krb5_config_get_strings(context, NULL, "realms", realm, 92455682Smarkm "v4_domains", NULL); 92555682Smarkm for(d = domains; d && *d; d++){ 92655682Smarkm snprintf(host, sizeof(host), "%s.%s", instance, *d); 92755682Smarkm ret = krb5_make_principal(context, &pr, realm, name, host, NULL); 928178825Sdfr if(func == NULL || (*func)(context, funcctx, pr)){ 92955682Smarkm *princ = pr; 93055682Smarkm krb5_config_free_strings(domains); 93155682Smarkm return 0; 93255682Smarkm } 93355682Smarkm krb5_free_principal(context, pr); 93455682Smarkm } 93555682Smarkm krb5_config_free_strings(domains); 93655682Smarkm } 93790926Snectar 93855682Smarkm 93955682Smarkm p = krb5_config_get_string(context, NULL, "realms", realm, 94055682Smarkm "default_domain", NULL); 94155682Smarkm if(p == NULL){ 94272445Sassar /* this should be an error, just faking a name is not good */ 94378527Sassar krb5_clear_error_string (context); 94455682Smarkm return HEIM_ERR_V4_PRINC_NO_CONV; 94555682Smarkm } 94655682Smarkm 94755682Smarkm if (*p == '.') 94855682Smarkm ++p; 94955682Smarkm snprintf(host, sizeof(host), "%s.%s", instance, p); 95090926Snectarlocal_host: 95155682Smarkm ret = krb5_make_principal(context, &pr, realm, name, host, NULL); 952178825Sdfr if(func == NULL || (*func)(context, funcctx, pr)){ 95355682Smarkm *princ = pr; 95455682Smarkm return 0; 95555682Smarkm } 95655682Smarkm krb5_free_principal(context, pr); 95778527Sassar krb5_clear_error_string (context); 95855682Smarkm return HEIM_ERR_V4_PRINC_NO_CONV; 95955682Smarkmno_host: 96055682Smarkm p = krb5_config_get_string(context, NULL, 96155682Smarkm "realms", 96255682Smarkm realm, 96355682Smarkm "v4_name_convert", 96455682Smarkm "plain", 96555682Smarkm name, 96655682Smarkm NULL); 96755682Smarkm if(p == NULL) 96855682Smarkm p = krb5_config_get_string(context, NULL, 96955682Smarkm "libdefaults", 97055682Smarkm "v4_name_convert", 97155682Smarkm "plain", 97255682Smarkm name, 97355682Smarkm NULL); 97455682Smarkm if(p) 97555682Smarkm name = p; 97655682Smarkm 97755682Smarkm ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); 978178825Sdfr if(func == NULL || (*func)(context, funcctx, pr)){ 97955682Smarkm *princ = pr; 98055682Smarkm return 0; 98155682Smarkm } 98255682Smarkm krb5_free_principal(context, pr); 98378527Sassar krb5_clear_error_string (context); 98455682Smarkm return HEIM_ERR_V4_PRINC_NO_CONV; 98555682Smarkm} 98655682Smarkm 987178825Sdfrstatic krb5_boolean 988178825Sdfrconvert_func(krb5_context conxtext, void *funcctx, krb5_principal principal) 989178825Sdfr{ 990178825Sdfr krb5_boolean (*func)(krb5_context, krb5_principal) = funcctx; 991178825Sdfr return (*func)(conxtext, principal); 992178825Sdfr} 993178825Sdfr 994178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 995178825Sdfrkrb5_425_conv_principal_ext(krb5_context context, 996178825Sdfr const char *name, 997178825Sdfr const char *instance, 998178825Sdfr const char *realm, 999178825Sdfr krb5_boolean (*func)(krb5_context, krb5_principal), 1000178825Sdfr krb5_boolean resolve, 1001178825Sdfr krb5_principal *principal) 1002178825Sdfr{ 1003178825Sdfr return krb5_425_conv_principal_ext2(context, 1004178825Sdfr name, 1005178825Sdfr instance, 1006178825Sdfr realm, 1007178825Sdfr func ? convert_func : NULL, 1008178825Sdfr func, 1009178825Sdfr resolve, 1010178825Sdfr principal); 1011178825Sdfr} 1012178825Sdfr 1013178825Sdfr 1014178825Sdfr 1015178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 101655682Smarkmkrb5_425_conv_principal(krb5_context context, 101755682Smarkm const char *name, 101855682Smarkm const char *instance, 101955682Smarkm const char *realm, 102055682Smarkm krb5_principal *princ) 102155682Smarkm{ 102255682Smarkm krb5_boolean resolve = krb5_config_get_bool(context, 102355682Smarkm NULL, 102455682Smarkm "libdefaults", 102555682Smarkm "v4_instance_resolve", 102655682Smarkm NULL); 102755682Smarkm 102855682Smarkm return krb5_425_conv_principal_ext(context, name, instance, realm, 102955682Smarkm NULL, resolve, princ); 103055682Smarkm} 103155682Smarkm 103255682Smarkm 103355682Smarkmstatic int 103455682Smarkmcheck_list(const krb5_config_binding *l, const char *name, const char **out) 103555682Smarkm{ 103655682Smarkm while(l){ 103755682Smarkm if (l->type != krb5_config_string) 103855682Smarkm continue; 103955682Smarkm if(strcmp(name, l->u.string) == 0) { 104055682Smarkm *out = l->name; 104155682Smarkm return 1; 104255682Smarkm } 104355682Smarkm l = l->next; 104455682Smarkm } 104555682Smarkm return 0; 104655682Smarkm} 104755682Smarkm 104855682Smarkmstatic int 104955682Smarkmname_convert(krb5_context context, const char *name, const char *realm, 105055682Smarkm const char **out) 105155682Smarkm{ 105255682Smarkm const krb5_config_binding *l; 105355682Smarkm l = krb5_config_get_list (context, 105455682Smarkm NULL, 105555682Smarkm "realms", 105655682Smarkm realm, 105755682Smarkm "v4_name_convert", 105855682Smarkm "host", 105955682Smarkm NULL); 106055682Smarkm if(l && check_list(l, name, out)) 106155682Smarkm return KRB5_NT_SRV_HST; 106255682Smarkm l = krb5_config_get_list (context, 106355682Smarkm NULL, 106455682Smarkm "libdefaults", 106555682Smarkm "v4_name_convert", 106655682Smarkm "host", 106755682Smarkm NULL); 106855682Smarkm if(l && check_list(l, name, out)) 106955682Smarkm return KRB5_NT_SRV_HST; 107055682Smarkm l = krb5_config_get_list (context, 107155682Smarkm NULL, 107255682Smarkm "realms", 107355682Smarkm realm, 107455682Smarkm "v4_name_convert", 107555682Smarkm "plain", 107655682Smarkm NULL); 107755682Smarkm if(l && check_list(l, name, out)) 107855682Smarkm return KRB5_NT_UNKNOWN; 107955682Smarkm l = krb5_config_get_list (context, 108055682Smarkm NULL, 108155682Smarkm "libdefaults", 108255682Smarkm "v4_name_convert", 108355682Smarkm "host", 108455682Smarkm NULL); 108555682Smarkm if(l && check_list(l, name, out)) 108655682Smarkm return KRB5_NT_UNKNOWN; 108755682Smarkm 108855682Smarkm /* didn't find it in config file, try built-in list */ 108955682Smarkm { 109055682Smarkm struct v4_name_convert *q; 109155682Smarkm for(q = default_v4_name_convert; q->from; q++) { 109255682Smarkm if(strcmp(name, q->to) == 0) { 109355682Smarkm *out = q->from; 109455682Smarkm return KRB5_NT_SRV_HST; 109555682Smarkm } 109655682Smarkm } 109755682Smarkm } 109855682Smarkm return -1; 109955682Smarkm} 110055682Smarkm 110172445Sassar/* 110272445Sassar * convert the v5 principal in `principal' into a v4 corresponding one 110372445Sassar * in `name, instance, realm' 110472445Sassar * this is limited interface since there's no length given for these 110572445Sassar * three parameters. They have to be 40 bytes each (ANAME_SZ). 110672445Sassar */ 110772445Sassar 1108178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 110955682Smarkmkrb5_524_conv_principal(krb5_context context, 111055682Smarkm const krb5_principal principal, 111155682Smarkm char *name, 111255682Smarkm char *instance, 111355682Smarkm char *realm) 111455682Smarkm{ 111555682Smarkm const char *n, *i, *r; 111655682Smarkm char tmpinst[40]; 111755682Smarkm int type = princ_type(principal); 111872445Sassar const int aname_sz = 40; 111955682Smarkm 112055682Smarkm r = principal->realm; 112155682Smarkm 112255682Smarkm switch(principal->name.name_string.len){ 112355682Smarkm case 1: 112455682Smarkm n = principal->name.name_string.val[0]; 112555682Smarkm i = ""; 112655682Smarkm break; 112755682Smarkm case 2: 112855682Smarkm n = principal->name.name_string.val[0]; 112955682Smarkm i = principal->name.name_string.val[1]; 113055682Smarkm break; 113155682Smarkm default: 113278527Sassar krb5_set_error_string (context, 113378527Sassar "cannot convert a %d component principal", 113478527Sassar principal->name.name_string.len); 113555682Smarkm return KRB5_PARSE_MALFORMED; 113655682Smarkm } 113755682Smarkm 113855682Smarkm { 113955682Smarkm const char *tmp; 114055682Smarkm int t = name_convert(context, n, r, &tmp); 114155682Smarkm if(t >= 0) { 114255682Smarkm type = t; 114355682Smarkm n = tmp; 114455682Smarkm } 114555682Smarkm } 114655682Smarkm 114755682Smarkm if(type == KRB5_NT_SRV_HST){ 114855682Smarkm char *p; 114957416Smarkm 115057416Smarkm strlcpy (tmpinst, i, sizeof(tmpinst)); 115155682Smarkm p = strchr(tmpinst, '.'); 115257416Smarkm if(p) 115357416Smarkm *p = 0; 115455682Smarkm i = tmpinst; 115555682Smarkm } 115655682Smarkm 115778527Sassar if (strlcpy (name, n, aname_sz) >= aname_sz) { 115878527Sassar krb5_set_error_string (context, 115978527Sassar "too long name component to convert"); 116055682Smarkm return KRB5_PARSE_MALFORMED; 116178527Sassar } 116278527Sassar if (strlcpy (instance, i, aname_sz) >= aname_sz) { 116378527Sassar krb5_set_error_string (context, 116478527Sassar "too long instance component to convert"); 116555682Smarkm return KRB5_PARSE_MALFORMED; 116678527Sassar } 116778527Sassar if (strlcpy (realm, r, aname_sz) >= aname_sz) { 116878527Sassar krb5_set_error_string (context, 116978527Sassar "too long realm component to convert"); 117055682Smarkm return KRB5_PARSE_MALFORMED; 117178527Sassar } 117255682Smarkm return 0; 117355682Smarkm} 117455682Smarkm 117555682Smarkm/* 117655682Smarkm * Create a principal in `ret_princ' for the service `sname' running 117757416Smarkm * on host `hostname'. */ 117855682Smarkm 1179178825Sdfrkrb5_error_code KRB5_LIB_FUNCTION 118055682Smarkmkrb5_sname_to_principal (krb5_context context, 118155682Smarkm const char *hostname, 118255682Smarkm const char *sname, 118355682Smarkm int32_t type, 118455682Smarkm krb5_principal *ret_princ) 118555682Smarkm{ 118655682Smarkm krb5_error_code ret; 118772445Sassar char localhost[MAXHOSTNAMELEN]; 118855682Smarkm char **realms, *host = NULL; 118955682Smarkm 119078527Sassar if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) { 119178527Sassar krb5_set_error_string (context, "unsupported name type %d", 119278527Sassar type); 119355682Smarkm return KRB5_SNAME_UNSUPP_NAMETYPE; 119478527Sassar } 119555682Smarkm if(hostname == NULL) { 119655682Smarkm gethostname(localhost, sizeof(localhost)); 119755682Smarkm hostname = localhost; 119855682Smarkm } 119955682Smarkm if(sname == NULL) 120055682Smarkm sname = "host"; 120155682Smarkm if(type == KRB5_NT_SRV_HST) { 120257416Smarkm ret = krb5_expand_hostname_realms (context, hostname, 120357416Smarkm &host, &realms); 120455682Smarkm if (ret) 120555682Smarkm return ret; 120655682Smarkm strlwr(host); 120755682Smarkm hostname = host; 120857416Smarkm } else { 120957416Smarkm ret = krb5_get_host_realm(context, hostname, &realms); 121057416Smarkm if(ret) 121157416Smarkm return ret; 121255682Smarkm } 121355682Smarkm 121455682Smarkm ret = krb5_make_principal(context, ret_princ, realms[0], sname, 121555682Smarkm hostname, NULL); 121655682Smarkm if(host) 121755682Smarkm free(host); 121855682Smarkm krb5_free_host_realm(context, realms); 121955682Smarkm return ret; 122055682Smarkm} 1221178825Sdfr 1222178825Sdfrstatic const struct { 1223178825Sdfr const char *type; 1224178825Sdfr int32_t value; 1225178825Sdfr} nametypes[] = { 1226178825Sdfr { "UNKNOWN", KRB5_NT_UNKNOWN }, 1227178825Sdfr { "PRINCIPAL", KRB5_NT_PRINCIPAL }, 1228178825Sdfr { "SRV_INST", KRB5_NT_SRV_INST }, 1229178825Sdfr { "SRV_HST", KRB5_NT_SRV_HST }, 1230178825Sdfr { "SRV_XHST", KRB5_NT_SRV_XHST }, 1231178825Sdfr { "UID", KRB5_NT_UID }, 1232178825Sdfr { "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL }, 1233178825Sdfr { "SMTP_NAME", KRB5_NT_SMTP_NAME }, 1234178825Sdfr { "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL }, 1235178825Sdfr { "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID }, 1236178825Sdfr { "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL }, 1237178825Sdfr { "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID }, 1238178825Sdfr { NULL } 1239178825Sdfr}; 1240178825Sdfr 1241178825Sdfrkrb5_error_code 1242178825Sdfrkrb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype) 1243178825Sdfr{ 1244178825Sdfr size_t i; 1245178825Sdfr 1246178825Sdfr for(i = 0; nametypes[i].type; i++) { 1247178825Sdfr if (strcasecmp(nametypes[i].type, str) == 0) { 1248178825Sdfr *nametype = nametypes[i].value; 1249178825Sdfr return 0; 1250178825Sdfr } 1251178825Sdfr } 1252178825Sdfr krb5_set_error_string(context, "Failed to find name type %s", str); 1253178825Sdfr return KRB5_PARSE_MALFORMED; 1254178825Sdfr} 1255