diff options
author | Bill Paul <wpaul@FreeBSD.org> | 1995-09-02 03:56:21 +0000 |
---|---|---|
committer | Bill Paul <wpaul@FreeBSD.org> | 1995-09-02 03:56:21 +0000 |
commit | 30955b898350ac476a47d83662e9679de21eb4e0 (patch) | |
tree | fe85eaa8e0b56e1f3b289fcd543dab08a04dd2e6 | |
parent | 73f5cfe48aa896d40905726d22fe1354a0608d6a (diff) | |
download | pw-darwin-30955b898350ac476a47d83662e9679de21eb4e0.tar.gz pw-darwin-30955b898350ac476a47d83662e9679de21eb4e0.tar.zst pw-darwin-30955b898350ac476a47d83662e9679de21eb4e0.zip |
Make use_yp() smarter about figuring out whether a user is local or
NIS (or both, or neither). Also add support for -l and -y flags to
force behavior to local or NIS. use_yp() also goes out of its way to
retrieve the correct password database information (local or NIS)
depending on what the situation since getpwent() & co. can't
necessarily be trusted in some cases.
Also document new flags in man page.
-rw-r--r-- | chpass/chpass.1 | 23 | ||||
-rw-r--r-- | chpass/chpass.c | 55 | ||||
-rw-r--r-- | chpass/pw_yp.c | 145 | ||||
-rw-r--r-- | chpass/pw_yp.h | 9 |
4 files changed, 202 insertions, 30 deletions
diff --git a/chpass/chpass.1 b/chpass/chpass.1 index 6186c7b..a42b43e 100644 --- a/chpass/chpass.1 +++ b/chpass/chpass.1 @@ -56,7 +56,7 @@ The information is formatted and supplied to an editor for changes. Only the information that the user is allowed to change is displayed. .Pp The options are as follows: -.Bl -tag -width Ds +.Bl -tag -width flag .It Fl a The super-user is allowed to directly supply a user database entry, in the format specified by @@ -271,6 +271,27 @@ otherwise .Xr yppasswdd 8 will refuse to update the NIS maps. .El +.Pp +There are also two extra option flags that are available when +.Nm chpass +is compiles with NIS support: +.Bl -tag -width flag +.It Fl l +The +.Fl l +flag forces +.Nm chpass +to modify the local copy of a user's password +information in the even that a user exists in both +the local and NIS databases. +.It Fl y +This flag has the opposite effect of +.Fl l . +This flag is largely redundant since +.Nm chpass +operates on NIS entries by default if NIS is enabled. +.El +.Pp .Sh FILES .Bl -tag -width /etc/master.passwd -compact .It Pa /etc/master.passwd diff --git a/chpass/chpass.c b/chpass/chpass.c index bba8b3d..ea4a558 100644 --- a/chpass/chpass.c +++ b/chpass/chpass.c @@ -40,7 +40,7 @@ static char copyright[] = #ifndef lint static char sccsid[] = "From: @(#)chpass.c 8.4 (Berkeley) 4/2/94"; static char rcsid[] = - "$Id: chpass.c,v 1.3 1995/05/30 06:29:36 rgrimes Exp $"; + "$Id: chpass.c,v 1.4 1995/08/13 16:12:24 wpaul Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -85,9 +85,17 @@ main(argc, argv) struct passwd *pw, lpw; int ch, pfd, tfd; char *arg; +#ifdef YP + int force_local = 0; + int force_yp = 0; +#endif op = EDITENTRY; +#ifdef YP + while ((ch = getopt(argc, argv, "a:p:s:ly")) != EOF) +#else while ((ch = getopt(argc, argv, "a:p:s:")) != EOF) +#endif switch(ch) { case 'a': op = LOADENTRY; @@ -101,6 +109,14 @@ main(argc, argv) op = NEWPW; arg = optarg; break; +#ifdef YP + case 'l': + force_local = 1; + break; + case 'y': + force_yp = 1; + break; +#endif case '?': default: usage(); @@ -152,20 +168,29 @@ main(argc, argv) } #ifdef YP - /* - * XXX The man page says the data returned by getpwent() - * and friends is stored in static buffers that may be - * overwritten after successive invokations. Unfortunately, - * we need to call getpwent() more than once with NIS - * enabled. - */ pw->pw_name = strdup(pw->pw_name); - pw->pw_passwd = strdup(pw->pw_passwd); - pw->pw_class = strdup(pw->pw_class); - pw->pw_gecos = strdup(pw->pw_gecos); - pw->pw_shell = strdup(pw->pw_shell); - pw->pw_dir = strdup(pw->pw_dir); _use_yp = use_yp(pw->pw_name); + if (_use_yp == USER_YP_ONLY) { + if (!force_local) { + _use_yp = 1; + pw = (struct passwd *)&yp_password; + } else + errx(1, "unknown local user: %s.", pw->pw_name); + } else if (_use_yp == USER_LOCAL_ONLY) { + if (!force_yp) { + _use_yp = 0; + pw = (struct passwd *)&local_password; + } else + errx(1, "unknown NIS user: %s.", pw->pw_name); + } else if (_use_yp == USER_YP_AND_LOCAL) { + if (!force_local) { + _use_yp = 1; + pw = (struct passwd *)&yp_password; + } else { + _use_yp = 0; + pw = (struct passwd *)&local_password; + } + } #endif /* YP */ /* @@ -231,6 +256,10 @@ usage() { (void)fprintf(stderr, +#ifdef YP + "usage: chpass [-l] [-y] [-a list] [-p encpass] [-s shell] [user]\n"); +#else "usage: chpass [-a list] [-p encpass] [-s shell] [user]\n"); +#endif exit(1); } diff --git a/chpass/pw_yp.c b/chpass/pw_yp.c index 6fd87f5..2c1c138 100644 --- a/chpass/pw_yp.c +++ b/chpass/pw_yp.c @@ -35,7 +35,7 @@ * Center for Telecommunications Research * Columbia University, New York City * - * $Id$ + * $Id: pw_yp.c,v 1.1 1995/08/13 16:12:27 wpaul Exp $ */ #ifdef YP @@ -75,42 +75,157 @@ HASHINFO openinfo = { int _use_yp = 0; +/* Save the local and NIS password information */ +struct passwd local_password; +struct passwd yp_password; + + +void copy_yp_pass(p, x, m) +char *p; +int x, m; +{ + register char *t, *s = p; + + yp_password.pw_fields = 0; + + t = (char *)malloc(m + 10); + + /* Turn all colons into NULLs */ + while (strchr(s, ':')) { + s = (strchr(s, ':') + 1); + *(s - 1)= '\0'; + } + +#define EXPAND(e) e = t; while (*t++ = *p++); + EXPAND(yp_password.pw_name); + yp_password.pw_fields |= _PWF_NAME; + EXPAND(yp_password.pw_passwd); + yp_password.pw_fields |= _PWF_PASSWD; + yp_password.pw_uid = atoi(p); + p += (strlen(p) + 1); + yp_password.pw_fields |= _PWF_UID; + yp_password.pw_gid = atoi(p); + p += (strlen(p) + 1); + yp_password.pw_fields |= _PWF_GID; + if (x) { + EXPAND(yp_password.pw_class); + yp_password.pw_fields |= _PWF_CLASS; + yp_password.pw_change = atol(p); + p += (strlen(p) + 1); + yp_password.pw_fields |= _PWF_CHANGE; + yp_password.pw_expire = atol(p); + p += (strlen(p) + 1); + yp_password.pw_expire |= _PWF_EXPIRE; + } + EXPAND(yp_password.pw_gecos); + yp_password.pw_fields |= _PWF_GECOS; + EXPAND(yp_password.pw_dir); + yp_password.pw_fields |= _PWF_DIR; + EXPAND(yp_password.pw_shell); + yp_password.pw_fields |= _PWF_SHELL; + + return; +} + +void copy_local_pass(p,m) +char *p; +int m; +{ + register char *t; + + t = (char *)malloc(m + 10); + + EXPAND(local_password.pw_name); + EXPAND(local_password.pw_passwd); + bcopy(p, (char *)&local_password.pw_uid, sizeof(int)); + p += sizeof(int); + bcopy(p, (char *)&local_password.pw_gid, sizeof(int)); + p += sizeof(int); + bcopy(p, (char *)&local_password.pw_change, sizeof(time_t)); + p += sizeof(time_t); + EXPAND(local_password.pw_class); + EXPAND(local_password.pw_gecos); + EXPAND(local_password.pw_dir); + EXPAND(local_password.pw_shell); + bcopy(p, (char *)&local_password.pw_expire, sizeof(time_t)); + p += sizeof(time_t); + bcopy(p, (char *)&local_password.pw_fields, sizeof local_password.pw_fields); + p += sizeof local_password.pw_fields; + + return; +} + /* * Check if the user we're working with is local or in NIS. */ int use_yp (user) char *user; { - int yp_enabled = 0, user_not_local = 0, exists = 0; + int user_local = 0, user_yp = 0, user_exists = 0; DB *dbp; DBT key,data; char bf[UT_NAMESIZE + 2]; + char *domain; + char *result; + int resultlen, rval; + + + /* Is the user anywhere */ + if (getpwnam(user) != NULL) + user_exists = 1; - if ((dbp = dbopen(_PATH_MP_DB, O_RDONLY, PERM_SECURE, + if ((dbp = dbopen(_PATH_SMP_DB, O_RDONLY, PERM_SECURE, DB_HASH, &openinfo)) == NULL) errx(1, "error opening database: %s.", _PATH_MP_DB); + + /* Is NIS turned on */ bf[0] = _PW_KEYYPENABLED; key.data = (u_char *)bf; key.size = 1; - if (!(dbp->get)(dbp,&key,&data,0)) - yp_enabled = 1; + if (!(dbp->get)(dbp,&key,&data,0)) { + if ((rval = yp_get_default_domain(&domain))) { + warnx("can't get local NIS domain name: %s",yperr_string(rval)); + pw_error(NULL, 0, 1); + } + + /* Is the user in the NIS passwd map */ + if (!yp_match(domain, "passwd.byname", user, strlen(user), + &result, &resultlen)) { + user_yp = 1; + copy_yp_pass(result, 0, resultlen); + free(result); + } + /* Is the user in the NIS passwd map */ + if (user_yp && !yp_match(domain, "master.passwd.byname", + user, strlen(user), + &result, &resultlen)) { + copy_yp_pass(result, 1, resultlen); + } + free(result); + } + + /* Is the user in the local password database */ bf[0] = _PW_KEYBYNAME; bcopy((char *)user, bf + 1, MIN(strlen(user), UT_NAMESIZE)); key.data = (u_char *)bf; key.size = strlen(user) + 1; - if ((dbp->get)(dbp,&key,&data,0)) - user_not_local = 1; - - (dbp->close)(dbp); + if (!(dbp->get)(dbp,&key,&data,0)) { + user_local = 1; + copy_local_pass(data.data, data.size); + } - if (getpwnam(user) != NULL) - exists = 1; + (dbp->close)(dbp); - if (yp_enabled && user_not_local && exists) - return(1); - else - return(0); + if (user_local && user_yp && user_exists) + return(USER_YP_AND_LOCAL); + else if (!user_local && user_yp && user_exists) + return(USER_YP_ONLY); + else if (user_local && !user_yp && user_exists) + return(USER_LOCAL_ONLY); + else if (!user_exists) + return(USER_UNKNOWN); + return(-1); } /* diff --git a/chpass/pw_yp.h b/chpass/pw_yp.h index 94c7a74..9d98a43 100644 --- a/chpass/pw_yp.h +++ b/chpass/pw_yp.h @@ -35,11 +35,18 @@ * Center for Telecommunications Research * Columbia University, New York City * - * $Id$ + * $Id: pw_yp.h,v 1.1 1995/08/13 16:12:28 wpaul Exp $ */ #ifdef YP +/* Four possible return codes from use_yp() */ +#define USER_UNKNOWN 0 +#define USER_YP_ONLY 1 +#define USER_LOCAL_ONLY 2 +#define USER_YP_AND_LOCAL 3 extern int _use_yp; +extern struct passwd local_password; +extern struct passwd yp_password; void yp_submit __P(( struct passwd * )); int use_yp __P(( char * )); #endif /* YP */ |