1 /*
2 * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
3 * All rights reserved.
4 */
5
6 #pragma ident "@(#)gssd_pname_to_uid.c 1.19 04/09/08 SMI"
7
8 #include <pwd.h>
9 #include <grp.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <mechglueP.h>
14 #include "../../cmd/gss/gsscred/gsscred.h"
15
16 extern int _getgroupsbymember(const char *, gid_t[], int, int);
17
18 /* local function used to call a mechanisms pname_to_uid */
19 static OM_uint32 gss_pname_to_uid(OM_uint32*, const gss_name_t,
20 const gss_OID, uid_t *);
21
22 static OM_uint32 private_gsscred_expname_to_unix_cred(const gss_buffer_t,
23 uid_t *, gid_t *, gid_t **, int *);
24
25 /*
26 * The gsscred functions will first attempt to call the
27 * mechanism'm pname_to_uid function. In case this function
28 * returns an error or if it is not provided by a mechanism
29 * then the functions will attempt to look up the principal
30 * in the gsscred table.
31 * It is envisioned that the pname_to_uid function will be
32 * provided by only a few mechanism, which may have the principal
33 * name to unix credential mapping inherently present.
34 */
35
36 /*
37 * This routine accepts a name in export name format and retrieves
38 * unix credentials associated with it.
39 */
40 OM_uint32
41 gsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen)
42 const gss_buffer_t expName;
43 uid_t *uidOut;
44 gid_t *gidOut;
45 gid_t *gids[];
46 int *gidsLen;
47 {
48 gss_name_t intName;
49 OM_uint32 minor, major;
50
51 if (uidOut == NULL)
52 return (GSS_S_CALL_INACCESSIBLE_WRITE);
53
54 if (expName == NULL)
55 return (GSS_S_CALL_INACCESSIBLE_READ);
56
57 /* first check the mechanism for the mapping */
58 if (gss_import_name(&minor, expName, (gss_OID)GSS_C_NT_EXPORT_NAME,
59 &intName) == GSS_S_COMPLETE) {
60 major = gss_pname_to_uid(&minor, intName, NULL, uidOut);
61 gss_release_name(&minor, &intName);
62 if (major == GSS_S_COMPLETE) {
63 if (gids && gidsLen && gidOut)
64 return (gss_get_group_info(*uidOut, gidOut,
65 gids, gidsLen));
66 return (GSS_S_COMPLETE);
67 (void) gss_release_buffer(&minor, &namebuf);
68 }
69 (void) gss_release_name(&minor, &intName);
70 (void) gss_release_name(&minor, &intName);
71 }
72
73 /*
74 * we fall back onto the gsscred table to provide the mapping
75 * start by making sure that the expName is an export name buffer
76 */
77 return (private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut,
78 gids, gidsLen));
79 } /* gsscred_expname_to_unix_cred */
80
81
82 static const char *expNameTokId = "\x04\x01";
83 static const int expNameTokIdLen = 2;
84 /*
85 * private routine added to be called from gsscred_name_to_unix_cred
86 * and gsscred_expName_to_unix_cred.
87 */
88 static OM_uint32
89 private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen)
90 const gss_buffer_t expName;
91 uid_t *uidOut;
92 gid_t *gidOut;
93 gid_t *gids[];
94 int *gidsLen;
95 {
96
97 if (expName->length < expNameTokIdLen ||
98 (memcmp(expName->value, expNameTokId, expNameTokIdLen) != 0))
99 return (GSS_S_DEFECTIVE_TOKEN);
100
101 if (!gss_getGssCredEntry(expName, uidOut))
102 return (GSS_S_FAILURE);
103
104 /* did caller request group info also ? */
105 if (gids && gidsLen && gidOut)
106 return (gss_get_group_info(*uidOut, gidOut, gids, gidsLen));
107
108 return (GSS_S_COMPLETE);
109 }
110
111 /*
112 (void) gss_release_name(&minor, &canonName);
113 (void) gss_release_buffer(&minor, &namebuf);
114 (void) gss_release_buffer(&minor, &expName);
115 (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
116 (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
117 (void) gss_release_buffer(&minor, &expName);
118 * This routine accepts a name in gss internal name format together with
119 * a mechanim OID and retrieves a unix credentials for that entity.
120 */
121 OM_uint32
122 gsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids, gidsLen)
123 const gss_name_t intName;
124 const gss_OID mechType;
125 uid_t *uidOut;
126 gid_t *gidOut;
127 gid_t *gids[];
128 int *gidsLen;
129 {
130 gss_name_t canonName;
131 gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
132 OM_uint32 major, minor;
133
134 if (intName == NULL || mechType == NULL)
135 return (GSS_S_CALL_INACCESSIBLE_READ);
136
137 if (uidOut == NULL)
138 return (GSS_S_CALL_INACCESSIBLE_WRITE);
139
140 /* first try the mechanism provided mapping */
141 if (gss_pname_to_uid(&minor, intName, mechType, uidOut)
142 == GSS_S_COMPLETE) {
143 if (gids && gidsLen && gidOut)
144 return (gss_get_group_info(*uidOut, gidOut, gids,
145 gidsLen));
146 return (GSS_S_COMPLETE);
147 }
148
149
150 /*
151 * falling back onto the gsscred table to provide the mapping
152 * start by canonicalizing the passed in name and then export it
153 */
154 if (major = gss_canonicalize_name(&minor, intName,
155 mechType, &canonName))
156 return (major);
157
158 major = gss_export_name(&minor, canonName, &expName);
159 (void) gss_release_name(&minor, &canonName);
160 if (major)
161 return (major);
162
163 major = private_gsscred_expname_to_unix_cred(&expName, uidOut, gidOut,
164 gids, gidsLen);
165 (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
166 (void) gss_release_buffer(&minor, &namebuf);
167 (void) gss_release_buffer(&minor, &expName);
168 return (major);
169 } /* gsscred_name_to_unix_cred */
170
171
172 /*
173 * This routine accepts a unix uid, and retrieves the group id
174 * and supplamentery group ids for that uid.
175 * Callers should be aware that the supplamentary group ids
176 * array may be empty even when this function returns success.
177 */
178 OM_uint32
179 gss_get_group_info(uid, gidOut, gids, gidsLen)
180 const uid_t uid;
181 gid_t *gidOut;
182 gid_t *gids[];
183 int *gidsLen;
184 {
185 struct passwd *pw;
186 int maxgroups;
187
188 /* check for output parameters */
189 if (gidOut == NULL || gids == NULL || gidsLen == NULL)
190 return (GSS_S_CALL_INACCESSIBLE_WRITE);
191
|
1 /*
2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "@(#)gssd_pname_to_uid.c 1.18 04/02/23 SMI"
7
8 #include <pwd.h>
9 #include <grp.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <thread.h>
14 #include <synch.h>
15 #include <syslog.h>
16 #include <deflt.h>
17 #include <mechglueP.h>
18 #include "../../cmd/gss/gsscred/gsscred.h"
19
20 static mutex_t uid_map_lock = DEFAULTMUTEX;
21 static int uid_map_opt = 0;
22
23 extern int _getgroupsbymember(const char *, gid_t[], int, int);
24
25 /* local function used to call a mechanisms pname_to_uid */
26 static OM_uint32 gss_pname_to_uid(OM_uint32*, const gss_name_t,
27 const gss_OID, uid_t *);
28
29 static OM_uint32 private_gsscred_expname_to_unix_cred(const gss_buffer_t,
30 uid_t *, gid_t *, gid_t **, int *);
31
32 /*
33 * The gsscred functions will first attempt to call the
34 * mechanism'm pname_to_uid function. In case this function
35 * returns an error or if it is not provided by a mechanism
36 * then the functions will attempt to look up the principal
37 * in the gsscred table.
38 * It is envisioned that the pname_to_uid function will be
39 * provided by only a few mechanism, which may have the principal
40 * name to unix credential mapping inherently present.
41 */
42
43 /*
44 * Fetch gsscred options from conf file.
45 */
46 static void
47 get_conf_options(int *uid_map)
48 {
49 register int flags;
50 char *ptr;
51 static char *conffile = "/etc/gss/gsscred.conf";
52 static mutex_t deflt_lock = DEFAULTMUTEX;
53
54
55 *uid_map = 0;
56 /*
57 * hold the lock for the deflt file access as its
58 * interface does not appear to be mt-safe
59 */
60 (void) mutex_lock(&deflt_lock);
61 if (defopen(conffile) == 0) {
62 flags = defcntl(DC_GETFLAGS, 0);
63 /* ignore case */
64 TURNOFF(flags, DC_CASE);
65 (void) defcntl(DC_SETFLAGS, flags);
66
67 if ((ptr = defread("SYSLOG_UID_MAPPING=")) != NULL &&
68 strcasecmp("yes", ptr) == 0) {
69 (void) defopen((char *)NULL);
70 (void) mutex_unlock(&deflt_lock);
71 *uid_map = 1;
72 return;
73 }
74 (void) defopen((char *)NULL);
75 }
76 (void) mutex_unlock(&deflt_lock);
77 }
78
79 void
80 gsscred_set_options()
81 {
82 int u;
83
84 get_conf_options(&u);
85 (void) mutex_lock(&uid_map_lock);
86 uid_map_opt = u;
87 (void) mutex_unlock(&uid_map_lock);
88 }
89
90 static int
91 get_uid_map_opt()
92 {
93 int u;
94
95 (void) mutex_lock(&uid_map_lock);
96 u = uid_map_opt;
97 (void) mutex_unlock(&uid_map_lock);
98 return (u);
99 }
100
101 /*
102 * This routine accepts a name in export name format and retrieves
103 * unix credentials associated with it.
104 */
105
106 OM_uint32
107 gsscred_expname_to_unix_cred_ext(
108 const gss_buffer_t expName,
109 uid_t *uidOut,
110 gid_t *gidOut,
111 gid_t *gids[],
112 int *gidsLen,
113 int try_mech)
114 {
115 gss_name_t intName;
116 OM_uint32 minor, major;
117 const char *mechStr = NULL;
118 char *nameStr = NULL;
119 char *whoami = "gsscred_expname_to_unix_cred";
120 gss_buffer_desc namebuf;
121 int debug = get_uid_map_opt();
122
123 if (uidOut == NULL)
124 return (GSS_S_CALL_INACCESSIBLE_WRITE);
125
126 if (expName == NULL)
127 return (GSS_S_CALL_INACCESSIBLE_READ);
128
129 /* first check the mechanism for the mapping */
130 if (gss_import_name(&minor, expName, (gss_OID)GSS_C_NT_EXPORT_NAME,
131 &intName) == GSS_S_COMPLETE) {
132
133 if (debug) {
134 gss_union_name_t uintName = (gss_union_name_t)intName;
135
136 if (uintName->mech_type)
137 mechStr = __gss_oid_to_mech(
138 uintName->mech_type);
139
140 major = gss_display_name(&minor, intName,
141 &namebuf, NULL);
142 if (major == GSS_S_COMPLETE) {
143 nameStr = strdup(namebuf.value);
144 (void) gss_release_buffer(&minor, &namebuf);
145 }
146 }
147
148 if (try_mech) {
149 major = gss_pname_to_uid(&minor, intName,
150 NULL, uidOut);
151 if (major == GSS_S_COMPLETE) {
152
153 if (debug) {
154 syslog(LOG_AUTH|LOG_DEBUG,
155 "%s: mech provided local name"
156 " mapping (%s, %s, %d)", whoami,
157 mechStr ? mechStr : "<null>",
158 nameStr ? nameStr : "<null>",
159 *uidOut);
160 free(nameStr);
161 }
162
163 (void) gss_release_name(&minor, &intName);
164 if (gids && gidsLen && gidOut)
165 return (gss_get_group_info(*uidOut,
166 gidOut,
167 gids,
168 gidsLen));
169 return (GSS_S_COMPLETE);
170 }
171 }
172
173 (void) gss_release_name(&minor, &intName);
174 }
175
176 /*
177 * we fall back onto the gsscred table to provide the mapping
178 * start by making sure that the expName is an export name buffer
179 */
180 major = private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut,
181 gids, gidsLen);
182
183 if (debug && major == GSS_S_COMPLETE) {
184 syslog(LOG_AUTH|LOG_DEBUG,
185 "%s: gsscred tbl provided"
186 " local name mapping (%s, %s, %d)",
187 whoami,
188 mechStr ? mechStr : "<unknown>",
189 nameStr ? nameStr : "<unknown>",
190 *uidOut);
191 free(nameStr);
192 } else if (debug) {
193 syslog(LOG_AUTH|LOG_DEBUG,
194 "%s: gsscred tbl could NOT"
195 " provide local name mapping (%s, %s)",
196 whoami,
197 mechStr ? mechStr : "<unknown>",
198 nameStr ? nameStr : "<unknown>");
199 free(nameStr);
200 }
201
202 return (major);
203
204 } /* gsscred_expname_to_unix_cred */
205
206 OM_uint32
207 gsscred_expname_to_unix_cred(
208 const gss_buffer_t expName,
209 uid_t *uidOut,
210 gid_t *gidOut,
211 gid_t *gids[],
212 int *gidsLen)
213 {
214 return (gsscred_expname_to_unix_cred_ext(expName, uidOut, gidOut, gids,
215 gidsLen, 1));
216 }
217
218
219 static const char *expNameTokId = "\x04\x01";
220 static const int expNameTokIdLen = 2;
221 /*
222 * private routine added to be called from gsscred_name_to_unix_cred
223 * and gsscred_expName_to_unix_cred.
224 */
225 static OM_uint32
226 private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen)
227 const gss_buffer_t expName;
228 uid_t *uidOut;
229 gid_t *gidOut;
230 gid_t *gids[];
231 int *gidsLen;
232 {
233
234 if (expName->length < expNameTokIdLen ||
235 (memcmp(expName->value, expNameTokId, expNameTokIdLen) != 0))
236 return (GSS_S_DEFECTIVE_TOKEN);
237
238 if (!gss_getGssCredEntry(expName, uidOut))
239 return (GSS_S_FAILURE);
240
241 /* did caller request group info also ? */
242 if (gids && gidsLen && gidOut)
243 return (gss_get_group_info(*uidOut, gidOut, gids, gidsLen));
244
245 return (GSS_S_COMPLETE);
246 }
247
248 /*
249 * Return a string of the authenticated name.
250 * It's a bit of hack/workaround/longroad but the current intName
251 * passed to gss_display_name insists on returning an empty string.
252 *
253 * Caller must free string memory.
254 */
255 static
256 char *make_name_str(
257 const gss_name_t intName,
258 const gss_OID mechType)
259
260 {
261 gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
262 OM_uint32 major, minor;
263 gss_name_t canonName;
264 gss_name_t iName;
265 gss_buffer_desc namebuf;
266
267 if (major = gss_canonicalize_name(&minor, intName,
268 mechType, &canonName))
269 return (NULL);
270
271 major = gss_export_name(&minor, canonName, &expName);
272 (void) gss_release_name(&minor, &canonName);
273 if (major)
274 return (NULL);
275
276 if (gss_import_name(&minor, &expName,
277 (gss_OID)GSS_C_NT_EXPORT_NAME,
278 &iName) == GSS_S_COMPLETE) {
279
280 major = gss_display_name(&minor, iName, &namebuf, NULL);
281 if (major == GSS_S_COMPLETE) {
282 char *s;
283
284 if (namebuf.value)
285 s = strdup(namebuf.value);
286
287 (void) gss_release_buffer(&minor, &namebuf);
288 (void) gss_release_buffer(&minor, &expName);
289 (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
290 return (s);
291 }
292 (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
293 }
294
295 (void) gss_release_buffer(&minor, &expName);
296 return (NULL);
297 }
298
299 /*
300 * This routine accepts a name in gss internal name format together with
301 * a mechanim OID and retrieves a unix credentials for that entity.
302 */
303 OM_uint32
304 gsscred_name_to_unix_cred_ext(
305 const gss_name_t intName,
306 const gss_OID mechType,
307 uid_t *uidOut,
308 gid_t *gidOut,
309 gid_t *gids[],
310 int *gidsLen,
311 int try_mech)
312 {
313 gss_name_t canonName;
314 gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
315 OM_uint32 major, minor;
316 int debug = get_uid_map_opt();
317
318 const char *mechStr;
319 char *whoami = "gsscred_name_to_unix_cred";
320 gss_buffer_desc namebuf;
321
322 if (intName == NULL || mechType == NULL)
323 return (GSS_S_CALL_INACCESSIBLE_READ);
324
325 if (uidOut == NULL)
326 return (GSS_S_CALL_INACCESSIBLE_WRITE);
327
328 mechStr = __gss_oid_to_mech(mechType);
329
330 /* first try the mechanism provided mapping */
331 if (try_mech && gss_pname_to_uid(&minor, intName, mechType, uidOut)
332 == GSS_S_COMPLETE) {
333
334 if (debug) {
335 char *s = make_name_str(intName, mechType);
336 syslog(LOG_AUTH|LOG_DEBUG,
337 "%s: mech provided local name"
338 " mapping (%s, %s, %d)", whoami,
339 mechStr ? mechStr : "<null>",
340 s ? s : "<null>",
341 *uidOut);
342 free(s);
343 }
344
345 if (gids && gidsLen && gidOut)
346 return (gss_get_group_info(*uidOut, gidOut, gids,
347 gidsLen));
348 return (GSS_S_COMPLETE);
349 }
350 /*
351 * falling back onto the gsscred table to provide the mapping
352 * start by canonicalizing the passed in name and then export it
353 */
354 if (major = gss_canonicalize_name(&minor, intName,
355 mechType, &canonName))
356 return (major);
357
358 major = gss_export_name(&minor, canonName, &expName);
359 (void) gss_release_name(&minor, &canonName);
360 if (major)
361 return (major);
362
363 major = private_gsscred_expname_to_unix_cred(&expName, uidOut, gidOut,
364 gids, gidsLen);
365
366
367 if (debug) {
368 gss_name_t iName;
369 OM_uint32 maj;
370 char *nameStr = NULL;
371
372 if (gss_import_name(&minor, &expName,
373 (gss_OID)GSS_C_NT_EXPORT_NAME,
374 &iName) == GSS_S_COMPLETE) {
375
376 maj = gss_display_name(&minor, iName, &namebuf,
377 NULL);
378 (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
379 if (maj == GSS_S_COMPLETE) {
380 nameStr = strdup(namebuf.value);
381 (void) gss_release_buffer(&minor, &namebuf);
382 }
383 }
384
385 if (major == GSS_S_COMPLETE)
386 syslog(LOG_AUTH|LOG_DEBUG,
387 "%s: gsscred tbl provided"
388 " local name mapping (%s, %s, %d)",
389 whoami,
390 mechStr ? mechStr : "<unknown>",
391 nameStr ? nameStr : "<unknown>",
392 *uidOut);
393 else
394 syslog(LOG_AUTH|LOG_DEBUG,
395 "%s: gsscred tbl could NOT"
396 " provide local name mapping (%s, %s)",
397 whoami,
398 mechStr ? mechStr : "<unknown>",
399 nameStr ? nameStr : "<unknown>");
400
401 free(nameStr);
402 }
403
404 (void) gss_release_buffer(&minor, &expName);
405 return (major);
406 } /* gsscred_name_to_unix_cred */
407
408
409 OM_uint32
410 gsscred_name_to_unix_cred(
411 const gss_name_t intName,
412 const gss_OID mechType,
413 uid_t *uidOut,
414 gid_t *gidOut,
415 gid_t *gids[],
416 int *gidsLen)
417 {
418 return (gsscred_name_to_unix_cred_ext(intName, mechType,
419 uidOut, gidOut,
420 gids, gidsLen, 1));
421 }
422
423
424
425 /*
426 * This routine accepts a unix uid, and retrieves the group id
427 * and supplamentery group ids for that uid.
428 * Callers should be aware that the supplamentary group ids
429 * array may be empty even when this function returns success.
430 */
431 OM_uint32
432 gss_get_group_info(uid, gidOut, gids, gidsLen)
433 const uid_t uid;
434 gid_t *gidOut;
435 gid_t *gids[];
436 int *gidsLen;
437 {
438 struct passwd *pw;
439 int maxgroups;
440
441 /* check for output parameters */
442 if (gidOut == NULL || gids == NULL || gidsLen == NULL)
443 return (GSS_S_CALL_INACCESSIBLE_WRITE);
444
|