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