[BACK]Return to ids.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rsync

Diff for /src/usr.bin/rsync/ids.c between version 1.4 and 1.5

version 1.4, 2019/02/12 19:39:57 version 1.5, 2019/02/14 18:26:52
Line 17 
Line 17 
 #include <assert.h>  #include <assert.h>
 #include <grp.h>  #include <grp.h>
 #include <inttypes.h>  #include <inttypes.h>
   #include <pwd.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
Line 41 
Line 42 
 }  }
   
 /*  /*
  * Given a list of files with the groups as set by the sender, re-assign   * Given a list of files with the identifiers as set by the sender,
  * the groups from the list of remapped group identifiers.   * re-assign the identifiers from the list of remapped ones.
  * Don't ever remap group wheel.   * Don't ever remap wheel/root.
  */   */
 void  void
 idents_gid_assign(struct sess *sess, struct flist *fl, size_t flsz,  idents_assign_gid(struct sess *sess, struct flist *fl, size_t flsz,
         const struct ident *gids, size_t gidsz)          const struct ident *ids, size_t idsz)
 {  {
         size_t   i, j;          size_t   i, j;
   
         for (i = 0; i < flsz; i++) {          for (i = 0; i < flsz; i++) {
                 if (0 == fl[i].st.gid)                  if (fl[i].st.gid == 0)
                         continue;                          continue;
                 for (j = 0; j < gidsz; j++)                  for (j = 0; j < idsz; j++)
                         if ((int32_t)fl[i].st.gid == gids[j].id)                          if ((int32_t)fl[i].st.gid == ids[j].id)
                                 break;                                  break;
                 assert(j < gidsz);                  assert(j < idsz);
                 fl[i].st.gid = gids[j].mapped;                  fl[i].st.gid = ids[j].mapped;
         }          }
 }  }
   
 /*  /*
  * Given a list of groups from the remote host, fill in our local   * Like idents_assign_gid().
    */
   void
   idents_assign_uid(struct sess *sess, struct flist *fl, size_t flsz,
           const struct ident *ids, size_t idsz)
   {
           size_t   i, j;
   
           for (i = 0; i < flsz; i++) {
                   if (fl[i].st.uid == 0)
                           continue;
                   for (j = 0; j < idsz; j++)
                           if ((int32_t)fl[i].st.uid == ids[j].id)
                                   break;
                   assert(j < idsz);
                   fl[i].st.uid = ids[j].mapped;
           }
   }
   
   /*
    * Given a list of identifiers from the remote host, fill in our local
  * identifiers of the same names.   * identifiers of the same names.
  * Use the remote numeric identifier if we can't find the group OR the   * Use the remote numeric identifier if we can't find the identifier OR
  * group has identifier zero.   * the identifier is zero (wheel/root).
  * FIXME: what happens if we don't find the local group (we should   * FIXME: what happens if we don't find the local identifier (we should
  * really warn about this), but the remote group identifier maps into a   * really warn about this), but the remote identifier maps into a
  * different group name for us?   * different name for us?
  * These are pretty unexpected things for rsync to do.   * These are pretty unexpected things for rsync to do.
  * Another FIXME because we shouldn't let that happen even though the   * Another FIXME because we shouldn't let that happen even though the
  * reference rsync does.   * reference rsync does.
  */   */
 void  void
 idents_gid_remap(struct sess *sess, struct ident *gids, size_t gidsz)  idents_remap(struct sess *sess, int isgid, struct ident *ids, size_t idsz)
 {  {
         size_t           i;          size_t           i;
         struct group    *grp;          struct group    *grp;
           struct passwd   *usr;
           int32_t          id;
   
         for (i = 0; i < gidsz; i++) {          for (i = 0; i < idsz; i++) {
                 assert(gids[i].id != 0);                  assert(ids[i].id != 0);
   
                   /* Start by getting our local representation. */
   
                   if (isgid)
                           id = (grp = getgrnam(ids[i].name)) == NULL ?
                                   -1 : grp->gr_gid;
                   else
                           id = (usr = getpwnam(ids[i].name)) == NULL ?
                                   -1 : usr->pw_uid;
   
                 /*                  /*
                  * (1) Empty names inherit.                   * (1) Empty names inherit.
                  * (2) Unknown group names inherit.                   * (2) Unknown identifier names inherit.
                  * (3) Group wheel inherits.                   * (3) Wheel/root inherits.
                  * (4) Otherwise, use the local identifier.                   * (4) Otherwise, use the local identifier.
                  */                   */
   
                 if (gids[i].name[0] == '\0')                  if (ids[i].name[0] == '\0')
                         gids[i].mapped = gids[i].id;                          ids[i].mapped = ids[i].id;
                 else if ((grp = getgrnam(gids[i].name)) == NULL)                  else if (id <= 0)
                         gids[i].mapped = gids[i].id;                          ids[i].mapped = ids[i].id;
                 else if (grp->gr_gid == 0)  
                         gids[i].mapped = gids[i].id;  
                 else                  else
                         gids[i].mapped = grp->gr_gid;                          ids[i].mapped = id;
   
                 LOG4(sess, "remapped group %s: %" PRId32 " -> %" PRId32,                  LOG4(sess, "remapped identifier %s: %" PRId32 " -> %" PRId32,
                         gids[i].name, gids[i].id, gids[i].mapped);                          ids[i].name, ids[i].id, ids[i].mapped);
         }          }
 }  }
   
 /*  /*
  * If "gid" is not part of the list of known groups, add it.   * If "id" is not part of the list of known users or groups (depending
  * This also verifies that the group name isn't too long.   * upon "isgid", add it.
  * Does nothing with group zero.   * This also verifies that the name isn't too long.
    * Does nothing with user/group zero.
  * Return zero on failure, non-zero on success.   * Return zero on failure, non-zero on success.
  */   */
 int  int
 idents_gid_add(struct sess *sess, struct ident **gids, size_t *gidsz, gid_t gid)  idents_add(struct sess *sess, int isgid,
           struct ident **ids, size_t *idsz, int32_t id)
 {  {
         struct group    *grp;          struct group    *grp;
           struct passwd   *usr;
         size_t           i, sz;          size_t           i, sz;
         void            *pp;          void            *pp;
           const char      *name;
   
         if (gid == 0)          if (id == 0)
                 return 1;                  return 1;
   
         for (i = 0; i < *gidsz; i++)          for (i = 0; i < *idsz; i++)
                 if ((*gids)[i].id == (int32_t)gid)                  if ((*ids)[i].id == id)
                         return 1;                          return 1;
   
         /*          /*
          * Look us up in /etc/group.           * Look up the reference in a type-specific way.
          * Make sure that the group name length is sane: we transmit it           * Make sure that the name length is sane: we transmit it using
          * using a single byte.           * a single byte.
          */           */
   
         assert(i == *gidsz);          assert(i == *idsz);
         if ((grp = getgrgid(gid)) == NULL) {          if (isgid) {
                 ERR(sess, "%u: unknown gid", gid);                  if ((grp = getgrgid((gid_t)id)) == NULL) {
                           ERR(sess, "%" PRId32 ": unknown gid", id);
                           return 0;
                   }
                   name = grp->gr_name;
           } else {
                   if ((usr = getpwuid((uid_t)id)) == NULL) {
                           ERR(sess, "%" PRId32 ": unknown uid", id);
                           return 0;
                   }
                   name = usr->pw_name;
           }
   
           if ((sz = strlen(name)) > UINT8_MAX) {
                   ERRX(sess, "%" PRId32 ": name too long: %s", id, name);
                 return 0;                  return 0;
         } else if ((sz = strlen(grp->gr_name)) > UINT8_MAX) {  
                 ERRX(sess, "%u: group name too long: %s", gid, grp->gr_name);  
                 return 0;  
         } else if (sz == 0) {          } else if (sz == 0) {
                 ERRX(sess, "%u: group name zero-length", gid);                  ERRX(sess, "%" PRId32 ": zero-length name", id);
                 return 0;                  return 0;
         }          }
   
         /* Add the group to the array. */          /* Add the identifier to the array. */
   
         pp = reallocarray(*gids, *gidsz + 1, sizeof(struct ident));          pp = reallocarray(*ids, *idsz + 1, sizeof(struct ident));
         if (pp == NULL) {          if (pp == NULL) {
                 ERR(sess, "reallocarray");                  ERR(sess, "reallocarray");
                 return 0;                  return 0;
         }          }
         *gids = pp;          *ids = pp;
         (*gids)[*gidsz].id = gid;          (*ids)[*idsz].id = id;
         (*gids)[*gidsz].name = strdup(grp->gr_name);          (*ids)[*idsz].name = strdup(name);
         if (NULL == (*gids)[*gidsz].name) {          if ((*ids)[*idsz].name == NULL) {
                 ERR(sess, "strdup");                  ERR(sess, "strdup");
                 return 0;                  return 0;
         }          }
   
         LOG4(sess, "adding group to list: %s (%u)",          LOG4(sess, "adding identifier to list: %s (%u)",
                 (*gids)[*gidsz].name, (*gids)[*gidsz].id);                  (*ids)[*idsz].name, (*ids)[*idsz].id);
         (*gidsz)++;          (*idsz)++;
         return 1;          return 1;
 }  }
   
Line 231 
Line 276 
                 memset(&(*ids)[*idsz], 0, sizeof(struct ident));                  memset(&(*ids)[*idsz], 0, sizeof(struct ident));
   
                 /*                  /*
                  * When reading the size, warn if we get a group size of                   * When reading the size, warn if we get a size of zero.
                  * zero.  
                  * The spec doesn't allow this, but we might have a                   * The spec doesn't allow this, but we might have a
                  * noncomformant or adversarial sender.                   * noncomformant or adversarial sender.
                  */                   */
Line 240 
Line 284 
                 if (!io_read_byte(sess, fd, &sz)) {                  if (!io_read_byte(sess, fd, &sz)) {
                         ERRX1(sess, "io_read_byte");                          ERRX1(sess, "io_read_byte");
                         return 0;                          return 0;
                 } else if (0 == sz)                  } else if (sz == 0)
                         WARNX(sess, "zero-length group name "                          WARNX(sess, "zero-length name "
                                 "in group list");                                  "in identifier list");
   
                 (*ids)[*idsz].id = id;                  (*ids)[*idsz].id = id;
                 (*ids)[*idsz].name = calloc(sz + 1, 1);                  (*ids)[*idsz].name = calloc(sz + 1, 1);

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5