1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/bld_princ.c - Build a principal from a list of strings */
3 /*
4 * Copyright 1991 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
6 *
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
11 *
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 */
26
27 #include "k5-int.h"
28 #include "int-proto.h"
29
30 krb5_int32
k5_infer_principal_type(krb5_principal princ)31 k5_infer_principal_type(krb5_principal princ)
32 {
33 /* RFC 4120 section 7.3 */
34 if (princ->length == 2 && data_eq_string(princ->data[0], KRB5_TGS_NAME))
35 return KRB5_NT_SRV_INST;
36
37 /* RFC 6111 section 3.1 */
38 if (princ->length >= 2 &&
39 data_eq_string(princ->data[0], KRB5_WELLKNOWN_NAMESTR))
40 return KRB5_NT_WELLKNOWN;
41
42 return KRB5_NT_PRINCIPAL;
43 }
44
45 static krb5_error_code
build_principal_va(krb5_context context,krb5_principal princ,unsigned int rlen,const char * realm,va_list ap)46 build_principal_va(krb5_context context, krb5_principal princ,
47 unsigned int rlen, const char *realm, va_list ap)
48 {
49 krb5_error_code retval = 0;
50 char *r = NULL;
51 krb5_data *data = NULL;
52 krb5_int32 count = 0;
53 krb5_int32 size = 2; /* initial guess at needed space */
54 char *component = NULL;
55
56 data = malloc(size * sizeof(krb5_data));
57 if (!data) { retval = ENOMEM; }
58
59 if (!retval)
60 r = k5memdup0(realm, rlen, &retval);
61
62 while (!retval && (component = va_arg(ap, char *))) {
63 if (count == size) {
64 krb5_data *new_data = NULL;
65
66 size *= 2;
67 new_data = realloc(data, size * sizeof(krb5_data));
68 if (new_data) {
69 data = new_data;
70 } else {
71 retval = ENOMEM;
72 }
73 }
74
75 if (!retval) {
76 data[count].length = strlen(component);
77 data[count].data = strdup(component);
78 if (!data[count].data) { retval = ENOMEM; }
79 count++;
80 }
81 }
82
83 if (!retval) {
84 princ->magic = KV5M_PRINCIPAL;
85 princ->realm = make_data(r, rlen);
86 princ->data = data;
87 princ->length = count;
88 princ->type = k5_infer_principal_type(princ);
89 r = NULL; /* take ownership */
90 data = NULL; /* take ownership */
91 }
92
93 if (data) {
94 while (--count >= 0) {
95 free(data[count].data);
96 }
97 free(data);
98 }
99 free(r);
100
101 return retval;
102 }
103
104 krb5_error_code KRB5_CALLCONV
krb5_build_principal_va(krb5_context context,krb5_principal princ,unsigned int rlen,const char * realm,va_list ap)105 krb5_build_principal_va(krb5_context context,
106 krb5_principal princ,
107 unsigned int rlen,
108 const char *realm,
109 va_list ap)
110 {
111 return build_principal_va(context, princ, rlen, realm, ap);
112 }
113
114 krb5_error_code KRB5_CALLCONV
krb5_build_principal_alloc_va(krb5_context context,krb5_principal * princ,unsigned int rlen,const char * realm,va_list ap)115 krb5_build_principal_alloc_va(krb5_context context,
116 krb5_principal *princ,
117 unsigned int rlen,
118 const char *realm,
119 va_list ap)
120 {
121 krb5_error_code retval = 0;
122 krb5_principal p;
123
124 p = malloc(sizeof(krb5_principal_data));
125 if (p == NULL)
126 return ENOMEM;
127
128 retval = build_principal_va(context, p, rlen, realm, ap);
129 if (retval) {
130 free(p);
131 return retval;
132 }
133
134 *princ = p;
135 return 0;
136 }
137
138 krb5_error_code KRB5_CALLCONV_C
krb5_build_principal(krb5_context context,krb5_principal * princ,unsigned int rlen,const char * realm,...)139 krb5_build_principal(krb5_context context,
140 krb5_principal * princ,
141 unsigned int rlen,
142 const char * realm, ...)
143 {
144 krb5_error_code retval = 0;
145 va_list ap;
146
147 va_start(ap, realm);
148 retval = krb5_build_principal_alloc_va(context, princ, rlen, realm, ap);
149 va_end(ap);
150
151 return retval;
152 }
153
154 /*Anonymous and well known principals*/
155 static const char anon_realm_str[] = KRB5_ANONYMOUS_REALMSTR;
156 static const krb5_data anon_realm_data = {
157 KV5M_DATA, sizeof(anon_realm_str) - 1, (char *) anon_realm_str
158 };
159 static const char wellknown_str[] = KRB5_WELLKNOWN_NAMESTR;
160 static const char anon_str[] = KRB5_ANONYMOUS_PRINCSTR;
161 static const krb5_data anon_princ_data[] = {
162 { KV5M_DATA, sizeof(wellknown_str) - 1, (char *) wellknown_str },
163 { KV5M_DATA, sizeof(anon_str) - 1, (char *) anon_str }
164 };
165
166 const krb5_principal_data anon_princ = {
167 KV5M_PRINCIPAL,
168 { KV5M_DATA, sizeof(anon_realm_str) - 1, (char *) anon_realm_str },
169 (krb5_data *) anon_princ_data, 2, KRB5_NT_WELLKNOWN
170 };
171
172 const krb5_data * KRB5_CALLCONV
krb5_anonymous_realm(void)173 krb5_anonymous_realm(void)
174 {
175 return &anon_realm_data;
176 }
177
178 krb5_const_principal KRB5_CALLCONV
krb5_anonymous_principal(void)179 krb5_anonymous_principal(void)
180 {
181 return &anon_princ;
182 }
183