1c501d73cSMariusz Zaborski /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 328b6f7c8SMariusz Zaborski * 4c501d73cSMariusz Zaborski * Copyright (c) 2013 The FreeBSD Foundation 5c501d73cSMariusz Zaborski * 6c501d73cSMariusz Zaborski * This software was developed by Pawel Jakub Dawidek under sponsorship from 7c501d73cSMariusz Zaborski * the FreeBSD Foundation. 8c501d73cSMariusz Zaborski * 9c501d73cSMariusz Zaborski * Redistribution and use in source and binary forms, with or without 10c501d73cSMariusz Zaborski * modification, are permitted provided that the following conditions 11c501d73cSMariusz Zaborski * are met: 12c501d73cSMariusz Zaborski * 1. Redistributions of source code must retain the above copyright 13c501d73cSMariusz Zaborski * notice, this list of conditions and the following disclaimer. 14c501d73cSMariusz Zaborski * 2. Redistributions in binary form must reproduce the above copyright 15c501d73cSMariusz Zaborski * notice, this list of conditions and the following disclaimer in the 16c501d73cSMariusz Zaborski * documentation and/or other materials provided with the distribution. 17c501d73cSMariusz Zaborski * 18c501d73cSMariusz Zaborski * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19c501d73cSMariusz Zaborski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20c501d73cSMariusz Zaborski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21c501d73cSMariusz Zaborski * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22c501d73cSMariusz Zaborski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23c501d73cSMariusz Zaborski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24c501d73cSMariusz Zaborski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25c501d73cSMariusz Zaborski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26c501d73cSMariusz Zaborski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27c501d73cSMariusz Zaborski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28c501d73cSMariusz Zaborski * SUCH DAMAGE. 29c501d73cSMariusz Zaborski */ 30c501d73cSMariusz Zaborski 31c501d73cSMariusz Zaborski #include <sys/cdefs.h> 32c501d73cSMariusz Zaborski #include <sys/dnv.h> 33c501d73cSMariusz Zaborski #include <sys/nv.h> 34c501d73cSMariusz Zaborski #include <sys/param.h> 35c501d73cSMariusz Zaborski 36c501d73cSMariusz Zaborski #include <assert.h> 37c501d73cSMariusz Zaborski #include <errno.h> 38c501d73cSMariusz Zaborski #include <grp.h> 39c501d73cSMariusz Zaborski #include <stdlib.h> 40c501d73cSMariusz Zaborski #include <string.h> 41c501d73cSMariusz Zaborski 42c501d73cSMariusz Zaborski #include <libcasper.h> 43c501d73cSMariusz Zaborski #include <libcasper_service.h> 44c501d73cSMariusz Zaborski 45c501d73cSMariusz Zaborski #include "cap_grp.h" 46c501d73cSMariusz Zaborski 47c501d73cSMariusz Zaborski static struct group ggrp; 48c501d73cSMariusz Zaborski static char *gbuffer; 49c501d73cSMariusz Zaborski static size_t gbufsize; 50c501d73cSMariusz Zaborski 51c501d73cSMariusz Zaborski static int 52c501d73cSMariusz Zaborski group_resize(void) 53c501d73cSMariusz Zaborski { 54c501d73cSMariusz Zaborski char *buf; 55c501d73cSMariusz Zaborski 56c501d73cSMariusz Zaborski if (gbufsize == 0) 57c501d73cSMariusz Zaborski gbufsize = 1024; 58c501d73cSMariusz Zaborski else 59c501d73cSMariusz Zaborski gbufsize *= 2; 60c501d73cSMariusz Zaborski 61c501d73cSMariusz Zaborski buf = gbuffer; 62c501d73cSMariusz Zaborski gbuffer = realloc(buf, gbufsize); 63c501d73cSMariusz Zaborski if (gbuffer == NULL) { 64c501d73cSMariusz Zaborski free(buf); 65c501d73cSMariusz Zaborski gbufsize = 0; 66c501d73cSMariusz Zaborski return (ENOMEM); 67c501d73cSMariusz Zaborski } 68c501d73cSMariusz Zaborski memset(gbuffer, 0, gbufsize); 69c501d73cSMariusz Zaborski 70c501d73cSMariusz Zaborski return (0); 71c501d73cSMariusz Zaborski } 72c501d73cSMariusz Zaborski 73c501d73cSMariusz Zaborski static int 74c501d73cSMariusz Zaborski group_unpack_string(const nvlist_t *nvl, const char *fieldname, char **fieldp, 75c501d73cSMariusz Zaborski char **bufferp, size_t *bufsizep) 76c501d73cSMariusz Zaborski { 77c501d73cSMariusz Zaborski const char *str; 78c501d73cSMariusz Zaborski size_t len; 79c501d73cSMariusz Zaborski 80c501d73cSMariusz Zaborski str = nvlist_get_string(nvl, fieldname); 81c501d73cSMariusz Zaborski len = strlcpy(*bufferp, str, *bufsizep); 82c501d73cSMariusz Zaborski if (len >= *bufsizep) 83c501d73cSMariusz Zaborski return (ERANGE); 84c501d73cSMariusz Zaborski *fieldp = *bufferp; 85c501d73cSMariusz Zaborski *bufferp += len + 1; 86c501d73cSMariusz Zaborski *bufsizep -= len + 1; 87c501d73cSMariusz Zaborski 88c501d73cSMariusz Zaborski return (0); 89c501d73cSMariusz Zaborski } 90c501d73cSMariusz Zaborski 91c501d73cSMariusz Zaborski static int 92c501d73cSMariusz Zaborski group_unpack_members(const nvlist_t *nvl, char ***fieldp, char **bufferp, 93c501d73cSMariusz Zaborski size_t *bufsizep) 94c501d73cSMariusz Zaborski { 95c501d73cSMariusz Zaborski const char *mem; 96c501d73cSMariusz Zaborski char **outstrs, *str, nvlname[64]; 97c501d73cSMariusz Zaborski size_t nmem, datasize, strsize; 98c501d73cSMariusz Zaborski unsigned int ii; 99c501d73cSMariusz Zaborski int n; 100c501d73cSMariusz Zaborski 101c501d73cSMariusz Zaborski if (!nvlist_exists_number(nvl, "gr_nmem")) { 102c501d73cSMariusz Zaborski datasize = _ALIGNBYTES + sizeof(char *); 103c501d73cSMariusz Zaborski if (datasize >= *bufsizep) 104c501d73cSMariusz Zaborski return (ERANGE); 105c501d73cSMariusz Zaborski outstrs = (char **)_ALIGN(*bufferp); 106c501d73cSMariusz Zaborski outstrs[0] = NULL; 107c501d73cSMariusz Zaborski *fieldp = outstrs; 108c501d73cSMariusz Zaborski *bufferp += datasize; 109c501d73cSMariusz Zaborski *bufsizep -= datasize; 110c501d73cSMariusz Zaborski return (0); 111c501d73cSMariusz Zaborski } 112c501d73cSMariusz Zaborski 113c501d73cSMariusz Zaborski nmem = (size_t)nvlist_get_number(nvl, "gr_nmem"); 114c501d73cSMariusz Zaborski datasize = _ALIGNBYTES + sizeof(char *) * (nmem + 1); 115c501d73cSMariusz Zaborski for (ii = 0; ii < nmem; ii++) { 116c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "gr_mem[%u]", ii); 117c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 118c501d73cSMariusz Zaborski mem = dnvlist_get_string(nvl, nvlname, NULL); 119c501d73cSMariusz Zaborski if (mem == NULL) 120c501d73cSMariusz Zaborski return (EINVAL); 121c501d73cSMariusz Zaborski datasize += strlen(mem) + 1; 122c501d73cSMariusz Zaborski } 123c501d73cSMariusz Zaborski 124c501d73cSMariusz Zaborski if (datasize >= *bufsizep) 125c501d73cSMariusz Zaborski return (ERANGE); 126c501d73cSMariusz Zaborski 127c501d73cSMariusz Zaborski outstrs = (char **)_ALIGN(*bufferp); 128c501d73cSMariusz Zaborski str = (char *)outstrs + sizeof(char *) * (nmem + 1); 129c501d73cSMariusz Zaborski for (ii = 0; ii < nmem; ii++) { 130c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "gr_mem[%u]", ii); 131c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 132c501d73cSMariusz Zaborski mem = nvlist_get_string(nvl, nvlname); 133c501d73cSMariusz Zaborski strsize = strlen(mem) + 1; 134c501d73cSMariusz Zaborski memcpy(str, mem, strsize); 135c501d73cSMariusz Zaborski outstrs[ii] = str; 136c501d73cSMariusz Zaborski str += strsize; 137c501d73cSMariusz Zaborski } 138c501d73cSMariusz Zaborski assert(ii == nmem); 139c501d73cSMariusz Zaborski outstrs[ii] = NULL; 140c501d73cSMariusz Zaborski 141c501d73cSMariusz Zaborski *fieldp = outstrs; 142c501d73cSMariusz Zaborski *bufferp += datasize; 143c501d73cSMariusz Zaborski *bufsizep -= datasize; 144c501d73cSMariusz Zaborski 145c501d73cSMariusz Zaborski return (0); 146c501d73cSMariusz Zaborski } 147c501d73cSMariusz Zaborski 148c501d73cSMariusz Zaborski static int 149c501d73cSMariusz Zaborski group_unpack(const nvlist_t *nvl, struct group *grp, char *buffer, 150c501d73cSMariusz Zaborski size_t bufsize) 151c501d73cSMariusz Zaborski { 152c501d73cSMariusz Zaborski int error; 153c501d73cSMariusz Zaborski 154c501d73cSMariusz Zaborski if (!nvlist_exists_string(nvl, "gr_name")) 155c501d73cSMariusz Zaborski return (EINVAL); 156c501d73cSMariusz Zaborski 157d9c2248dSMariusz Zaborski explicit_bzero(grp, sizeof(*grp)); 158c501d73cSMariusz Zaborski 159c501d73cSMariusz Zaborski error = group_unpack_string(nvl, "gr_name", &grp->gr_name, &buffer, 160c501d73cSMariusz Zaborski &bufsize); 161c501d73cSMariusz Zaborski if (error != 0) 162c501d73cSMariusz Zaborski return (error); 163c501d73cSMariusz Zaborski error = group_unpack_string(nvl, "gr_passwd", &grp->gr_passwd, &buffer, 164c501d73cSMariusz Zaborski &bufsize); 165c501d73cSMariusz Zaborski if (error != 0) 166c501d73cSMariusz Zaborski return (error); 167c501d73cSMariusz Zaborski grp->gr_gid = (gid_t)nvlist_get_number(nvl, "gr_gid"); 168c501d73cSMariusz Zaborski error = group_unpack_members(nvl, &grp->gr_mem, &buffer, &bufsize); 169c501d73cSMariusz Zaborski if (error != 0) 170c501d73cSMariusz Zaborski return (error); 171c501d73cSMariusz Zaborski 172c501d73cSMariusz Zaborski return (0); 173c501d73cSMariusz Zaborski } 174c501d73cSMariusz Zaborski 175c501d73cSMariusz Zaborski static int 176c501d73cSMariusz Zaborski cap_getgrcommon_r(cap_channel_t *chan, const char *cmd, const char *name, 177c501d73cSMariusz Zaborski gid_t gid, struct group *grp, char *buffer, size_t bufsize, 178c501d73cSMariusz Zaborski struct group **result) 179c501d73cSMariusz Zaborski { 180c501d73cSMariusz Zaborski nvlist_t *nvl; 181c501d73cSMariusz Zaborski bool getgr_r; 182c501d73cSMariusz Zaborski int error; 183c501d73cSMariusz Zaborski 184c501d73cSMariusz Zaborski nvl = nvlist_create(0); 185c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", cmd); 186c501d73cSMariusz Zaborski if (strcmp(cmd, "getgrent") == 0 || strcmp(cmd, "getgrent_r") == 0) { 187c501d73cSMariusz Zaborski /* Add nothing. */ 188c501d73cSMariusz Zaborski } else if (strcmp(cmd, "getgrnam") == 0 || 189c501d73cSMariusz Zaborski strcmp(cmd, "getgrnam_r") == 0) { 190c501d73cSMariusz Zaborski nvlist_add_string(nvl, "name", name); 191c501d73cSMariusz Zaborski } else if (strcmp(cmd, "getgrgid") == 0 || 192c501d73cSMariusz Zaborski strcmp(cmd, "getgrgid_r") == 0) { 193c501d73cSMariusz Zaborski nvlist_add_number(nvl, "gid", (uint64_t)gid); 194c501d73cSMariusz Zaborski } else { 195c501d73cSMariusz Zaborski abort(); 196c501d73cSMariusz Zaborski } 1974fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 198c501d73cSMariusz Zaborski if (nvl == NULL) { 199c501d73cSMariusz Zaborski assert(errno != 0); 200c501d73cSMariusz Zaborski *result = NULL; 201c501d73cSMariusz Zaborski return (errno); 202c501d73cSMariusz Zaborski } 203c501d73cSMariusz Zaborski error = (int)nvlist_get_number(nvl, "error"); 204c501d73cSMariusz Zaborski if (error != 0) { 205c501d73cSMariusz Zaborski nvlist_destroy(nvl); 206c501d73cSMariusz Zaborski *result = NULL; 207c501d73cSMariusz Zaborski return (error); 208c501d73cSMariusz Zaborski } 209c501d73cSMariusz Zaborski 210c501d73cSMariusz Zaborski if (!nvlist_exists_string(nvl, "gr_name")) { 211c501d73cSMariusz Zaborski /* Not found. */ 212c501d73cSMariusz Zaborski nvlist_destroy(nvl); 213c501d73cSMariusz Zaborski *result = NULL; 214c501d73cSMariusz Zaborski return (0); 215c501d73cSMariusz Zaborski } 216c501d73cSMariusz Zaborski 217c501d73cSMariusz Zaborski getgr_r = (strcmp(cmd, "getgrent_r") == 0 || 218c501d73cSMariusz Zaborski strcmp(cmd, "getgrnam_r") == 0 || strcmp(cmd, "getgrgid_r") == 0); 219c501d73cSMariusz Zaborski 220c501d73cSMariusz Zaborski for (;;) { 221c501d73cSMariusz Zaborski error = group_unpack(nvl, grp, buffer, bufsize); 222c501d73cSMariusz Zaborski if (getgr_r || error != ERANGE) 223c501d73cSMariusz Zaborski break; 224c501d73cSMariusz Zaborski assert(buffer == gbuffer); 225c501d73cSMariusz Zaborski assert(bufsize == gbufsize); 226c501d73cSMariusz Zaborski error = group_resize(); 227c501d73cSMariusz Zaborski if (error != 0) 228c501d73cSMariusz Zaborski break; 229c501d73cSMariusz Zaborski /* Update pointers after resize. */ 230c501d73cSMariusz Zaborski buffer = gbuffer; 231c501d73cSMariusz Zaborski bufsize = gbufsize; 232c501d73cSMariusz Zaborski } 233c501d73cSMariusz Zaborski 234c501d73cSMariusz Zaborski nvlist_destroy(nvl); 235c501d73cSMariusz Zaborski 236c501d73cSMariusz Zaborski if (error == 0) 237c501d73cSMariusz Zaborski *result = grp; 238c501d73cSMariusz Zaborski else 239c501d73cSMariusz Zaborski *result = NULL; 240c501d73cSMariusz Zaborski 241c501d73cSMariusz Zaborski return (error); 242c501d73cSMariusz Zaborski } 243c501d73cSMariusz Zaborski 244c501d73cSMariusz Zaborski static struct group * 245c501d73cSMariusz Zaborski cap_getgrcommon(cap_channel_t *chan, const char *cmd, const char *name, 246c501d73cSMariusz Zaborski gid_t gid) 247c501d73cSMariusz Zaborski { 248c501d73cSMariusz Zaborski struct group *result; 249c501d73cSMariusz Zaborski int error, serrno; 250c501d73cSMariusz Zaborski 251c501d73cSMariusz Zaborski serrno = errno; 252c501d73cSMariusz Zaborski 253c501d73cSMariusz Zaborski error = cap_getgrcommon_r(chan, cmd, name, gid, &ggrp, gbuffer, 254c501d73cSMariusz Zaborski gbufsize, &result); 255c501d73cSMariusz Zaborski if (error != 0) { 256c501d73cSMariusz Zaborski errno = error; 257c501d73cSMariusz Zaborski return (NULL); 258c501d73cSMariusz Zaborski } 259c501d73cSMariusz Zaborski 260c501d73cSMariusz Zaborski errno = serrno; 261c501d73cSMariusz Zaborski 262c501d73cSMariusz Zaborski return (result); 263c501d73cSMariusz Zaborski } 264c501d73cSMariusz Zaborski 265c501d73cSMariusz Zaborski struct group * 266c501d73cSMariusz Zaborski cap_getgrent(cap_channel_t *chan) 267c501d73cSMariusz Zaborski { 268c501d73cSMariusz Zaborski 269c501d73cSMariusz Zaborski return (cap_getgrcommon(chan, "getgrent", NULL, 0)); 270c501d73cSMariusz Zaborski } 271c501d73cSMariusz Zaborski 272c501d73cSMariusz Zaborski struct group * 273c501d73cSMariusz Zaborski cap_getgrnam(cap_channel_t *chan, const char *name) 274c501d73cSMariusz Zaborski { 275c501d73cSMariusz Zaborski 276c501d73cSMariusz Zaborski return (cap_getgrcommon(chan, "getgrnam", name, 0)); 277c501d73cSMariusz Zaborski } 278c501d73cSMariusz Zaborski 279c501d73cSMariusz Zaborski struct group * 280c501d73cSMariusz Zaborski cap_getgrgid(cap_channel_t *chan, gid_t gid) 281c501d73cSMariusz Zaborski { 282c501d73cSMariusz Zaborski 283c501d73cSMariusz Zaborski return (cap_getgrcommon(chan, "getgrgid", NULL, gid)); 284c501d73cSMariusz Zaborski } 285c501d73cSMariusz Zaborski 286c501d73cSMariusz Zaborski int 287c501d73cSMariusz Zaborski cap_getgrent_r(cap_channel_t *chan, struct group *grp, char *buffer, 288c501d73cSMariusz Zaborski size_t bufsize, struct group **result) 289c501d73cSMariusz Zaborski { 290c501d73cSMariusz Zaborski 291c501d73cSMariusz Zaborski return (cap_getgrcommon_r(chan, "getgrent_r", NULL, 0, grp, buffer, 292c501d73cSMariusz Zaborski bufsize, result)); 293c501d73cSMariusz Zaborski } 294c501d73cSMariusz Zaborski 295c501d73cSMariusz Zaborski int 296c501d73cSMariusz Zaborski cap_getgrnam_r(cap_channel_t *chan, const char *name, struct group *grp, 297c501d73cSMariusz Zaborski char *buffer, size_t bufsize, struct group **result) 298c501d73cSMariusz Zaborski { 299c501d73cSMariusz Zaborski 300c501d73cSMariusz Zaborski return (cap_getgrcommon_r(chan, "getgrnam_r", name, 0, grp, buffer, 301c501d73cSMariusz Zaborski bufsize, result)); 302c501d73cSMariusz Zaborski } 303c501d73cSMariusz Zaborski 304c501d73cSMariusz Zaborski int 305c501d73cSMariusz Zaborski cap_getgrgid_r(cap_channel_t *chan, gid_t gid, struct group *grp, char *buffer, 306c501d73cSMariusz Zaborski size_t bufsize, struct group **result) 307c501d73cSMariusz Zaborski { 308c501d73cSMariusz Zaborski 309c501d73cSMariusz Zaborski return (cap_getgrcommon_r(chan, "getgrgid_r", NULL, gid, grp, buffer, 310c501d73cSMariusz Zaborski bufsize, result)); 311c501d73cSMariusz Zaborski } 312c501d73cSMariusz Zaborski 313c501d73cSMariusz Zaborski int 314c501d73cSMariusz Zaborski cap_setgroupent(cap_channel_t *chan, int stayopen) 315c501d73cSMariusz Zaborski { 316c501d73cSMariusz Zaborski nvlist_t *nvl; 317c501d73cSMariusz Zaborski 318c501d73cSMariusz Zaborski nvl = nvlist_create(0); 319c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", "setgroupent"); 320c501d73cSMariusz Zaborski nvlist_add_bool(nvl, "stayopen", stayopen != 0); 3214fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 322c501d73cSMariusz Zaborski if (nvl == NULL) 323c501d73cSMariusz Zaborski return (0); 324c501d73cSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 325c501d73cSMariusz Zaborski errno = nvlist_get_number(nvl, "error"); 326c501d73cSMariusz Zaborski nvlist_destroy(nvl); 327c501d73cSMariusz Zaborski return (0); 328c501d73cSMariusz Zaborski } 329c501d73cSMariusz Zaborski nvlist_destroy(nvl); 330c501d73cSMariusz Zaborski 331c501d73cSMariusz Zaborski return (1); 332c501d73cSMariusz Zaborski } 333c501d73cSMariusz Zaborski 334c501d73cSMariusz Zaborski int 335c501d73cSMariusz Zaborski cap_setgrent(cap_channel_t *chan) 336c501d73cSMariusz Zaborski { 337c501d73cSMariusz Zaborski nvlist_t *nvl; 338c501d73cSMariusz Zaborski 339c501d73cSMariusz Zaborski nvl = nvlist_create(0); 340c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", "setgrent"); 3414fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 342c501d73cSMariusz Zaborski if (nvl == NULL) 343c501d73cSMariusz Zaborski return (0); 344c501d73cSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 345c501d73cSMariusz Zaborski errno = nvlist_get_number(nvl, "error"); 346c501d73cSMariusz Zaborski nvlist_destroy(nvl); 347c501d73cSMariusz Zaborski return (0); 348c501d73cSMariusz Zaborski } 349c501d73cSMariusz Zaborski nvlist_destroy(nvl); 350c501d73cSMariusz Zaborski 351c501d73cSMariusz Zaborski return (1); 352c501d73cSMariusz Zaborski } 353c501d73cSMariusz Zaborski 354c501d73cSMariusz Zaborski void 355c501d73cSMariusz Zaborski cap_endgrent(cap_channel_t *chan) 356c501d73cSMariusz Zaborski { 357c501d73cSMariusz Zaborski nvlist_t *nvl; 358c501d73cSMariusz Zaborski 359c501d73cSMariusz Zaborski nvl = nvlist_create(0); 360c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", "endgrent"); 361c501d73cSMariusz Zaborski /* Ignore any errors, we have no way to report them. */ 3624fc0a279SMariusz Zaborski nvlist_destroy(cap_xfer_nvlist(chan, nvl)); 363c501d73cSMariusz Zaborski } 364c501d73cSMariusz Zaborski 365c501d73cSMariusz Zaborski int 366c501d73cSMariusz Zaborski cap_grp_limit_cmds(cap_channel_t *chan, const char * const *cmds, size_t ncmds) 367c501d73cSMariusz Zaborski { 368c501d73cSMariusz Zaborski nvlist_t *limits, *nvl; 369c501d73cSMariusz Zaborski unsigned int i; 370c501d73cSMariusz Zaborski 371c501d73cSMariusz Zaborski if (cap_limit_get(chan, &limits) < 0) 372c501d73cSMariusz Zaborski return (-1); 373c501d73cSMariusz Zaborski if (limits == NULL) { 374c501d73cSMariusz Zaborski limits = nvlist_create(0); 375c501d73cSMariusz Zaborski } else { 376c501d73cSMariusz Zaborski if (nvlist_exists_nvlist(limits, "cmds")) 377c501d73cSMariusz Zaborski nvlist_free_nvlist(limits, "cmds"); 378c501d73cSMariusz Zaborski } 379c501d73cSMariusz Zaborski nvl = nvlist_create(0); 380c501d73cSMariusz Zaborski for (i = 0; i < ncmds; i++) 381c501d73cSMariusz Zaborski nvlist_add_null(nvl, cmds[i]); 382c501d73cSMariusz Zaborski nvlist_move_nvlist(limits, "cmds", nvl); 383c501d73cSMariusz Zaborski return (cap_limit_set(chan, limits)); 384c501d73cSMariusz Zaborski } 385c501d73cSMariusz Zaborski 386c501d73cSMariusz Zaborski int 387c501d73cSMariusz Zaborski cap_grp_limit_fields(cap_channel_t *chan, const char * const *fields, 388c501d73cSMariusz Zaborski size_t nfields) 389c501d73cSMariusz Zaborski { 390c501d73cSMariusz Zaborski nvlist_t *limits, *nvl; 391c501d73cSMariusz Zaborski unsigned int i; 392c501d73cSMariusz Zaborski 393c501d73cSMariusz Zaborski if (cap_limit_get(chan, &limits) < 0) 394c501d73cSMariusz Zaborski return (-1); 395c501d73cSMariusz Zaborski if (limits == NULL) { 396c501d73cSMariusz Zaborski limits = nvlist_create(0); 397c501d73cSMariusz Zaborski } else { 398c501d73cSMariusz Zaborski if (nvlist_exists_nvlist(limits, "fields")) 399c501d73cSMariusz Zaborski nvlist_free_nvlist(limits, "fields"); 400c501d73cSMariusz Zaborski } 401c501d73cSMariusz Zaborski nvl = nvlist_create(0); 402c501d73cSMariusz Zaborski for (i = 0; i < nfields; i++) 403c501d73cSMariusz Zaborski nvlist_add_null(nvl, fields[i]); 404c501d73cSMariusz Zaborski nvlist_move_nvlist(limits, "fields", nvl); 405c501d73cSMariusz Zaborski return (cap_limit_set(chan, limits)); 406c501d73cSMariusz Zaborski } 407c501d73cSMariusz Zaborski 408c501d73cSMariusz Zaborski int 409c501d73cSMariusz Zaborski cap_grp_limit_groups(cap_channel_t *chan, const char * const *names, 4104468cd1aSMariusz Zaborski size_t nnames, const gid_t *gids, size_t ngids) 411c501d73cSMariusz Zaborski { 412c501d73cSMariusz Zaborski nvlist_t *limits, *groups; 413c501d73cSMariusz Zaborski unsigned int i; 414c501d73cSMariusz Zaborski char nvlname[64]; 415c501d73cSMariusz Zaborski int n; 416c501d73cSMariusz Zaborski 417c501d73cSMariusz Zaborski if (cap_limit_get(chan, &limits) < 0) 418c501d73cSMariusz Zaborski return (-1); 419c501d73cSMariusz Zaborski if (limits == NULL) { 420c501d73cSMariusz Zaborski limits = nvlist_create(0); 421c501d73cSMariusz Zaborski } else { 422c501d73cSMariusz Zaborski if (nvlist_exists_nvlist(limits, "groups")) 423c501d73cSMariusz Zaborski nvlist_free_nvlist(limits, "groups"); 424c501d73cSMariusz Zaborski } 425c501d73cSMariusz Zaborski groups = nvlist_create(0); 426c501d73cSMariusz Zaborski for (i = 0; i < ngids; i++) { 427c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "gid%u", i); 428c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 429c501d73cSMariusz Zaborski nvlist_add_number(groups, nvlname, (uint64_t)gids[i]); 430c501d73cSMariusz Zaborski } 431c501d73cSMariusz Zaborski for (i = 0; i < nnames; i++) { 432c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "gid%u", i); 433c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 434c501d73cSMariusz Zaborski nvlist_add_string(groups, nvlname, names[i]); 435c501d73cSMariusz Zaborski } 436c501d73cSMariusz Zaborski nvlist_move_nvlist(limits, "groups", groups); 437c501d73cSMariusz Zaborski return (cap_limit_set(chan, limits)); 438c501d73cSMariusz Zaborski } 439c501d73cSMariusz Zaborski 440c501d73cSMariusz Zaborski /* 441c501d73cSMariusz Zaborski * Service functions. 442c501d73cSMariusz Zaborski */ 443c501d73cSMariusz Zaborski static bool 444c501d73cSMariusz Zaborski grp_allowed_cmd(const nvlist_t *limits, const char *cmd) 445c501d73cSMariusz Zaborski { 446c501d73cSMariusz Zaborski 447c501d73cSMariusz Zaborski if (limits == NULL) 448c501d73cSMariusz Zaborski return (true); 449c501d73cSMariusz Zaborski 450c501d73cSMariusz Zaborski /* 451c501d73cSMariusz Zaborski * If no limit was set on allowed commands, then all commands 452c501d73cSMariusz Zaborski * are allowed. 453c501d73cSMariusz Zaborski */ 454c501d73cSMariusz Zaborski if (!nvlist_exists_nvlist(limits, "cmds")) 455c501d73cSMariusz Zaborski return (true); 456c501d73cSMariusz Zaborski 457c501d73cSMariusz Zaborski limits = nvlist_get_nvlist(limits, "cmds"); 458c501d73cSMariusz Zaborski return (nvlist_exists_null(limits, cmd)); 459c501d73cSMariusz Zaborski } 460c501d73cSMariusz Zaborski 461c501d73cSMariusz Zaborski static int 462c501d73cSMariusz Zaborski grp_allowed_cmds(const nvlist_t *oldlimits, const nvlist_t *newlimits) 463c501d73cSMariusz Zaborski { 464c501d73cSMariusz Zaborski const char *name; 465c501d73cSMariusz Zaborski void *cookie; 466c501d73cSMariusz Zaborski int type; 467c501d73cSMariusz Zaborski 468c501d73cSMariusz Zaborski cookie = NULL; 469c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { 470c501d73cSMariusz Zaborski if (type != NV_TYPE_NULL) 471c501d73cSMariusz Zaborski return (EINVAL); 472c501d73cSMariusz Zaborski if (!grp_allowed_cmd(oldlimits, name)) 473c501d73cSMariusz Zaborski return (ENOTCAPABLE); 474c501d73cSMariusz Zaborski } 475c501d73cSMariusz Zaborski 476c501d73cSMariusz Zaborski return (0); 477c501d73cSMariusz Zaborski } 478c501d73cSMariusz Zaborski 479c501d73cSMariusz Zaborski static bool 480c501d73cSMariusz Zaborski grp_allowed_group(const nvlist_t *limits, const char *gname, gid_t gid) 481c501d73cSMariusz Zaborski { 482c501d73cSMariusz Zaborski const char *name; 483c501d73cSMariusz Zaborski void *cookie; 484c501d73cSMariusz Zaborski int type; 485c501d73cSMariusz Zaborski 486c501d73cSMariusz Zaborski if (limits == NULL) 487c501d73cSMariusz Zaborski return (true); 488c501d73cSMariusz Zaborski 489c501d73cSMariusz Zaborski /* 490c501d73cSMariusz Zaborski * If no limit was set on allowed groups, then all groups are allowed. 491c501d73cSMariusz Zaborski */ 492c501d73cSMariusz Zaborski if (!nvlist_exists_nvlist(limits, "groups")) 493c501d73cSMariusz Zaborski return (true); 494c501d73cSMariusz Zaborski 495c501d73cSMariusz Zaborski limits = nvlist_get_nvlist(limits, "groups"); 496c501d73cSMariusz Zaborski cookie = NULL; 497c501d73cSMariusz Zaborski while ((name = nvlist_next(limits, &type, &cookie)) != NULL) { 498c501d73cSMariusz Zaborski switch (type) { 499c501d73cSMariusz Zaborski case NV_TYPE_NUMBER: 500c501d73cSMariusz Zaborski if (gid != (gid_t)-1 && 501c501d73cSMariusz Zaborski nvlist_get_number(limits, name) == (uint64_t)gid) { 502c501d73cSMariusz Zaborski return (true); 503c501d73cSMariusz Zaborski } 504c501d73cSMariusz Zaborski break; 505c501d73cSMariusz Zaborski case NV_TYPE_STRING: 506c501d73cSMariusz Zaborski if (gname != NULL && 507c501d73cSMariusz Zaborski strcmp(nvlist_get_string(limits, name), 508c501d73cSMariusz Zaborski gname) == 0) { 509c501d73cSMariusz Zaborski return (true); 510c501d73cSMariusz Zaborski } 511c501d73cSMariusz Zaborski break; 512c501d73cSMariusz Zaborski default: 513c501d73cSMariusz Zaborski abort(); 514c501d73cSMariusz Zaborski } 515c501d73cSMariusz Zaborski } 516c501d73cSMariusz Zaborski 517c501d73cSMariusz Zaborski return (false); 518c501d73cSMariusz Zaborski } 519c501d73cSMariusz Zaborski 520c501d73cSMariusz Zaborski static int 521c501d73cSMariusz Zaborski grp_allowed_groups(const nvlist_t *oldlimits, const nvlist_t *newlimits) 522c501d73cSMariusz Zaborski { 523c501d73cSMariusz Zaborski const char *name, *gname; 524c501d73cSMariusz Zaborski void *cookie; 525c501d73cSMariusz Zaborski gid_t gid; 526c501d73cSMariusz Zaborski int type; 527c501d73cSMariusz Zaborski 528c501d73cSMariusz Zaborski cookie = NULL; 529c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { 530c501d73cSMariusz Zaborski switch (type) { 531c501d73cSMariusz Zaborski case NV_TYPE_NUMBER: 532c501d73cSMariusz Zaborski gid = (gid_t)nvlist_get_number(newlimits, name); 533c501d73cSMariusz Zaborski gname = NULL; 534c501d73cSMariusz Zaborski break; 535c501d73cSMariusz Zaborski case NV_TYPE_STRING: 536c501d73cSMariusz Zaborski gid = (gid_t)-1; 537c501d73cSMariusz Zaborski gname = nvlist_get_string(newlimits, name); 538c501d73cSMariusz Zaborski break; 539c501d73cSMariusz Zaborski default: 540c501d73cSMariusz Zaborski return (EINVAL); 541c501d73cSMariusz Zaborski } 542c501d73cSMariusz Zaborski if (!grp_allowed_group(oldlimits, gname, gid)) 543c501d73cSMariusz Zaborski return (ENOTCAPABLE); 544c501d73cSMariusz Zaborski } 545c501d73cSMariusz Zaborski 546c501d73cSMariusz Zaborski return (0); 547c501d73cSMariusz Zaborski } 548c501d73cSMariusz Zaborski 549c501d73cSMariusz Zaborski static bool 550c501d73cSMariusz Zaborski grp_allowed_field(const nvlist_t *limits, const char *field) 551c501d73cSMariusz Zaborski { 552c501d73cSMariusz Zaborski 553c501d73cSMariusz Zaborski if (limits == NULL) 554c501d73cSMariusz Zaborski return (true); 555c501d73cSMariusz Zaborski 556c501d73cSMariusz Zaborski /* 557c501d73cSMariusz Zaborski * If no limit was set on allowed fields, then all fields are allowed. 558c501d73cSMariusz Zaborski */ 559c501d73cSMariusz Zaborski if (!nvlist_exists_nvlist(limits, "fields")) 560c501d73cSMariusz Zaborski return (true); 561c501d73cSMariusz Zaborski 562c501d73cSMariusz Zaborski limits = nvlist_get_nvlist(limits, "fields"); 563c501d73cSMariusz Zaborski return (nvlist_exists_null(limits, field)); 564c501d73cSMariusz Zaborski } 565c501d73cSMariusz Zaborski 566c501d73cSMariusz Zaborski static int 567c501d73cSMariusz Zaborski grp_allowed_fields(const nvlist_t *oldlimits, const nvlist_t *newlimits) 568c501d73cSMariusz Zaborski { 569c501d73cSMariusz Zaborski const char *name; 570c501d73cSMariusz Zaborski void *cookie; 571c501d73cSMariusz Zaborski int type; 572c501d73cSMariusz Zaborski 573c501d73cSMariusz Zaborski cookie = NULL; 574c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { 575c501d73cSMariusz Zaborski if (type != NV_TYPE_NULL) 576c501d73cSMariusz Zaborski return (EINVAL); 577c501d73cSMariusz Zaborski if (!grp_allowed_field(oldlimits, name)) 578c501d73cSMariusz Zaborski return (ENOTCAPABLE); 579c501d73cSMariusz Zaborski } 580c501d73cSMariusz Zaborski 581c501d73cSMariusz Zaborski return (0); 582c501d73cSMariusz Zaborski } 583c501d73cSMariusz Zaborski 584c501d73cSMariusz Zaborski static bool 585c501d73cSMariusz Zaborski grp_pack(const nvlist_t *limits, const struct group *grp, nvlist_t *nvl) 586c501d73cSMariusz Zaborski { 587c501d73cSMariusz Zaborski char nvlname[64]; 588c501d73cSMariusz Zaborski int n; 589c501d73cSMariusz Zaborski 590c501d73cSMariusz Zaborski if (grp == NULL) 591c501d73cSMariusz Zaborski return (true); 592c501d73cSMariusz Zaborski 593c501d73cSMariusz Zaborski /* 594c501d73cSMariusz Zaborski * If either name or GID is allowed, we allow it. 595c501d73cSMariusz Zaborski */ 596c501d73cSMariusz Zaborski if (!grp_allowed_group(limits, grp->gr_name, grp->gr_gid)) 597c501d73cSMariusz Zaborski return (false); 598c501d73cSMariusz Zaborski 599c501d73cSMariusz Zaborski if (grp_allowed_field(limits, "gr_name")) 600c501d73cSMariusz Zaborski nvlist_add_string(nvl, "gr_name", grp->gr_name); 601c501d73cSMariusz Zaborski else 602c501d73cSMariusz Zaborski nvlist_add_string(nvl, "gr_name", ""); 603c501d73cSMariusz Zaborski if (grp_allowed_field(limits, "gr_passwd")) 604c501d73cSMariusz Zaborski nvlist_add_string(nvl, "gr_passwd", grp->gr_passwd); 605c501d73cSMariusz Zaborski else 606c501d73cSMariusz Zaborski nvlist_add_string(nvl, "gr_passwd", ""); 607c501d73cSMariusz Zaborski if (grp_allowed_field(limits, "gr_gid")) 608c501d73cSMariusz Zaborski nvlist_add_number(nvl, "gr_gid", (uint64_t)grp->gr_gid); 609c501d73cSMariusz Zaborski else 610c501d73cSMariusz Zaborski nvlist_add_number(nvl, "gr_gid", (uint64_t)-1); 611c501d73cSMariusz Zaborski if (grp_allowed_field(limits, "gr_mem") && grp->gr_mem[0] != NULL) { 612c501d73cSMariusz Zaborski unsigned int ngroups; 613c501d73cSMariusz Zaborski 614c501d73cSMariusz Zaborski for (ngroups = 0; grp->gr_mem[ngroups] != NULL; ngroups++) { 615c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "gr_mem[%u]", 616c501d73cSMariusz Zaborski ngroups); 617c501d73cSMariusz Zaborski assert(n > 0 && n < (ssize_t)sizeof(nvlname)); 618c501d73cSMariusz Zaborski nvlist_add_string(nvl, nvlname, grp->gr_mem[ngroups]); 619c501d73cSMariusz Zaborski } 620c501d73cSMariusz Zaborski nvlist_add_number(nvl, "gr_nmem", (uint64_t)ngroups); 621c501d73cSMariusz Zaborski } 622c501d73cSMariusz Zaborski 623c501d73cSMariusz Zaborski return (true); 624c501d73cSMariusz Zaborski } 625c501d73cSMariusz Zaborski 626c501d73cSMariusz Zaborski static int 627c501d73cSMariusz Zaborski grp_getgrent(const nvlist_t *limits, const nvlist_t *nvlin __unused, 628c501d73cSMariusz Zaborski nvlist_t *nvlout) 629c501d73cSMariusz Zaborski { 630c501d73cSMariusz Zaborski struct group *grp; 631c501d73cSMariusz Zaborski 632c501d73cSMariusz Zaborski for (;;) { 633c501d73cSMariusz Zaborski errno = 0; 634c501d73cSMariusz Zaborski grp = getgrent(); 635c501d73cSMariusz Zaborski if (errno != 0) 636c501d73cSMariusz Zaborski return (errno); 637c501d73cSMariusz Zaborski if (grp_pack(limits, grp, nvlout)) 638c501d73cSMariusz Zaborski return (0); 639c501d73cSMariusz Zaborski } 640c501d73cSMariusz Zaborski 641c501d73cSMariusz Zaborski /* NOTREACHED */ 642c501d73cSMariusz Zaborski } 643c501d73cSMariusz Zaborski 644c501d73cSMariusz Zaborski static int 645c501d73cSMariusz Zaborski grp_getgrnam(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) 646c501d73cSMariusz Zaborski { 647c501d73cSMariusz Zaborski struct group *grp; 648c501d73cSMariusz Zaborski const char *name; 649c501d73cSMariusz Zaborski 650c501d73cSMariusz Zaborski if (!nvlist_exists_string(nvlin, "name")) 651c501d73cSMariusz Zaborski return (EINVAL); 652c501d73cSMariusz Zaborski name = nvlist_get_string(nvlin, "name"); 653c501d73cSMariusz Zaborski assert(name != NULL); 654c501d73cSMariusz Zaborski 655c501d73cSMariusz Zaborski errno = 0; 656c501d73cSMariusz Zaborski grp = getgrnam(name); 657c501d73cSMariusz Zaborski if (errno != 0) 658c501d73cSMariusz Zaborski return (errno); 659c501d73cSMariusz Zaborski 660c501d73cSMariusz Zaborski (void)grp_pack(limits, grp, nvlout); 661c501d73cSMariusz Zaborski 662c501d73cSMariusz Zaborski return (0); 663c501d73cSMariusz Zaborski } 664c501d73cSMariusz Zaborski 665c501d73cSMariusz Zaborski static int 666c501d73cSMariusz Zaborski grp_getgrgid(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) 667c501d73cSMariusz Zaborski { 668c501d73cSMariusz Zaborski struct group *grp; 669c501d73cSMariusz Zaborski gid_t gid; 670c501d73cSMariusz Zaborski 671c501d73cSMariusz Zaborski if (!nvlist_exists_number(nvlin, "gid")) 672c501d73cSMariusz Zaborski return (EINVAL); 673c501d73cSMariusz Zaborski 674c501d73cSMariusz Zaborski gid = (gid_t)nvlist_get_number(nvlin, "gid"); 675c501d73cSMariusz Zaborski 676c501d73cSMariusz Zaborski errno = 0; 677c501d73cSMariusz Zaborski grp = getgrgid(gid); 678c501d73cSMariusz Zaborski if (errno != 0) 679c501d73cSMariusz Zaborski return (errno); 680c501d73cSMariusz Zaborski 681c501d73cSMariusz Zaborski (void)grp_pack(limits, grp, nvlout); 682c501d73cSMariusz Zaborski 683c501d73cSMariusz Zaborski return (0); 684c501d73cSMariusz Zaborski } 685c501d73cSMariusz Zaborski 686c501d73cSMariusz Zaborski static int 687c501d73cSMariusz Zaborski grp_setgroupent(const nvlist_t *limits __unused, const nvlist_t *nvlin, 688c501d73cSMariusz Zaborski nvlist_t *nvlout __unused) 689c501d73cSMariusz Zaborski { 690c501d73cSMariusz Zaborski int stayopen; 691c501d73cSMariusz Zaborski 692c501d73cSMariusz Zaborski if (!nvlist_exists_bool(nvlin, "stayopen")) 693c501d73cSMariusz Zaborski return (EINVAL); 694c501d73cSMariusz Zaborski 695c501d73cSMariusz Zaborski stayopen = nvlist_get_bool(nvlin, "stayopen") ? 1 : 0; 696c501d73cSMariusz Zaborski 697c501d73cSMariusz Zaborski return (setgroupent(stayopen) == 0 ? EFAULT : 0); 698c501d73cSMariusz Zaborski } 699c501d73cSMariusz Zaborski 700c501d73cSMariusz Zaborski static int 701c501d73cSMariusz Zaborski grp_setgrent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, 702c501d73cSMariusz Zaborski nvlist_t *nvlout __unused) 703c501d73cSMariusz Zaborski { 704c501d73cSMariusz Zaborski 7052ca9ffa9SEd Schouten setgrent(); 7062ca9ffa9SEd Schouten 7072ca9ffa9SEd Schouten return (0); 708c501d73cSMariusz Zaborski } 709c501d73cSMariusz Zaborski 710c501d73cSMariusz Zaborski static int 711c501d73cSMariusz Zaborski grp_endgrent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, 712c501d73cSMariusz Zaborski nvlist_t *nvlout __unused) 713c501d73cSMariusz Zaborski { 714c501d73cSMariusz Zaborski 715c501d73cSMariusz Zaborski endgrent(); 716c501d73cSMariusz Zaborski 717c501d73cSMariusz Zaborski return (0); 718c501d73cSMariusz Zaborski } 719c501d73cSMariusz Zaborski 720c501d73cSMariusz Zaborski static int 721c501d73cSMariusz Zaborski grp_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) 722c501d73cSMariusz Zaborski { 723c501d73cSMariusz Zaborski const nvlist_t *limits; 724c501d73cSMariusz Zaborski const char *name; 725c501d73cSMariusz Zaborski void *cookie; 726c501d73cSMariusz Zaborski int error, type; 727c501d73cSMariusz Zaborski 728c501d73cSMariusz Zaborski if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "cmds") && 729c501d73cSMariusz Zaborski !nvlist_exists_nvlist(newlimits, "cmds")) { 730c501d73cSMariusz Zaborski return (ENOTCAPABLE); 731c501d73cSMariusz Zaborski } 732c501d73cSMariusz Zaborski if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "fields") && 733c501d73cSMariusz Zaborski !nvlist_exists_nvlist(newlimits, "fields")) { 734c501d73cSMariusz Zaborski return (ENOTCAPABLE); 735c501d73cSMariusz Zaborski } 736c501d73cSMariusz Zaborski if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "groups") && 737c501d73cSMariusz Zaborski !nvlist_exists_nvlist(newlimits, "groups")) { 738c501d73cSMariusz Zaborski return (ENOTCAPABLE); 739c501d73cSMariusz Zaborski } 740c501d73cSMariusz Zaborski 741c501d73cSMariusz Zaborski cookie = NULL; 742c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { 743c501d73cSMariusz Zaborski if (type != NV_TYPE_NVLIST) 744c501d73cSMariusz Zaborski return (EINVAL); 745c501d73cSMariusz Zaborski limits = nvlist_get_nvlist(newlimits, name); 746c501d73cSMariusz Zaborski if (strcmp(name, "cmds") == 0) 747c501d73cSMariusz Zaborski error = grp_allowed_cmds(oldlimits, limits); 748c501d73cSMariusz Zaborski else if (strcmp(name, "fields") == 0) 749c501d73cSMariusz Zaborski error = grp_allowed_fields(oldlimits, limits); 750c501d73cSMariusz Zaborski else if (strcmp(name, "groups") == 0) 751c501d73cSMariusz Zaborski error = grp_allowed_groups(oldlimits, limits); 752c501d73cSMariusz Zaborski else 753c501d73cSMariusz Zaborski error = EINVAL; 754c501d73cSMariusz Zaborski if (error != 0) 755c501d73cSMariusz Zaborski return (error); 756c501d73cSMariusz Zaborski } 757c501d73cSMariusz Zaborski 758c501d73cSMariusz Zaborski return (0); 759c501d73cSMariusz Zaborski } 760c501d73cSMariusz Zaborski 761c501d73cSMariusz Zaborski static int 762c501d73cSMariusz Zaborski grp_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, 763c501d73cSMariusz Zaborski nvlist_t *nvlout) 764c501d73cSMariusz Zaborski { 765c501d73cSMariusz Zaborski int error; 766c501d73cSMariusz Zaborski 767c501d73cSMariusz Zaborski if (!grp_allowed_cmd(limits, cmd)) 768c501d73cSMariusz Zaborski return (ENOTCAPABLE); 769c501d73cSMariusz Zaborski 770c501d73cSMariusz Zaborski if (strcmp(cmd, "getgrent") == 0 || strcmp(cmd, "getgrent_r") == 0) 771c501d73cSMariusz Zaborski error = grp_getgrent(limits, nvlin, nvlout); 772c501d73cSMariusz Zaborski else if (strcmp(cmd, "getgrnam") == 0 || strcmp(cmd, "getgrnam_r") == 0) 773c501d73cSMariusz Zaborski error = grp_getgrnam(limits, nvlin, nvlout); 774c501d73cSMariusz Zaborski else if (strcmp(cmd, "getgrgid") == 0 || strcmp(cmd, "getgrgid_r") == 0) 775c501d73cSMariusz Zaborski error = grp_getgrgid(limits, nvlin, nvlout); 776c501d73cSMariusz Zaborski else if (strcmp(cmd, "setgroupent") == 0) 777c501d73cSMariusz Zaborski error = grp_setgroupent(limits, nvlin, nvlout); 778c501d73cSMariusz Zaborski else if (strcmp(cmd, "setgrent") == 0) 779c501d73cSMariusz Zaborski error = grp_setgrent(limits, nvlin, nvlout); 780c501d73cSMariusz Zaborski else if (strcmp(cmd, "endgrent") == 0) 781c501d73cSMariusz Zaborski error = grp_endgrent(limits, nvlin, nvlout); 782c501d73cSMariusz Zaborski else 783c501d73cSMariusz Zaborski error = EINVAL; 784c501d73cSMariusz Zaborski 785c501d73cSMariusz Zaborski return (error); 786c501d73cSMariusz Zaborski } 787c501d73cSMariusz Zaborski 788920be817SMariusz Zaborski CREATE_SERVICE("system.grp", grp_limit, grp_command, 0); 789