[BACK]Return to server-acl.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/server-acl.c, Revision 1.1

1.1     ! nicm        1: /* $OpenBSD$ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2021 Holland Schutte, Jayson Morberg
        !             5:  * Copyright (c) 2021 Dallas Lyons <dallasdlyons@gmail.com>
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
        !            16:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
        !            17:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19:
        !            20: #include <sys/types.h>
        !            21: #include <sys/stat.h>
        !            22: #include <sys/socket.h>
        !            23:
        !            24: #include <ctype.h>
        !            25: #include <pwd.h>
        !            26: #include <stdlib.h>
        !            27: #include <string.h>
        !            28: #include <unistd.h>
        !            29:
        !            30: #include "tmux.h"
        !            31:
        !            32: struct server_acl_user {
        !            33:        uid_t                           uid;
        !            34:
        !            35:        int                             flags;
        !            36: #define SERVER_ACL_READONLY 0x1
        !            37:
        !            38:        RB_ENTRY(server_acl_user)       entry;
        !            39: };
        !            40:
        !            41: static int
        !            42: server_acl_cmp(struct server_acl_user *user1, struct server_acl_user *user2)
        !            43: {
        !            44:        if (user1->uid < user2->uid)
        !            45:                return -1;
        !            46:        return user1->uid > user2->uid;
        !            47: }
        !            48:
        !            49: RB_HEAD(server_acl_entries, server_acl_user) server_acl_entries;
        !            50: RB_GENERATE_STATIC(server_acl_entries, server_acl_user, entry, server_acl_cmp);
        !            51:
        !            52: /* Initialize server_acl tree. */
        !            53: void
        !            54: server_acl_init(void)
        !            55: {
        !            56:        RB_INIT(&server_acl_entries);
        !            57:
        !            58:        if (getuid() != 0)
        !            59:                server_acl_user_allow(0);
        !            60:        server_acl_user_allow(getuid());
        !            61: }
        !            62:
        !            63: /* Find user entry. */
        !            64: struct server_acl_user*
        !            65: server_acl_user_find(uid_t uid)
        !            66: {
        !            67:        struct server_acl_user  find = { .uid = uid };
        !            68:
        !            69:        return RB_FIND(server_acl_entries, &server_acl_entries, &find);
        !            70: }
        !            71:
        !            72: /* Display the tree. */
        !            73: void
        !            74: server_acl_display(struct cmdq_item *item)
        !            75: {
        !            76:        struct server_acl_user  *loop;
        !            77:        struct passwd           *pw;
        !            78:        const char              *name;
        !            79:
        !            80:        RB_FOREACH(loop, server_acl_entries, &server_acl_entries) {
        !            81:                if (loop->uid == 0)
        !            82:                        continue;
        !            83:                if ((pw = getpwuid(loop->uid)) != NULL)
        !            84:                        name = pw->pw_name;
        !            85:                else
        !            86:                        name = "unknown";
        !            87:                if (loop->flags == SERVER_ACL_READONLY)
        !            88:                        cmdq_print(item, "%s (R)", name);
        !            89:                else
        !            90:                        cmdq_print(item, "%s (W)", name);
        !            91:        }
        !            92: }
        !            93:
        !            94: /* Allow a user. */
        !            95: void
        !            96: server_acl_user_allow(uid_t uid)
        !            97: {
        !            98:        struct server_acl_user  *user;
        !            99:
        !           100:        user = server_acl_user_find(uid);
        !           101:        if (user == NULL) {
        !           102:                user = xcalloc(1, sizeof *user);
        !           103:                user->uid = uid;
        !           104:                RB_INSERT(server_acl_entries, &server_acl_entries, user);
        !           105:        }
        !           106: }
        !           107:
        !           108: /* Deny a user (remove from the tree). */
        !           109: void
        !           110: server_acl_user_deny(uid_t uid)
        !           111: {
        !           112:        struct server_acl_user  *user;
        !           113:
        !           114:        user = server_acl_user_find(uid);
        !           115:        if (user != NULL) {
        !           116:                RB_REMOVE(server_acl_entries, &server_acl_entries, user);
        !           117:                free(user);
        !           118:        }
        !           119: }
        !           120:
        !           121: /* Allow this user write access. */
        !           122: void
        !           123: server_acl_user_allow_write(uid_t uid)
        !           124: {
        !           125:        struct server_acl_user  *user;
        !           126:        struct client           *c;
        !           127:
        !           128:        user = server_acl_user_find(uid);
        !           129:        if (user == NULL)
        !           130:                return;
        !           131:        user->flags &= ~SERVER_ACL_READONLY;
        !           132:
        !           133:        TAILQ_FOREACH(c, &clients, entry) {
        !           134:                uid = proc_get_peer_uid(c->peer);
        !           135:                if (uid != (uid_t)-1 && uid == user->uid)
        !           136:                        c->flags &= ~CLIENT_READONLY;
        !           137:        }
        !           138: }
        !           139:
        !           140: /* Deny this user write access. */
        !           141: void
        !           142: server_acl_user_deny_write(uid_t uid)
        !           143: {
        !           144:        struct server_acl_user  *user;
        !           145:        struct client           *c;
        !           146:
        !           147:        user = server_acl_user_find(uid);
        !           148:        if (user == NULL)
        !           149:                return;
        !           150:        user->flags |= SERVER_ACL_READONLY;
        !           151:
        !           152:        TAILQ_FOREACH(c, &clients, entry) {
        !           153:                uid = proc_get_peer_uid(c->peer);
        !           154:                if (uid != (uid_t)-1 && uid == user->uid)
        !           155:                        c->flags |= CLIENT_READONLY;
        !           156:        }
        !           157: }
        !           158:
        !           159: /*
        !           160:  * Check if the client's UID exists in the ACL list and if so, set as read only
        !           161:  * if needed. Return false if the user does not exist.
        !           162:  */
        !           163: int
        !           164: server_acl_join(struct client *c)
        !           165: {
        !           166:        struct server_acl_user  *user;
        !           167:        uid_t                    uid;
        !           168:
        !           169:        uid = proc_get_peer_uid(c->peer);
        !           170:        if (uid == (uid_t)-1)
        !           171:                return (0);
        !           172:
        !           173:        user = server_acl_user_find(uid);
        !           174:        if (user == NULL)
        !           175:                return (0);
        !           176:        if (user->flags & SERVER_ACL_READONLY)
        !           177:                c->flags |= CLIENT_READONLY;
        !           178:        return (1);
        !           179: }
        !           180:
        !           181: /* Get UID for user entry. */
        !           182: uid_t
        !           183: server_acl_get_uid(struct server_acl_user *user)
        !           184: {
        !           185:        return (user->uid);
        !           186: }