xref: /freebsd/crypto/krb5/src/lib/krb5/krb/bld_princ.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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