1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* lib/gssapi/generic/oid_ops.c */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright 1995 by the Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert * All Rights Reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert * permission. Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
24*7f2fe78bSCy Schubert * or implied warranty.
25*7f2fe78bSCy Schubert */
26*7f2fe78bSCy Schubert /*
27*7f2fe78bSCy Schubert * Copyright 1993 by OpenVision Technologies, Inc.
28*7f2fe78bSCy Schubert *
29*7f2fe78bSCy Schubert * Permission to use, copy, modify, distribute, and sell this software
30*7f2fe78bSCy Schubert * and its documentation for any purpose is hereby granted without fee,
31*7f2fe78bSCy Schubert * provided that the above copyright notice appears in all copies and
32*7f2fe78bSCy Schubert * that both that copyright notice and this permission notice appear in
33*7f2fe78bSCy Schubert * supporting documentation, and that the name of OpenVision not be used
34*7f2fe78bSCy Schubert * in advertising or publicity pertaining to distribution of the software
35*7f2fe78bSCy Schubert * without specific, written prior permission. OpenVision makes no
36*7f2fe78bSCy Schubert * representations about the suitability of this software for any
37*7f2fe78bSCy Schubert * purpose. It is provided "as is" without express or implied warranty.
38*7f2fe78bSCy Schubert *
39*7f2fe78bSCy Schubert * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
40*7f2fe78bSCy Schubert * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
41*7f2fe78bSCy Schubert * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
42*7f2fe78bSCy Schubert * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
43*7f2fe78bSCy Schubert * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
44*7f2fe78bSCy Schubert * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
45*7f2fe78bSCy Schubert * PERFORMANCE OF THIS SOFTWARE.
46*7f2fe78bSCy Schubert */
47*7f2fe78bSCy Schubert
48*7f2fe78bSCy Schubert /* GSS-API V2 interfaces to manipulate OIDs */
49*7f2fe78bSCy Schubert
50*7f2fe78bSCy Schubert #include "gssapiP_generic.h"
51*7f2fe78bSCy Schubert #ifdef HAVE_UNISTD_H
52*7f2fe78bSCy Schubert #include <unistd.h>
53*7f2fe78bSCy Schubert #endif
54*7f2fe78bSCy Schubert #include <stdlib.h>
55*7f2fe78bSCy Schubert #include <string.h>
56*7f2fe78bSCy Schubert #include <stdio.h>
57*7f2fe78bSCy Schubert #include <gssapi/gssapi_generic.h>
58*7f2fe78bSCy Schubert #include <errno.h>
59*7f2fe78bSCy Schubert #include <ctype.h>
60*7f2fe78bSCy Schubert
61*7f2fe78bSCy Schubert /*
62*7f2fe78bSCy Schubert * The functions for allocating and releasing individual OIDs use malloc and
63*7f2fe78bSCy Schubert * free instead of the gssalloc wrappers, because the mechglue currently mixes
64*7f2fe78bSCy Schubert * generic_gss_copy_oid() with hand-freeing of OIDs. We do not need to free
65*7f2fe78bSCy Schubert * free OIDs allocated by mechanisms, so this should not be a problem.
66*7f2fe78bSCy Schubert */
67*7f2fe78bSCy Schubert
68*7f2fe78bSCy Schubert OM_uint32
generic_gss_release_oid(OM_uint32 * minor_status,gss_OID * oid)69*7f2fe78bSCy Schubert generic_gss_release_oid(OM_uint32 *minor_status, gss_OID *oid)
70*7f2fe78bSCy Schubert {
71*7f2fe78bSCy Schubert if (minor_status)
72*7f2fe78bSCy Schubert *minor_status = 0;
73*7f2fe78bSCy Schubert
74*7f2fe78bSCy Schubert if (oid == NULL || *oid == GSS_C_NO_OID)
75*7f2fe78bSCy Schubert return(GSS_S_COMPLETE);
76*7f2fe78bSCy Schubert
77*7f2fe78bSCy Schubert /*
78*7f2fe78bSCy Schubert * The V2 API says the following!
79*7f2fe78bSCy Schubert *
80*7f2fe78bSCy Schubert * gss_release_oid[()] will recognize any of the GSSAPI's own OID values,
81*7f2fe78bSCy Schubert * and will silently ignore attempts to free these OIDs; for other OIDs
82*7f2fe78bSCy Schubert * it will call the C free() routine for both the OID data and the
83*7f2fe78bSCy Schubert * descriptor. This allows applications to freely mix their own heap-
84*7f2fe78bSCy Schubert * allocated OID values with OIDs returned by GSS-API.
85*7f2fe78bSCy Schubert */
86*7f2fe78bSCy Schubert
87*7f2fe78bSCy Schubert /*
88*7f2fe78bSCy Schubert * We use the official OID definitions instead of the unofficial OID
89*7f2fe78bSCy Schubert * definitions. But we continue to support the unofficial OID
90*7f2fe78bSCy Schubert * gss_nt_service_name just in case if some gss applications use
91*7f2fe78bSCy Schubert * the old OID.
92*7f2fe78bSCy Schubert */
93*7f2fe78bSCy Schubert
94*7f2fe78bSCy Schubert if ((*oid != GSS_C_NT_USER_NAME) &&
95*7f2fe78bSCy Schubert (*oid != GSS_C_NT_MACHINE_UID_NAME) &&
96*7f2fe78bSCy Schubert (*oid != GSS_C_NT_STRING_UID_NAME) &&
97*7f2fe78bSCy Schubert (*oid != GSS_C_NT_HOSTBASED_SERVICE) &&
98*7f2fe78bSCy Schubert (*oid != GSS_C_NT_ANONYMOUS) &&
99*7f2fe78bSCy Schubert (*oid != GSS_C_NT_EXPORT_NAME) &&
100*7f2fe78bSCy Schubert (*oid != GSS_C_NT_COMPOSITE_EXPORT) &&
101*7f2fe78bSCy Schubert (*oid != gss_nt_service_name)) {
102*7f2fe78bSCy Schubert free((*oid)->elements);
103*7f2fe78bSCy Schubert free(*oid);
104*7f2fe78bSCy Schubert }
105*7f2fe78bSCy Schubert *oid = GSS_C_NO_OID;
106*7f2fe78bSCy Schubert return(GSS_S_COMPLETE);
107*7f2fe78bSCy Schubert }
108*7f2fe78bSCy Schubert
109*7f2fe78bSCy Schubert OM_uint32
generic_gss_copy_oid(OM_uint32 * minor_status,const gss_OID_desc * const oid,gss_OID * new_oid)110*7f2fe78bSCy Schubert generic_gss_copy_oid(OM_uint32 *minor_status,
111*7f2fe78bSCy Schubert const gss_OID_desc * const oid,
112*7f2fe78bSCy Schubert gss_OID *new_oid)
113*7f2fe78bSCy Schubert {
114*7f2fe78bSCy Schubert gss_OID p;
115*7f2fe78bSCy Schubert
116*7f2fe78bSCy Schubert *minor_status = 0;
117*7f2fe78bSCy Schubert
118*7f2fe78bSCy Schubert p = (gss_OID) malloc(sizeof(gss_OID_desc));
119*7f2fe78bSCy Schubert if (!p) {
120*7f2fe78bSCy Schubert *minor_status = ENOMEM;
121*7f2fe78bSCy Schubert return GSS_S_FAILURE;
122*7f2fe78bSCy Schubert }
123*7f2fe78bSCy Schubert p->length = oid->length;
124*7f2fe78bSCy Schubert p->elements = malloc(p->length);
125*7f2fe78bSCy Schubert if (!p->elements) {
126*7f2fe78bSCy Schubert free(p);
127*7f2fe78bSCy Schubert return GSS_S_FAILURE;
128*7f2fe78bSCy Schubert }
129*7f2fe78bSCy Schubert memcpy(p->elements, oid->elements, p->length);
130*7f2fe78bSCy Schubert *new_oid = p;
131*7f2fe78bSCy Schubert return(GSS_S_COMPLETE);
132*7f2fe78bSCy Schubert }
133*7f2fe78bSCy Schubert
134*7f2fe78bSCy Schubert
135*7f2fe78bSCy Schubert OM_uint32
generic_gss_create_empty_oid_set(OM_uint32 * minor_status,gss_OID_set * oid_set)136*7f2fe78bSCy Schubert generic_gss_create_empty_oid_set(OM_uint32 *minor_status, gss_OID_set *oid_set)
137*7f2fe78bSCy Schubert {
138*7f2fe78bSCy Schubert *minor_status = 0;
139*7f2fe78bSCy Schubert
140*7f2fe78bSCy Schubert if (oid_set == NULL)
141*7f2fe78bSCy Schubert return GSS_S_CALL_INACCESSIBLE_WRITE;
142*7f2fe78bSCy Schubert
143*7f2fe78bSCy Schubert if ((*oid_set = (gss_OID_set) gssalloc_malloc(sizeof(gss_OID_set_desc)))) {
144*7f2fe78bSCy Schubert memset(*oid_set, 0, sizeof(gss_OID_set_desc));
145*7f2fe78bSCy Schubert return(GSS_S_COMPLETE);
146*7f2fe78bSCy Schubert }
147*7f2fe78bSCy Schubert else {
148*7f2fe78bSCy Schubert *minor_status = ENOMEM;
149*7f2fe78bSCy Schubert return(GSS_S_FAILURE);
150*7f2fe78bSCy Schubert }
151*7f2fe78bSCy Schubert }
152*7f2fe78bSCy Schubert
153*7f2fe78bSCy Schubert OM_uint32
generic_gss_add_oid_set_member(OM_uint32 * minor_status,const gss_OID_desc * const member_oid,gss_OID_set * oid_set)154*7f2fe78bSCy Schubert generic_gss_add_oid_set_member(OM_uint32 *minor_status,
155*7f2fe78bSCy Schubert const gss_OID_desc * const member_oid,
156*7f2fe78bSCy Schubert gss_OID_set *oid_set)
157*7f2fe78bSCy Schubert {
158*7f2fe78bSCy Schubert gss_OID elist;
159*7f2fe78bSCy Schubert gss_OID lastel;
160*7f2fe78bSCy Schubert
161*7f2fe78bSCy Schubert *minor_status = 0;
162*7f2fe78bSCy Schubert
163*7f2fe78bSCy Schubert if (member_oid == NULL || member_oid->length == 0 ||
164*7f2fe78bSCy Schubert member_oid->elements == NULL)
165*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_READ);
166*7f2fe78bSCy Schubert
167*7f2fe78bSCy Schubert if (oid_set == NULL)
168*7f2fe78bSCy Schubert return GSS_S_CALL_INACCESSIBLE_WRITE;
169*7f2fe78bSCy Schubert
170*7f2fe78bSCy Schubert elist = (*oid_set)->elements;
171*7f2fe78bSCy Schubert /* Get an enlarged copy of the array */
172*7f2fe78bSCy Schubert if (((*oid_set)->elements = (gss_OID) gssalloc_malloc(((*oid_set)->count+1) *
173*7f2fe78bSCy Schubert sizeof(gss_OID_desc)))) {
174*7f2fe78bSCy Schubert /* Copy in the old junk */
175*7f2fe78bSCy Schubert if (elist)
176*7f2fe78bSCy Schubert memcpy((*oid_set)->elements,
177*7f2fe78bSCy Schubert elist,
178*7f2fe78bSCy Schubert ((*oid_set)->count * sizeof(gss_OID_desc)));
179*7f2fe78bSCy Schubert
180*7f2fe78bSCy Schubert /* Duplicate the input element */
181*7f2fe78bSCy Schubert lastel = &(*oid_set)->elements[(*oid_set)->count];
182*7f2fe78bSCy Schubert if ((lastel->elements =
183*7f2fe78bSCy Schubert (void *) gssalloc_malloc((size_t) member_oid->length))) {
184*7f2fe78bSCy Schubert /* Success - copy elements */
185*7f2fe78bSCy Schubert memcpy(lastel->elements, member_oid->elements,
186*7f2fe78bSCy Schubert (size_t) member_oid->length);
187*7f2fe78bSCy Schubert /* Set length */
188*7f2fe78bSCy Schubert lastel->length = member_oid->length;
189*7f2fe78bSCy Schubert
190*7f2fe78bSCy Schubert /* Update count */
191*7f2fe78bSCy Schubert (*oid_set)->count++;
192*7f2fe78bSCy Schubert if (elist)
193*7f2fe78bSCy Schubert gssalloc_free(elist);
194*7f2fe78bSCy Schubert *minor_status = 0;
195*7f2fe78bSCy Schubert return(GSS_S_COMPLETE);
196*7f2fe78bSCy Schubert }
197*7f2fe78bSCy Schubert else
198*7f2fe78bSCy Schubert gssalloc_free((*oid_set)->elements);
199*7f2fe78bSCy Schubert }
200*7f2fe78bSCy Schubert /* Failure - restore old contents of list */
201*7f2fe78bSCy Schubert (*oid_set)->elements = elist;
202*7f2fe78bSCy Schubert *minor_status = ENOMEM;
203*7f2fe78bSCy Schubert return(GSS_S_FAILURE);
204*7f2fe78bSCy Schubert }
205*7f2fe78bSCy Schubert
206*7f2fe78bSCy Schubert OM_uint32
generic_gss_test_oid_set_member(OM_uint32 * minor_status,const gss_OID_desc * const member,gss_OID_set set,int * present)207*7f2fe78bSCy Schubert generic_gss_test_oid_set_member(OM_uint32 *minor_status,
208*7f2fe78bSCy Schubert const gss_OID_desc * const member,
209*7f2fe78bSCy Schubert gss_OID_set set,
210*7f2fe78bSCy Schubert int * present)
211*7f2fe78bSCy Schubert {
212*7f2fe78bSCy Schubert OM_uint32 i;
213*7f2fe78bSCy Schubert int result;
214*7f2fe78bSCy Schubert
215*7f2fe78bSCy Schubert *minor_status = 0;
216*7f2fe78bSCy Schubert
217*7f2fe78bSCy Schubert if (member == NULL || set == NULL)
218*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_READ);
219*7f2fe78bSCy Schubert
220*7f2fe78bSCy Schubert if (present == NULL)
221*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
222*7f2fe78bSCy Schubert
223*7f2fe78bSCy Schubert result = 0;
224*7f2fe78bSCy Schubert for (i=0; i<set->count; i++) {
225*7f2fe78bSCy Schubert if ((set->elements[i].length == member->length) &&
226*7f2fe78bSCy Schubert !memcmp(set->elements[i].elements,
227*7f2fe78bSCy Schubert member->elements,
228*7f2fe78bSCy Schubert (size_t) member->length)) {
229*7f2fe78bSCy Schubert result = 1;
230*7f2fe78bSCy Schubert break;
231*7f2fe78bSCy Schubert }
232*7f2fe78bSCy Schubert }
233*7f2fe78bSCy Schubert *present = result;
234*7f2fe78bSCy Schubert return(GSS_S_COMPLETE);
235*7f2fe78bSCy Schubert }
236*7f2fe78bSCy Schubert
237*7f2fe78bSCy Schubert OM_uint32
generic_gss_oid_to_str(OM_uint32 * minor_status,const gss_OID_desc * const oid,gss_buffer_t oid_str)238*7f2fe78bSCy Schubert generic_gss_oid_to_str(OM_uint32 *minor_status,
239*7f2fe78bSCy Schubert const gss_OID_desc * const oid,
240*7f2fe78bSCy Schubert gss_buffer_t oid_str)
241*7f2fe78bSCy Schubert {
242*7f2fe78bSCy Schubert unsigned long number, n;
243*7f2fe78bSCy Schubert OM_uint32 i;
244*7f2fe78bSCy Schubert int first;
245*7f2fe78bSCy Schubert unsigned char *cp;
246*7f2fe78bSCy Schubert struct k5buf buf;
247*7f2fe78bSCy Schubert
248*7f2fe78bSCy Schubert if (minor_status != NULL)
249*7f2fe78bSCy Schubert *minor_status = 0;
250*7f2fe78bSCy Schubert
251*7f2fe78bSCy Schubert if (oid_str != GSS_C_NO_BUFFER) {
252*7f2fe78bSCy Schubert oid_str->length = 0;
253*7f2fe78bSCy Schubert oid_str->value = NULL;
254*7f2fe78bSCy Schubert }
255*7f2fe78bSCy Schubert
256*7f2fe78bSCy Schubert if (oid == NULL || oid->length == 0 || oid->elements == NULL)
257*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_READ);
258*7f2fe78bSCy Schubert
259*7f2fe78bSCy Schubert if (oid_str == GSS_C_NO_BUFFER)
260*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
261*7f2fe78bSCy Schubert
262*7f2fe78bSCy Schubert /* Decoded according to krb5/gssapi_krb5.c */
263*7f2fe78bSCy Schubert
264*7f2fe78bSCy Schubert cp = (unsigned char *) oid->elements;
265*7f2fe78bSCy Schubert number = (unsigned long) cp[0];
266*7f2fe78bSCy Schubert k5_buf_init_dynamic(&buf);
267*7f2fe78bSCy Schubert k5_buf_add(&buf, "{ ");
268*7f2fe78bSCy Schubert number = 0;
269*7f2fe78bSCy Schubert cp = (unsigned char *) oid->elements;
270*7f2fe78bSCy Schubert first = 1;
271*7f2fe78bSCy Schubert for (i = 0; i < oid->length; i++) {
272*7f2fe78bSCy Schubert number = (number << 7) | (cp[i] & 0x7f);
273*7f2fe78bSCy Schubert if ((cp[i] & 0x80) == 0) {
274*7f2fe78bSCy Schubert if (first) {
275*7f2fe78bSCy Schubert n = (number < 40) ? 0 : (number < 80) ? 1 : 2;
276*7f2fe78bSCy Schubert k5_buf_add_fmt(&buf, "%lu %lu ", n, number - (n * 40));
277*7f2fe78bSCy Schubert first = 0;
278*7f2fe78bSCy Schubert } else {
279*7f2fe78bSCy Schubert k5_buf_add_fmt(&buf, "%lu ", number);
280*7f2fe78bSCy Schubert }
281*7f2fe78bSCy Schubert number = 0;
282*7f2fe78bSCy Schubert }
283*7f2fe78bSCy Schubert }
284*7f2fe78bSCy Schubert k5_buf_add_len(&buf, "}\0", 2);
285*7f2fe78bSCy Schubert return k5buf_to_gss(minor_status, &buf, oid_str);
286*7f2fe78bSCy Schubert }
287*7f2fe78bSCy Schubert
288*7f2fe78bSCy Schubert /* Return the length of a DER OID subidentifier encoding. */
289*7f2fe78bSCy Schubert static size_t
arc_encoded_length(unsigned long arc)290*7f2fe78bSCy Schubert arc_encoded_length(unsigned long arc)
291*7f2fe78bSCy Schubert {
292*7f2fe78bSCy Schubert size_t len = 1;
293*7f2fe78bSCy Schubert
294*7f2fe78bSCy Schubert for (arc >>= 7; arc; arc >>= 7)
295*7f2fe78bSCy Schubert len++;
296*7f2fe78bSCy Schubert return len;
297*7f2fe78bSCy Schubert }
298*7f2fe78bSCy Schubert
299*7f2fe78bSCy Schubert /* Encode a subidentifier into *bufp and advance it to the encoding's end. */
300*7f2fe78bSCy Schubert static void
arc_encode(unsigned long arc,unsigned char ** bufp)301*7f2fe78bSCy Schubert arc_encode(unsigned long arc, unsigned char **bufp)
302*7f2fe78bSCy Schubert {
303*7f2fe78bSCy Schubert unsigned char *p;
304*7f2fe78bSCy Schubert
305*7f2fe78bSCy Schubert /* Advance to the end and encode backwards. */
306*7f2fe78bSCy Schubert p = *bufp = *bufp + arc_encoded_length(arc);
307*7f2fe78bSCy Schubert *--p = arc & 0x7f;
308*7f2fe78bSCy Schubert for (arc >>= 7; arc; arc >>= 7)
309*7f2fe78bSCy Schubert *--p = (arc & 0x7f) | 0x80;
310*7f2fe78bSCy Schubert }
311*7f2fe78bSCy Schubert
312*7f2fe78bSCy Schubert /* Fetch an arc value from *bufp and advance past it and any following spaces
313*7f2fe78bSCy Schubert * or periods. Return 1 on success, 0 if *bufp is not at a valid arc value. */
314*7f2fe78bSCy Schubert static int
get_arc(const unsigned char ** bufp,const unsigned char * end,unsigned long * arc_out)315*7f2fe78bSCy Schubert get_arc(const unsigned char **bufp, const unsigned char *end,
316*7f2fe78bSCy Schubert unsigned long *arc_out)
317*7f2fe78bSCy Schubert {
318*7f2fe78bSCy Schubert const unsigned char *p = *bufp;
319*7f2fe78bSCy Schubert unsigned long arc = 0, newval;
320*7f2fe78bSCy Schubert
321*7f2fe78bSCy Schubert if (p == end || !isdigit(*p))
322*7f2fe78bSCy Schubert return 0;
323*7f2fe78bSCy Schubert for (; p < end && isdigit(*p); p++) {
324*7f2fe78bSCy Schubert newval = arc * 10 + (*p - '0');
325*7f2fe78bSCy Schubert if (newval < arc)
326*7f2fe78bSCy Schubert return 0;
327*7f2fe78bSCy Schubert arc = newval;
328*7f2fe78bSCy Schubert }
329*7f2fe78bSCy Schubert while (p < end && (isspace(*p) || *p == '.'))
330*7f2fe78bSCy Schubert p++;
331*7f2fe78bSCy Schubert *bufp = p;
332*7f2fe78bSCy Schubert *arc_out = arc;
333*7f2fe78bSCy Schubert return 1;
334*7f2fe78bSCy Schubert }
335*7f2fe78bSCy Schubert
336*7f2fe78bSCy Schubert /*
337*7f2fe78bSCy Schubert * Convert a sequence of two or more decimal arc values into a DER-encoded OID.
338*7f2fe78bSCy Schubert * The values may be separated by any combination of whitespace and period
339*7f2fe78bSCy Schubert * characters, and may be optionally surrounded with braces. Leading
340*7f2fe78bSCy Schubert * whitespace and trailing garbage is allowed. The first arc value must be 0,
341*7f2fe78bSCy Schubert * 1, or 2, and the second value must be less than 40 if the first value is not
342*7f2fe78bSCy Schubert * 2.
343*7f2fe78bSCy Schubert */
344*7f2fe78bSCy Schubert OM_uint32
generic_gss_str_to_oid(OM_uint32 * minor_status,gss_buffer_t oid_str,gss_OID * oid_out)345*7f2fe78bSCy Schubert generic_gss_str_to_oid(OM_uint32 *minor_status,
346*7f2fe78bSCy Schubert gss_buffer_t oid_str,
347*7f2fe78bSCy Schubert gss_OID *oid_out)
348*7f2fe78bSCy Schubert {
349*7f2fe78bSCy Schubert const unsigned char *p, *end, *arc3_start;
350*7f2fe78bSCy Schubert unsigned char *out;
351*7f2fe78bSCy Schubert unsigned long arc, arc1, arc2;
352*7f2fe78bSCy Schubert size_t nbytes;
353*7f2fe78bSCy Schubert int brace = 0;
354*7f2fe78bSCy Schubert gss_OID oid;
355*7f2fe78bSCy Schubert
356*7f2fe78bSCy Schubert if (minor_status != NULL)
357*7f2fe78bSCy Schubert *minor_status = 0;
358*7f2fe78bSCy Schubert
359*7f2fe78bSCy Schubert if (oid_out != NULL)
360*7f2fe78bSCy Schubert *oid_out = GSS_C_NO_OID;
361*7f2fe78bSCy Schubert
362*7f2fe78bSCy Schubert if (GSS_EMPTY_BUFFER(oid_str))
363*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_READ);
364*7f2fe78bSCy Schubert
365*7f2fe78bSCy Schubert if (oid_out == NULL)
366*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
367*7f2fe78bSCy Schubert
368*7f2fe78bSCy Schubert /* Skip past initial spaces and, optionally, an open brace. */
369*7f2fe78bSCy Schubert brace = 0;
370*7f2fe78bSCy Schubert p = oid_str->value;
371*7f2fe78bSCy Schubert end = p + oid_str->length;
372*7f2fe78bSCy Schubert while (p < end && isspace(*p))
373*7f2fe78bSCy Schubert p++;
374*7f2fe78bSCy Schubert if (p < end && *p == '{') {
375*7f2fe78bSCy Schubert brace = 1;
376*7f2fe78bSCy Schubert p++;
377*7f2fe78bSCy Schubert }
378*7f2fe78bSCy Schubert while (p < end && isspace(*p))
379*7f2fe78bSCy Schubert p++;
380*7f2fe78bSCy Schubert
381*7f2fe78bSCy Schubert /* Get the first two arc values, to be encoded as one subidentifier. */
382*7f2fe78bSCy Schubert if (!get_arc(&p, end, &arc1) || !get_arc(&p, end, &arc2))
383*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
384*7f2fe78bSCy Schubert if (arc1 > 2 || (arc1 < 2 && arc2 > 39) || arc2 > ULONG_MAX - 80)
385*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
386*7f2fe78bSCy Schubert arc3_start = p;
387*7f2fe78bSCy Schubert
388*7f2fe78bSCy Schubert /* Compute the total length of the encoding while checking syntax. */
389*7f2fe78bSCy Schubert nbytes = arc_encoded_length(arc1 * 40 + arc2);
390*7f2fe78bSCy Schubert while (get_arc(&p, end, &arc))
391*7f2fe78bSCy Schubert nbytes += arc_encoded_length(arc);
392*7f2fe78bSCy Schubert if (brace && (p == end || *p != '}'))
393*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
394*7f2fe78bSCy Schubert
395*7f2fe78bSCy Schubert /* Allocate an oid structure. */
396*7f2fe78bSCy Schubert oid = malloc(sizeof(*oid));
397*7f2fe78bSCy Schubert if (oid == NULL)
398*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
399*7f2fe78bSCy Schubert oid->elements = malloc(nbytes);
400*7f2fe78bSCy Schubert if (oid->elements == NULL) {
401*7f2fe78bSCy Schubert free(oid);
402*7f2fe78bSCy Schubert return (GSS_S_FAILURE);
403*7f2fe78bSCy Schubert }
404*7f2fe78bSCy Schubert oid->length = nbytes;
405*7f2fe78bSCy Schubert
406*7f2fe78bSCy Schubert out = oid->elements;
407*7f2fe78bSCy Schubert arc_encode(arc1 * 40 + arc2, &out);
408*7f2fe78bSCy Schubert p = arc3_start;
409*7f2fe78bSCy Schubert while (get_arc(&p, end, &arc))
410*7f2fe78bSCy Schubert arc_encode(arc, &out);
411*7f2fe78bSCy Schubert assert(out - nbytes == oid->elements);
412*7f2fe78bSCy Schubert *oid_out = oid;
413*7f2fe78bSCy Schubert return(GSS_S_COMPLETE);
414*7f2fe78bSCy Schubert }
415*7f2fe78bSCy Schubert
416*7f2fe78bSCy Schubert /* Compose an OID of a prefix and an integer suffix */
417*7f2fe78bSCy Schubert OM_uint32
generic_gss_oid_compose(OM_uint32 * minor_status,const char * prefix,size_t prefix_len,int suffix,gss_OID_desc * oid)418*7f2fe78bSCy Schubert generic_gss_oid_compose(OM_uint32 *minor_status,
419*7f2fe78bSCy Schubert const char *prefix,
420*7f2fe78bSCy Schubert size_t prefix_len,
421*7f2fe78bSCy Schubert int suffix,
422*7f2fe78bSCy Schubert gss_OID_desc *oid)
423*7f2fe78bSCy Schubert {
424*7f2fe78bSCy Schubert int osuffix, i;
425*7f2fe78bSCy Schubert size_t nbytes;
426*7f2fe78bSCy Schubert unsigned char *op;
427*7f2fe78bSCy Schubert
428*7f2fe78bSCy Schubert if (oid == GSS_C_NO_OID) {
429*7f2fe78bSCy Schubert *minor_status = EINVAL;
430*7f2fe78bSCy Schubert return GSS_S_FAILURE;
431*7f2fe78bSCy Schubert }
432*7f2fe78bSCy Schubert if (oid->length < prefix_len) {
433*7f2fe78bSCy Schubert *minor_status = ERANGE;
434*7f2fe78bSCy Schubert return GSS_S_FAILURE;
435*7f2fe78bSCy Schubert }
436*7f2fe78bSCy Schubert
437*7f2fe78bSCy Schubert memcpy(oid->elements, prefix, prefix_len);
438*7f2fe78bSCy Schubert
439*7f2fe78bSCy Schubert nbytes = 0;
440*7f2fe78bSCy Schubert osuffix = suffix;
441*7f2fe78bSCy Schubert while (suffix) {
442*7f2fe78bSCy Schubert nbytes++;
443*7f2fe78bSCy Schubert suffix >>= 7;
444*7f2fe78bSCy Schubert }
445*7f2fe78bSCy Schubert suffix = osuffix;
446*7f2fe78bSCy Schubert
447*7f2fe78bSCy Schubert if (oid->length < prefix_len + nbytes) {
448*7f2fe78bSCy Schubert *minor_status = ERANGE;
449*7f2fe78bSCy Schubert return GSS_S_FAILURE;
450*7f2fe78bSCy Schubert }
451*7f2fe78bSCy Schubert
452*7f2fe78bSCy Schubert op = (unsigned char *) oid->elements + prefix_len + nbytes;
453*7f2fe78bSCy Schubert i = -1;
454*7f2fe78bSCy Schubert while (suffix) {
455*7f2fe78bSCy Schubert op[i] = (unsigned char)suffix & 0x7f;
456*7f2fe78bSCy Schubert if (i != -1)
457*7f2fe78bSCy Schubert op[i] |= 0x80;
458*7f2fe78bSCy Schubert i--;
459*7f2fe78bSCy Schubert suffix >>= 7;
460*7f2fe78bSCy Schubert }
461*7f2fe78bSCy Schubert
462*7f2fe78bSCy Schubert oid->length = prefix_len + nbytes;
463*7f2fe78bSCy Schubert
464*7f2fe78bSCy Schubert *minor_status = 0;
465*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
466*7f2fe78bSCy Schubert }
467*7f2fe78bSCy Schubert
468*7f2fe78bSCy Schubert OM_uint32
generic_gss_oid_decompose(OM_uint32 * minor_status,const char * prefix,size_t prefix_len,gss_OID_desc * oid,int * suffix)469*7f2fe78bSCy Schubert generic_gss_oid_decompose(OM_uint32 *minor_status,
470*7f2fe78bSCy Schubert const char *prefix,
471*7f2fe78bSCy Schubert size_t prefix_len,
472*7f2fe78bSCy Schubert gss_OID_desc *oid,
473*7f2fe78bSCy Schubert int *suffix)
474*7f2fe78bSCy Schubert {
475*7f2fe78bSCy Schubert size_t i, slen;
476*7f2fe78bSCy Schubert unsigned char *op;
477*7f2fe78bSCy Schubert
478*7f2fe78bSCy Schubert if (oid->length < prefix_len ||
479*7f2fe78bSCy Schubert memcmp(oid->elements, prefix, prefix_len) != 0) {
480*7f2fe78bSCy Schubert return GSS_S_BAD_MECH;
481*7f2fe78bSCy Schubert }
482*7f2fe78bSCy Schubert
483*7f2fe78bSCy Schubert op = (unsigned char *) oid->elements + prefix_len;
484*7f2fe78bSCy Schubert
485*7f2fe78bSCy Schubert *suffix = 0;
486*7f2fe78bSCy Schubert
487*7f2fe78bSCy Schubert slen = oid->length - prefix_len;
488*7f2fe78bSCy Schubert
489*7f2fe78bSCy Schubert for (i = 0; i < slen; i++) {
490*7f2fe78bSCy Schubert *suffix = (*suffix << 7) | (op[i] & 0x7f);
491*7f2fe78bSCy Schubert if (i + 1 != slen && (op[i] & 0x80) == 0) {
492*7f2fe78bSCy Schubert *minor_status = EINVAL;
493*7f2fe78bSCy Schubert return GSS_S_FAILURE;
494*7f2fe78bSCy Schubert }
495*7f2fe78bSCy Schubert }
496*7f2fe78bSCy Schubert
497*7f2fe78bSCy Schubert return GSS_S_COMPLETE;
498*7f2fe78bSCy Schubert }
499*7f2fe78bSCy Schubert
500*7f2fe78bSCy Schubert OM_uint32
generic_gss_copy_oid_set(OM_uint32 * minor_status,const gss_OID_set_desc * const oidset,gss_OID_set * new_oidset)501*7f2fe78bSCy Schubert generic_gss_copy_oid_set(OM_uint32 *minor_status,
502*7f2fe78bSCy Schubert const gss_OID_set_desc * const oidset,
503*7f2fe78bSCy Schubert gss_OID_set *new_oidset)
504*7f2fe78bSCy Schubert {
505*7f2fe78bSCy Schubert gss_OID_set_desc *copy;
506*7f2fe78bSCy Schubert OM_uint32 minor = 0;
507*7f2fe78bSCy Schubert OM_uint32 major = GSS_S_COMPLETE;
508*7f2fe78bSCy Schubert OM_uint32 i;
509*7f2fe78bSCy Schubert
510*7f2fe78bSCy Schubert if (minor_status != NULL)
511*7f2fe78bSCy Schubert *minor_status = 0;
512*7f2fe78bSCy Schubert
513*7f2fe78bSCy Schubert if (new_oidset != NULL)
514*7f2fe78bSCy Schubert *new_oidset = GSS_C_NO_OID_SET;
515*7f2fe78bSCy Schubert
516*7f2fe78bSCy Schubert if (oidset == GSS_C_NO_OID_SET)
517*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_READ);
518*7f2fe78bSCy Schubert
519*7f2fe78bSCy Schubert if (new_oidset == NULL)
520*7f2fe78bSCy Schubert return (GSS_S_CALL_INACCESSIBLE_WRITE);
521*7f2fe78bSCy Schubert
522*7f2fe78bSCy Schubert if ((copy = (gss_OID_set_desc *) gssalloc_calloc(1, sizeof (*copy))) == NULL) {
523*7f2fe78bSCy Schubert major = GSS_S_FAILURE;
524*7f2fe78bSCy Schubert goto done;
525*7f2fe78bSCy Schubert }
526*7f2fe78bSCy Schubert
527*7f2fe78bSCy Schubert if ((copy->elements = (gss_OID_desc *)
528*7f2fe78bSCy Schubert gssalloc_calloc(oidset->count, sizeof (*copy->elements))) == NULL) {
529*7f2fe78bSCy Schubert major = GSS_S_FAILURE;
530*7f2fe78bSCy Schubert goto done;
531*7f2fe78bSCy Schubert }
532*7f2fe78bSCy Schubert copy->count = oidset->count;
533*7f2fe78bSCy Schubert
534*7f2fe78bSCy Schubert for (i = 0; i < copy->count; i++) {
535*7f2fe78bSCy Schubert gss_OID_desc *out = ©->elements[i];
536*7f2fe78bSCy Schubert gss_OID_desc *in = &oidset->elements[i];
537*7f2fe78bSCy Schubert
538*7f2fe78bSCy Schubert if ((out->elements = (void *) gssalloc_malloc(in->length)) == NULL) {
539*7f2fe78bSCy Schubert major = GSS_S_FAILURE;
540*7f2fe78bSCy Schubert goto done;
541*7f2fe78bSCy Schubert }
542*7f2fe78bSCy Schubert (void) memcpy(out->elements, in->elements, in->length);
543*7f2fe78bSCy Schubert out->length = in->length;
544*7f2fe78bSCy Schubert }
545*7f2fe78bSCy Schubert
546*7f2fe78bSCy Schubert *new_oidset = copy;
547*7f2fe78bSCy Schubert done:
548*7f2fe78bSCy Schubert if (major != GSS_S_COMPLETE) {
549*7f2fe78bSCy Schubert (void) generic_gss_release_oid_set(&minor, ©);
550*7f2fe78bSCy Schubert }
551*7f2fe78bSCy Schubert
552*7f2fe78bSCy Schubert return (major);
553*7f2fe78bSCy Schubert }
554