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

Annotation of src/usr.bin/rsync/ids.c, Revision 1.2

1.2     ! benno       1: /*     $Id: ids.c,v 1.1 2019/02/12 19:08:29 benno Exp $ */
1.1       benno       2: /*
                      3:  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: #include <assert.h>
                     18: #include <grp.h>
                     19: #include <inttypes.h>
                     20: #include <stdio.h>
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23: #include <unistd.h>
                     24:
                     25: #include "extern.h"
                     26:
                     27: /*
                     28:  * Free a list of struct ident previously allocated with idents_gid_add().
                     29:  * Does nothing if the pointer is NULL.
                     30:  */
                     31: void
                     32: idents_free(struct ident *p, size_t sz)
                     33: {
                     34:        size_t   i;
                     35:
                     36:        if (NULL == p)
                     37:                return;
                     38:        for (i = 0; i < sz; i++)
                     39:                free(p[i].name);
                     40:        free(p);
                     41: }
                     42:
                     43: /*
                     44:  * Given a list of groups from the remote host, fill in our local
                     45:  * identifiers of the same names.
                     46:  * Use the remote numeric identifier if we can't find the group OR the
                     47:  * group has identifier zero.
1.2     ! benno      48:  * FIXME: what happens if we don't find the local group (we should
        !            49:  * really warn about this), but the remote group identifier maps into a
        !            50:  * different group name for us?
        !            51:  * These are pretty unexpected things for rsync to do.
        !            52:  * Another FIXME because we shouldn't let that happen even though the
        !            53:  * reference rsync does.
1.1       benno      54:  */
                     55: void
                     56: idents_gid_remap(struct sess *sess, struct ident *gids, size_t gidsz)
                     57: {
                     58:        size_t           i;
                     59:        struct group    *grp;
                     60:
                     61:        for (i = 0; i < gidsz; i++) {
                     62:                if (NULL == (grp = getgrnam(gids[i].name)))
                     63:                        gids[i].mapped = gids[i].id;
                     64:                else if (0 == grp->gr_gid)
                     65:                        gids[i].mapped = gids[i].id;
                     66:                else
                     67:                        gids[i].mapped = grp->gr_gid;
1.2     ! benno      68:
1.1       benno      69:                LOG4(sess, "remapped group %s: %" PRId32 " -> %" PRId32,
                     70:                        gids[i].name, gids[i].id, gids[i].mapped);
                     71:        }
                     72: }
                     73:
                     74: /*
                     75:  * If "gid" is not part of the list of known groups, add it.
                     76:  * This also verifies that the group name isn't too long.
                     77:  * Return zero on failure, non-zero on success.
                     78:  */
                     79: int
                     80: idents_gid_add(struct sess *sess, struct ident **gids, size_t *gidsz, gid_t gid)
                     81: {
                     82:        struct group    *grp;
                     83:        size_t           i, sz;
                     84:        void            *pp;
                     85:
                     86:        for (i = 0; i < *gidsz; i++)
                     87:                if ((*gids)[i].id == (int32_t)gid)
                     88:                        return 1;
                     89:
                     90:        /*
                     91:         * Look us up in /etc/group.
                     92:         * Make sure that the group name length is sane: we transmit it
                     93:         * using a single byte.
                     94:         */
                     95:
                     96:        assert(i == *gidsz);
                     97:        if (NULL == (grp = getgrgid(gid))) {
                     98:                ERR(sess, "%u: unknown gid", gid);
                     99:                return 0;
                    100:        } else if ((sz = strlen(grp->gr_name)) > UINT8_MAX) {
                    101:                ERRX(sess, "%u: group name too long: %s", gid, grp->gr_name);
                    102:                return 0;
                    103:        } else if (0 == sz) {
                    104:                ERRX(sess, "%u: group name zero-length", gid);
                    105:                return 0;
                    106:        }
                    107:
                    108:        /* Add the group to the array. */
                    109:
                    110:        pp = reallocarray(*gids, *gidsz + 1, sizeof(struct ident));
                    111:        if (NULL == pp) {
                    112:                ERR(sess, "reallocarray");
                    113:                return 0;
                    114:        }
                    115:        *gids = pp;
                    116:        (*gids)[*gidsz].id = gid;
                    117:        (*gids)[*gidsz].name = strdup(grp->gr_name);
                    118:        if (NULL == (*gids)[*gidsz].name) {
                    119:                ERR(sess, "strdup");
                    120:                return 0;
                    121:        }
                    122:
                    123:        LOG4(sess, "adding group to list: %s (%u)",
                    124:                (*gids)[*gidsz].name, (*gids)[*gidsz].id);
                    125:        (*gidsz)++;
                    126:        return 1;
                    127: }
                    128:
                    129: /*
                    130:  * Send a list of struct ident.
                    131:  * See idents_recv().
                    132:  * We should only do this if we're preserving gids/uids.
                    133:  * Return zero on failure, non-zero on success.
                    134:  */
                    135: int
                    136: idents_send(struct sess *sess,
                    137:        int fd, const struct ident *ids, size_t idsz)
                    138: {
                    139:        size_t   i, sz;
                    140:
                    141:        for (i = 0; i < idsz; i++) {
                    142:                assert(NULL != ids[i].name);
                    143:                sz = strlen(ids[i].name);
                    144:                assert(sz > 0 && sz <= UINT8_MAX);
                    145:                if (!io_write_int(sess, fd, ids[i].id)) {
                    146:                        ERRX1(sess, "io_write_int");
                    147:                        return 0;
                    148:                } else if (!io_write_byte(sess, fd, sz)) {
                    149:                        ERRX1(sess, "io_write_byte");
                    150:                        return 0;
                    151:                } else if (!io_write_buf(sess, fd, ids[i].name, sz)) {
                    152:                        ERRX1(sess, "io_write_byte");
                    153:                        return 0;
                    154:                }
                    155:        }
                    156:
                    157:        if (!io_write_int(sess, fd, 0)) {
                    158:                ERRX1(sess, "io_write_int");
                    159:                return 0;
                    160:        }
                    161:
                    162:        return 1;
                    163: }
                    164:
                    165: /*
                    166:  * Receive a list of struct ident.
                    167:  * See idents_send().
                    168:  * We should only do this if we're preserving gids/uids.
                    169:  * Return zero on failure, non-zero on success.
                    170:  */
                    171: int
                    172: idents_recv(struct sess *sess,
                    173:        int fd, struct ident **ids, size_t *idsz)
                    174: {
                    175:        int32_t  id;
                    176:        uint8_t  sz;
                    177:        void    *pp;
                    178:
                    179:        for (;;) {
                    180:                if (!io_read_int(sess, fd, &id)) {
                    181:                        ERRX1(sess, "io_read_int");
                    182:                        return 0;
                    183:                } else if (0 == id)
                    184:                        break;
                    185:
                    186:                pp = reallocarray(*ids,
                    187:                        *idsz + 1, sizeof(struct ident));
                    188:                if (NULL == pp) {
                    189:                        ERR(sess, "reallocarray");
                    190:                        return 0;
                    191:                }
                    192:                *ids = pp;
                    193:                memset(&(*ids)[*idsz], 0, sizeof(struct ident));
                    194:                if (!io_read_byte(sess, fd, &sz)) {
                    195:                        ERRX1(sess, "io_read_byte");
                    196:                        return 0;
                    197:                }
                    198:                (*ids)[*idsz].id = id;
                    199:                (*ids)[*idsz].name = calloc(sz + 1, 1);
                    200:                if (NULL == (*ids)[*idsz].name) {
                    201:                        ERR(sess, "calloc");
                    202:                        return 0;
                    203:                }
                    204:                if (!io_read_buf(sess, fd, (*ids)[*idsz].name, sz)) {
                    205:                        ERRX1(sess, "io_read_buf");
                    206:                        return 0;
                    207:                }
                    208:                (*idsz)++;
                    209:        }
                    210:
                    211:        return 1;
                    212: }