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