]> git.cameronkatri.com Git - pw-darwin.git/commitdiff
Make use_yp() smarter about figuring out whether a user is local or
authorBill Paul <wpaul@FreeBSD.org>
Sat, 2 Sep 1995 03:56:21 +0000 (03:56 +0000)
committerBill Paul <wpaul@FreeBSD.org>
Sat, 2 Sep 1995 03:56:21 +0000 (03:56 +0000)
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.

chpass/chpass.1
chpass/chpass.c
chpass/pw_yp.c
chpass/pw_yp.h

index 6186c7b280abeb3bab171c2fdca5dc164fc85808..a42b43ee924b4026f138d643f732c379fcc7641b 100644 (file)
@@ -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
index bba8b3d3d6cddd77905ffe7f73df567aa59dac02..ea4a55879c084ef1825bdf56786bad8ab668217b 100644 (file)
@@ -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);
 }
index 6fd87f54707944c485789881075f1502c39a0d9c..2c1c138e6254cd044820ed25a002025921b982ae 100644 (file)
@@ -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);
 }
 
 /*
index 94c7a74090d2b9c86f7233bd9824c905e469f6bd..9d98a4355ed6a4ba3fff2fd57582ab82a59a300a 100644 (file)
  * 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 */