Subject: Re: Hesiod uid maps
To: Michael Graff <explorer@flame.org>
From: Greg Hudson <ghudson@MIT.EDU>
List: tech-userlevel
Date: 03/07/1999 15:47:21
> Do you really want a function that is marked as "internal to..." to
> have a weak alias?  I may not fully understand the purpose of this,
> but I thoght it was to allow us to provide a function but allow it
> to be overridden at link time.

Hm.  The intention was that if the application has its own
hesiod__uidresolve function which does something completely different,
getpwuid() shouldn't break.  Thus the namespace.h addition.  Having
the weak alias there shouldn't be necessary, I suppose.

I could also just name it _hesiod_uidresolve() and ignore namespace.h.
That might be better.  (The Athena distribution will name it
hesiod__uidresolve(), however, since a non-system library can't safely
use symbols beginning with an underscore.)

*** /mit/netbsd/src/lib/libc/net/hesiod.c	Tue Mar  2 17:48:41 1999
--- hesiod.c	Sun Mar  7 15:45:40 1999
***************
*** 83,92 ****
  __weak_alias(hes_free,_hes_free);
  #endif
  
  struct hesiod_p {
! 	char	*lhs;			/* normally ".ns" */
! 	char	*rhs;			/* AKA the default hesiod domain */
! 	int	 classes[2];		/* The class search order. */
  };
  
  #define	MAX_HESRESP	1024
--- 83,99 ----
  __weak_alias(hes_free,_hes_free);
  #endif
  
+ /* Athena uses the "uid" hesiod type for uid lookups.  Ultrix uses the
+  * "passwd" type.  Some constants for the compatibility code.
+  */
+ #define UIDMAP_UID    "uid"
+ #define UIDMAP_PASSWD "passwd"
+ 
  struct hesiod_p {
! 	char		*lhs;		/* normally ".ns" */
! 	char		*rhs;		/* AKA the default hesiod domain */
! 	int	 	classes[2];	/* The class search order */
! 	const char	*uidmaps[2];	/* The uid map search order */
  };
  
  #define	MAX_HESRESP	1024
***************
*** 259,264 ****
--- 266,284 ----
  	return retvec;
  }
  
+ /* Internal function for getpwent.c. */
+ char **_hesiod_uidresolve(void *context, const char *uidstr)
+ {
+ 	struct hesiod_p *ctx = (struct hesiod_p *) context;
+ 	char **retvec;
+ 
+ 	retvec = hesiod_resolve(context, uidstr, ctx->uidmaps[0]);
+ 	if (retvec == NULL && errno == ENOENT && ctx->uidmaps[1])
+ 		retvec = hesiod_resolve(context, uidstr, ctx->uidmaps[1]);
+ 
+ 	return retvec;
+ }
+ 
  /*ARGSUSED*/
  void 
  hesiod_free_list(context, list)
***************
*** 294,299 ****
--- 314,323 ----
  	ctx->classes[0] = C_IN;
  	ctx->classes[1] = C_HS;
  
+ 		/* Set default uid maps. */
+ 	ctx->uidmaps[0] = UIDMAP_UID;
+ 	ctx->uidmaps[1] = NULL;
+ 
  		/* Try to open the configuration file. */
  	fp = fopen(filename, "r");
  	if (!fp) {
***************
*** 355,367 ****
  				}
  				while (n < 2)
  					ctx->classes[n++] = 0;
  			}
  		}
  	}
  	fclose(fp);
  
  	if (!ctx->rhs || ctx->classes[0] == 0 ||
! 	    ctx->classes[0] == ctx->classes[1]) {
  		errno = ENOEXEC;
  		return -1;
  	}
--- 379,412 ----
  				}
  				while (n < 2)
  					ctx->classes[n++] = 0;
+ 			} else if (strcasecmp(key, "uidmaps") == 0) {
+ 				n = 0;
+ 				while (*data && n < 2) {
+ 					p = data;
+ 					while (*p && *p != ',')
+ 						p++;
+ 					if (*p)
+ 						*p++ = 0;
+ 					if (strcasecmp(data, "uid") == 0)
+ 						ctx->uidmaps[n++] = UIDMAP_UID;
+ 					else if (strcasecmp(data,
+ 							    "passwd") == 0)
+ 						ctx->uidmaps[n++] =
+ 						    UIDMAP_PASSWD;
+ 					data = p;
+ 				}
+ 				while (n < 2)
+ 					ctx->uidmaps[n++] = NULL;
  			}
  		}
  	}
  	fclose(fp);
  
+ 		/* Make sure that the rhs is set and that the class search
+ 		 * order and the uidmap search order both make sense. */
  	if (!ctx->rhs || ctx->classes[0] == 0 ||
! 	    ctx->classes[0] == ctx->classes[1] || ctx->uidmaps[0] == 0 ||
! 	    ctx->uidmaps[0] == ctx->uidmaps[1]) {
  		errno = ENOEXEC;
  		return -1;
  	}
*** /mit/netbsd/src/lib/libc/gen/getpwent.c	Fri Jan 29 16:40:12 1999
--- getpwent.c	Sun Mar  7 15:45:53 1999
***************
*** 83,88 ****
--- 83,89 ----
  __weak_alias(setpwent,_setpwent);
  #endif
  
+ extern char **_hesiod_uidresolve __P((void *, const char *));
  
  /*
   * The lookup techniques and data extraction code here must be kept
***************
*** 450,456 ****
  	uid_t		  uid;
  	int		  search;
  
- 	char		 *map;
  	char		**hp;
  	void		 *context;
  	int		  r;
--- 451,456 ----
***************
*** 460,476 ****
  	case _PW_KEYBYNUM:
  		snprintf(line, sizeof(line) - 1, "passwd-%u", _pw_hesnum);
  		_pw_hesnum++;
- 		map = "passwd";
  		break;
  	case _PW_KEYBYNAME:
  		name = va_arg(ap, const char *);
  		strncpy(line, name, sizeof(line));
- 		map = "passwd";
  		break;
  	case _PW_KEYBYUID:
  		uid = va_arg(ap, uid_t);
  		snprintf(line, sizeof(line), "%u", (unsigned int)uid);
- 		map = "uid";		/* XXX this is `passwd' on ultrix */
  		break;
  	default:
  		abort();
--- 460,473 ----
***************
*** 481,487 ****
  	if (hesiod_init(&context) == -1)
  		return (r);
  
! 	hp = hesiod_resolve(context, line, map);
  	if (hp == NULL) {
  		if (errno == ENOENT) {
  			if (search == _PW_KEYBYNUM) {
--- 478,487 ----
  	if (hesiod_init(&context) == -1)
  		return (r);
  
! 	if (search == _PW_KEYBYUID)
! 		hp = _hesiod_uidresolve(context, line);
! 	else
! 		hp = hesiod_resolve(context, line, "passwd");
  	if (hp == NULL) {
  		if (errno == ENOENT) {
  			if (search == _PW_KEYBYNUM) {