Sdiff gssd_pname_to_uid.c
  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