summaryrefslogtreecommitdiffstats
path: root/chpass
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>1995-09-02 03:56:21 +0000
committerBill Paul <wpaul@FreeBSD.org>1995-09-02 03:56:21 +0000
commit30955b898350ac476a47d83662e9679de21eb4e0 (patch)
treefe85eaa8e0b56e1f3b289fcd543dab08a04dd2e6 /chpass
parent73f5cfe48aa896d40905726d22fe1354a0608d6a (diff)
downloadpw-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.
Diffstat (limited to 'chpass')
-rw-r--r--chpass/chpass.123
-rw-r--r--chpass/chpass.c55
-rw-r--r--chpass/pw_yp.c145
-rw-r--r--chpass/pw_yp.h9
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 */