1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 *
31 * gsscred utility
32 * Manages mapping between a security principal name and unix uid
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <ctype.h>
40 #include "gsscred.h"
41
42 /* From g_glue.c */
43
44 extern int
45 get_der_length(unsigned char **, unsigned int, unsigned int *);
46
47 extern unsigned int
48 der_length_size(unsigned int);
49
50 extern int
51 put_der_length(unsigned int, unsigned char **, unsigned int);
52
53
54
55 /*
56 * GSS export name constants
57 */
58 static const char *expNameTokId = "\x04\x01";
59 static const int expNameTokIdLen = 2;
60 static const int mechOidLenLen = 2;
61 static const int mechOidTagLen = 1;
62
63
64 /*
65 * Internal utility routines.
66 */
67
68 /*
69 * gsscred_read_config_file
70 *
71 * function to read the optional gsscred configuration file
72 * which specifies which backend to use to store the gsscred
73 * table.
74 *
75 * we now only support flat files (btw, this file for backend is Obsoleted
76 * by PSARC)
77 */
78 int
gsscred_read_config_file(void)79 gsscred_read_config_file(void)
80 {
81 return (GSSCRED_FLAT_FILE);
82 } /* gsscred_read_config_file */
83
84
85 /*
86 * gsscred_MakeName
87 *
88 * construct a principal name in the GSS_C_NT_EXPORT_NAME format.
89 */
gsscred_MakeName(const gss_OID mechOid,const char * name,const char * nameOidStr,gss_buffer_t nameOut)90 int gsscred_MakeName(const gss_OID mechOid, const char *name,
91 const char *nameOidStr, gss_buffer_t nameOut)
92 {
93 gss_OID nameOid;
94 gss_name_t intName;
95 OM_uint32 minor, major;
96 gss_buffer_desc aName = GSS_C_EMPTY_BUFFER, oidStr;
97
98 nameOut->length = 0;
99 nameOut->value = NULL;
100
101 /* we need to import the name, then canonicalize it, then export it */
102 if (nameOidStr == NULL)
103 nameOid = (gss_OID)GSS_C_NT_USER_NAME;
104 else {
105 oidStr.length = strlen(nameOidStr);
106 oidStr.value = (void *)nameOidStr;
107 if (gss_str_to_oid(&minor, &oidStr, &nameOid) !=
108 GSS_S_COMPLETE) {
109 (void) fprintf(stderr,
110 gettext("\nInvalid name oid supplied [%s].\n"),
111 nameOidStr);
112 return (0);
113 }
114 }
115
116 /* first import the name */
117 aName.length = strlen(name);
118 aName.value = (void*)name;
119 major = gss_import_name(&minor, &aName, nameOid, &intName);
120 if (nameOidStr != NULL) {
121 free(nameOid->elements);
122 free(nameOid);
123 }
124
125 if (major != GSS_S_COMPLETE) {
126 (void) fprintf(stderr,
127 gettext("\nInternal error importing name [%s].\n"),
128 name);
129 return (0);
130 }
131
132 /* now canonicalize the name */
133 if (gss_canonicalize_name(&minor, intName, mechOid, NULL)
134 != GSS_S_COMPLETE) {
135 (void) fprintf(stderr,
136 gettext("\nInternal error canonicalizing name"
137 " [%s].\n"),
138 name);
139 (void) gss_release_name(&minor, &intName);
140 return (0);
141 }
142
143 /* now convert to export format */
144 if (gss_export_name(&minor, intName, nameOut) != GSS_S_COMPLETE) {
145 (void) fprintf(stderr,
146 gettext("\nInternal error exporting name [%s].\n"),
147 name);
148 (void) gss_release_name(&minor, &intName);
149 return (0);
150 }
151
152 (void) gss_release_name(&minor, &intName);
153 return (1);
154 } /* ******* makeName ****** */
155
156
157 /*
158 * Constructs a part of the GSS_NT_EXPORT_NAME
159 * Only the mechanism independent name part is created.
160 */
161 int
gsscred_MakeNameHeader(const gss_OID mechOid,gss_buffer_t outNameHdr)162 gsscred_MakeNameHeader(const gss_OID mechOid, gss_buffer_t outNameHdr)
163 {
164 unsigned char *buf = NULL;
165 int mechOidDERLength, mechOidLength;
166
167 /* determine the length of buffer needed */
168 mechOidDERLength = der_length_size(mechOid->length);
169 outNameHdr->length = mechOidLenLen + mechOidTagLen +
170 mechOidDERLength + expNameTokIdLen + mechOid->length;
171 if ((outNameHdr->value = (void*)malloc(outNameHdr->length)) == NULL) {
172 outNameHdr->length = 0;
173 return (0);
174 }
175
176 /* start by putting the token id */
177 buf = (unsigned char *) outNameHdr->value;
178 (void) memset(outNameHdr->value, '\0', outNameHdr->length);
179 (void) memcpy(buf, expNameTokId, expNameTokIdLen);
180 buf += expNameTokIdLen;
181
182 /*
183 * next 2 bytes contain the mech oid length (includes
184 * DER encoding)
185 */
186 mechOidLength = mechOidTagLen + mechOidDERLength +
187 mechOid->length;
188
189 *buf++ = (mechOidLength & 0xFF00) >> 8;
190 *buf++ = (mechOidLength & 0x00FF);
191 *buf++ = 0x06;
192 if (put_der_length(mechOid->length, &buf,
193 mechOidDERLength) != 0) {
194 /* free the buffer */
195 free(outNameHdr->value);
196 return (0);
197 }
198
199 /* now add the mechanism oid */
200 (void) memcpy(buf, mechOid->elements, mechOid->length);
201
202 /* we stop here because the rest is mechanism specific */
203 return (1);
204 } /* gsscred_MakeNameHeader */
205
206
207 /*
208 * Converts the supplied string to HEX.
209 * The passed in buffer must be twice as long as the input buffer.
210 * Long form is used (i.e. '\0' will become '00'). This is needed
211 * to enable proper re-parsing of names.
212 */
213 int
gsscred_AsHex(gss_buffer_t dataIn,gss_buffer_t dataOut)214 gsscred_AsHex(gss_buffer_t dataIn, gss_buffer_t dataOut)
215 {
216 int i;
217 char *out, *in;
218 unsigned int tmp;
219
220 if (dataOut->length < ((dataIn->length *2) + 1))
221 return (0);
222
223 out = (char *)dataOut->value;
224 in = (char *)dataIn->value;
225 dataOut->length = 0;
226
227 for (i = 0; i < dataIn->length; i++) {
228 tmp = (unsigned int)(*in++)&0xff;
229 (void) sprintf(out, "%02X", tmp);
230 out++;
231 out++;
232 }
233 dataOut->length = out - (char *)dataOut->value;
234 *out = '\0';
235
236 return (1);
237 } /* ******* gsscred_AsHex ******* */
238
239
240 /*
241 * GSS entry point for retrieving user uid mappings.
242 * The name buffer contains a principal name in exported format.
243 */
244 int
gss_getGssCredEntry(const gss_buffer_t expName,uid_t * uid)245 gss_getGssCredEntry(const gss_buffer_t expName, uid_t *uid)
246 {
247 int tableSource;
248 unsigned char *buf;
249 gss_buffer_desc mechOidDesc = GSS_C_EMPTY_BUFFER,
250 mechHexOidDesc = GSS_C_EMPTY_BUFFER,
251 expNameHexDesc = GSS_C_EMPTY_BUFFER;
252 char oidHexBuf[256], expNameHexBuf[1024];
253 unsigned int dummy;
254 int len;
255
256 tableSource = gsscred_read_config_file();
257
258 /*
259 * for xfn (ldap?), we must first construct, a hex mechansim oid string
260 */
261 if (expName->length < (expNameTokIdLen + mechOidLenLen +
262 mechOidTagLen))
263 return (0);
264
265 buf = (unsigned char *)expName->value;
266 buf += expNameTokIdLen;
267
268 /* skip oid length - get to der */
269 buf++;
270 buf++;
271
272 /* skip oid tag */
273 buf++;
274
275 /* get oid length */
276 len = get_der_length(&buf,
277 (expName->length - expNameTokIdLen
278 - mechOidLenLen - mechOidTagLen), &dummy);
279 if (len == -1)
280 return (0);
281 else
282 mechOidDesc.length = len;
283
284 if (expName->length <
285 (expNameTokIdLen + mechOidLenLen + mechOidDesc.length
286 + dummy+ mechOidTagLen))
287 return (0);
288
289 mechOidDesc.value = (void *)buf;
290
291 /* convert the oid buffer to hex */
292 mechHexOidDesc.value = (void*) oidHexBuf;
293 mechHexOidDesc.length = sizeof (oidHexBuf);
294 if (!gsscred_AsHex(&mechOidDesc, &mechHexOidDesc))
295 return (0);
296
297 /* also need to convert the name buffer into hex */
298 expNameHexDesc.value = expNameHexBuf;
299 expNameHexDesc.length = sizeof (expNameHexBuf);
300 if (!gsscred_AsHex(expName, &expNameHexDesc))
301 return (0);
302
303 if (tableSource == GSSCRED_FLAT_FILE)
304 return (file_getGssCredUid(&expNameHexDesc, uid));
305
306 return (0); /* XXX for new backends (ldap, dss), 0->1 probably */
307 } /* gss_getGssCredEntry */
308