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/types.h> 32c501d73cSMariusz Zaborski #include <sys/nv.h> 33c501d73cSMariusz Zaborski 34c501d73cSMariusz Zaborski #include <assert.h> 35c501d73cSMariusz Zaborski #include <errno.h> 36c501d73cSMariusz Zaborski #include <pwd.h> 37c501d73cSMariusz Zaborski #include <stdlib.h> 38c501d73cSMariusz Zaborski #include <string.h> 39c501d73cSMariusz Zaborski #include <unistd.h> 40c501d73cSMariusz Zaborski 41c501d73cSMariusz Zaborski #include <libcasper.h> 42c501d73cSMariusz Zaborski #include <libcasper_service.h> 43c501d73cSMariusz Zaborski 44c501d73cSMariusz Zaborski #include "cap_pwd.h" 45c501d73cSMariusz Zaborski 46c501d73cSMariusz Zaborski static struct passwd gpwd; 47c501d73cSMariusz Zaborski static char *gbuffer; 48c501d73cSMariusz Zaborski static size_t gbufsize; 49c501d73cSMariusz Zaborski 50c501d73cSMariusz Zaborski static int 51c501d73cSMariusz Zaborski passwd_resize(void) 52c501d73cSMariusz Zaborski { 53c501d73cSMariusz Zaborski char *buf; 54c501d73cSMariusz Zaborski 55c501d73cSMariusz Zaborski if (gbufsize == 0) 56c501d73cSMariusz Zaborski gbufsize = 1024; 57c501d73cSMariusz Zaborski else 58c501d73cSMariusz Zaborski gbufsize *= 2; 59c501d73cSMariusz Zaborski 60c501d73cSMariusz Zaborski buf = gbuffer; 61c501d73cSMariusz Zaborski gbuffer = realloc(buf, gbufsize); 62c501d73cSMariusz Zaborski if (gbuffer == NULL) { 63c501d73cSMariusz Zaborski free(buf); 64c501d73cSMariusz Zaborski gbufsize = 0; 65c501d73cSMariusz Zaborski return (ENOMEM); 66c501d73cSMariusz Zaborski } 67c501d73cSMariusz Zaborski memset(gbuffer, 0, gbufsize); 68c501d73cSMariusz Zaborski 69c501d73cSMariusz Zaborski return (0); 70c501d73cSMariusz Zaborski } 71c501d73cSMariusz Zaborski 72c501d73cSMariusz Zaborski static int 73c501d73cSMariusz Zaborski passwd_unpack_string(const nvlist_t *nvl, const char *fieldname, char **fieldp, 74c501d73cSMariusz Zaborski char **bufferp, size_t *bufsizep) 75c501d73cSMariusz Zaborski { 76c501d73cSMariusz Zaborski const char *str; 77c501d73cSMariusz Zaborski size_t len; 78c501d73cSMariusz Zaborski 79c501d73cSMariusz Zaborski str = nvlist_get_string(nvl, fieldname); 80c501d73cSMariusz Zaborski len = strlcpy(*bufferp, str, *bufsizep); 81c501d73cSMariusz Zaborski if (len >= *bufsizep) 82c501d73cSMariusz Zaborski return (ERANGE); 83c501d73cSMariusz Zaborski *fieldp = *bufferp; 84c501d73cSMariusz Zaborski *bufferp += len + 1; 85c501d73cSMariusz Zaborski *bufsizep -= len + 1; 86c501d73cSMariusz Zaborski 87c501d73cSMariusz Zaborski return (0); 88c501d73cSMariusz Zaborski } 89c501d73cSMariusz Zaborski 90c501d73cSMariusz Zaborski static int 91c501d73cSMariusz Zaborski passwd_unpack(const nvlist_t *nvl, struct passwd *pwd, char *buffer, 92c501d73cSMariusz Zaborski size_t bufsize) 93c501d73cSMariusz Zaborski { 94c501d73cSMariusz Zaborski int error; 95c501d73cSMariusz Zaborski 96c501d73cSMariusz Zaborski if (!nvlist_exists_string(nvl, "pw_name")) 97c501d73cSMariusz Zaborski return (EINVAL); 98c501d73cSMariusz Zaborski 9900e94733SMariusz Zaborski explicit_bzero(pwd, sizeof(*pwd)); 100c501d73cSMariusz Zaborski 101c501d73cSMariusz Zaborski error = passwd_unpack_string(nvl, "pw_name", &pwd->pw_name, &buffer, 102c501d73cSMariusz Zaborski &bufsize); 103c501d73cSMariusz Zaborski if (error != 0) 104c501d73cSMariusz Zaborski return (error); 105c501d73cSMariusz Zaborski pwd->pw_uid = (uid_t)nvlist_get_number(nvl, "pw_uid"); 106c501d73cSMariusz Zaborski pwd->pw_gid = (gid_t)nvlist_get_number(nvl, "pw_gid"); 107c501d73cSMariusz Zaborski pwd->pw_change = (time_t)nvlist_get_number(nvl, "pw_change"); 108c501d73cSMariusz Zaborski error = passwd_unpack_string(nvl, "pw_passwd", &pwd->pw_passwd, &buffer, 109c501d73cSMariusz Zaborski &bufsize); 110c501d73cSMariusz Zaborski if (error != 0) 111c501d73cSMariusz Zaborski return (error); 112c501d73cSMariusz Zaborski error = passwd_unpack_string(nvl, "pw_class", &pwd->pw_class, &buffer, 113c501d73cSMariusz Zaborski &bufsize); 114c501d73cSMariusz Zaborski if (error != 0) 115c501d73cSMariusz Zaborski return (error); 116c501d73cSMariusz Zaborski error = passwd_unpack_string(nvl, "pw_gecos", &pwd->pw_gecos, &buffer, 117c501d73cSMariusz Zaborski &bufsize); 118c501d73cSMariusz Zaborski if (error != 0) 119c501d73cSMariusz Zaborski return (error); 120c501d73cSMariusz Zaborski error = passwd_unpack_string(nvl, "pw_dir", &pwd->pw_dir, &buffer, 121c501d73cSMariusz Zaborski &bufsize); 122c501d73cSMariusz Zaborski if (error != 0) 123c501d73cSMariusz Zaborski return (error); 124c501d73cSMariusz Zaborski error = passwd_unpack_string(nvl, "pw_shell", &pwd->pw_shell, &buffer, 125c501d73cSMariusz Zaborski &bufsize); 126c501d73cSMariusz Zaborski if (error != 0) 127c501d73cSMariusz Zaborski return (error); 128c501d73cSMariusz Zaborski pwd->pw_expire = (time_t)nvlist_get_number(nvl, "pw_expire"); 129c501d73cSMariusz Zaborski pwd->pw_fields = (int)nvlist_get_number(nvl, "pw_fields"); 130c501d73cSMariusz Zaborski 131c501d73cSMariusz Zaborski return (0); 132c501d73cSMariusz Zaborski } 133c501d73cSMariusz Zaborski 134c501d73cSMariusz Zaborski static int 135c501d73cSMariusz Zaborski cap_getpwcommon_r(cap_channel_t *chan, const char *cmd, const char *login, 136c501d73cSMariusz Zaborski uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, 137c501d73cSMariusz Zaborski struct passwd **result) 138c501d73cSMariusz Zaborski { 139c501d73cSMariusz Zaborski nvlist_t *nvl; 140c501d73cSMariusz Zaborski bool getpw_r; 141c501d73cSMariusz Zaborski int error; 142c501d73cSMariusz Zaborski 143c501d73cSMariusz Zaborski nvl = nvlist_create(0); 144c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", cmd); 145c501d73cSMariusz Zaborski if (strcmp(cmd, "getpwent") == 0 || strcmp(cmd, "getpwent_r") == 0) { 146c501d73cSMariusz Zaborski /* Add nothing. */ 147c501d73cSMariusz Zaborski } else if (strcmp(cmd, "getpwnam") == 0 || 148c501d73cSMariusz Zaborski strcmp(cmd, "getpwnam_r") == 0) { 149c501d73cSMariusz Zaborski nvlist_add_string(nvl, "name", login); 150c501d73cSMariusz Zaborski } else if (strcmp(cmd, "getpwuid") == 0 || 151c501d73cSMariusz Zaborski strcmp(cmd, "getpwuid_r") == 0) { 152c501d73cSMariusz Zaborski nvlist_add_number(nvl, "uid", (uint64_t)uid); 153c501d73cSMariusz Zaborski } else { 154c501d73cSMariusz Zaborski abort(); 155c501d73cSMariusz Zaborski } 1564fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 157c501d73cSMariusz Zaborski if (nvl == NULL) { 158c501d73cSMariusz Zaborski assert(errno != 0); 159c501d73cSMariusz Zaborski *result = NULL; 160c501d73cSMariusz Zaborski return (errno); 161c501d73cSMariusz Zaborski } 162c501d73cSMariusz Zaborski error = (int)nvlist_get_number(nvl, "error"); 163c501d73cSMariusz Zaborski if (error != 0) { 164c501d73cSMariusz Zaborski nvlist_destroy(nvl); 165c501d73cSMariusz Zaborski *result = NULL; 166c501d73cSMariusz Zaborski return (error); 167c501d73cSMariusz Zaborski } 168c501d73cSMariusz Zaborski 169c501d73cSMariusz Zaborski if (!nvlist_exists_string(nvl, "pw_name")) { 170c501d73cSMariusz Zaborski /* Not found. */ 171c501d73cSMariusz Zaborski nvlist_destroy(nvl); 172c501d73cSMariusz Zaborski *result = NULL; 173c501d73cSMariusz Zaborski return (0); 174c501d73cSMariusz Zaborski } 175c501d73cSMariusz Zaborski 176c501d73cSMariusz Zaborski getpw_r = (strcmp(cmd, "getpwent_r") == 0 || 177c501d73cSMariusz Zaborski strcmp(cmd, "getpwnam_r") == 0 || strcmp(cmd, "getpwuid_r") == 0); 178c501d73cSMariusz Zaborski 179c501d73cSMariusz Zaborski for (;;) { 180c501d73cSMariusz Zaborski error = passwd_unpack(nvl, pwd, buffer, bufsize); 181c501d73cSMariusz Zaborski if (getpw_r || error != ERANGE) 182c501d73cSMariusz Zaborski break; 183c501d73cSMariusz Zaborski assert(buffer == gbuffer); 184c501d73cSMariusz Zaborski assert(bufsize == gbufsize); 185c501d73cSMariusz Zaborski error = passwd_resize(); 186c501d73cSMariusz Zaborski if (error != 0) 187c501d73cSMariusz Zaborski break; 188c501d73cSMariusz Zaborski /* Update pointers after resize. */ 189c501d73cSMariusz Zaborski buffer = gbuffer; 190c501d73cSMariusz Zaborski bufsize = gbufsize; 191c501d73cSMariusz Zaborski } 192c501d73cSMariusz Zaborski 193c501d73cSMariusz Zaborski nvlist_destroy(nvl); 194c501d73cSMariusz Zaborski 195c501d73cSMariusz Zaborski if (error == 0) 196c501d73cSMariusz Zaborski *result = pwd; 197c501d73cSMariusz Zaborski else 198c501d73cSMariusz Zaborski *result = NULL; 199c501d73cSMariusz Zaborski 200c501d73cSMariusz Zaborski return (error); 201c501d73cSMariusz Zaborski } 202c501d73cSMariusz Zaborski 203c501d73cSMariusz Zaborski static struct passwd * 204c501d73cSMariusz Zaborski cap_getpwcommon(cap_channel_t *chan, const char *cmd, const char *login, 205c501d73cSMariusz Zaborski uid_t uid) 206c501d73cSMariusz Zaborski { 207c501d73cSMariusz Zaborski struct passwd *result; 208c501d73cSMariusz Zaborski int error, serrno; 209c501d73cSMariusz Zaborski 210c501d73cSMariusz Zaborski serrno = errno; 211c501d73cSMariusz Zaborski 212c501d73cSMariusz Zaborski error = cap_getpwcommon_r(chan, cmd, login, uid, &gpwd, gbuffer, 213c501d73cSMariusz Zaborski gbufsize, &result); 214c501d73cSMariusz Zaborski if (error != 0) { 215c501d73cSMariusz Zaborski errno = error; 216c501d73cSMariusz Zaborski return (NULL); 217c501d73cSMariusz Zaborski } 218c501d73cSMariusz Zaborski 219c501d73cSMariusz Zaborski errno = serrno; 220c501d73cSMariusz Zaborski 221c501d73cSMariusz Zaborski return (result); 222c501d73cSMariusz Zaborski } 223c501d73cSMariusz Zaborski 224c501d73cSMariusz Zaborski struct passwd * 225c501d73cSMariusz Zaborski cap_getpwent(cap_channel_t *chan) 226c501d73cSMariusz Zaborski { 227c501d73cSMariusz Zaborski 228c501d73cSMariusz Zaborski return (cap_getpwcommon(chan, "getpwent", NULL, 0)); 229c501d73cSMariusz Zaborski } 230c501d73cSMariusz Zaborski 231c501d73cSMariusz Zaborski struct passwd * 232c501d73cSMariusz Zaborski cap_getpwnam(cap_channel_t *chan, const char *login) 233c501d73cSMariusz Zaborski { 234c501d73cSMariusz Zaborski 235c501d73cSMariusz Zaborski return (cap_getpwcommon(chan, "getpwnam", login, 0)); 236c501d73cSMariusz Zaborski } 237c501d73cSMariusz Zaborski 238c501d73cSMariusz Zaborski struct passwd * 239c501d73cSMariusz Zaborski cap_getpwuid(cap_channel_t *chan, uid_t uid) 240c501d73cSMariusz Zaborski { 241c501d73cSMariusz Zaborski 242c501d73cSMariusz Zaborski return (cap_getpwcommon(chan, "getpwuid", NULL, uid)); 243c501d73cSMariusz Zaborski } 244c501d73cSMariusz Zaborski 245c501d73cSMariusz Zaborski int 246c501d73cSMariusz Zaborski cap_getpwent_r(cap_channel_t *chan, struct passwd *pwd, char *buffer, 247c501d73cSMariusz Zaborski size_t bufsize, struct passwd **result) 248c501d73cSMariusz Zaborski { 249c501d73cSMariusz Zaborski 250c501d73cSMariusz Zaborski return (cap_getpwcommon_r(chan, "getpwent_r", NULL, 0, pwd, buffer, 251c501d73cSMariusz Zaborski bufsize, result)); 252c501d73cSMariusz Zaborski } 253c501d73cSMariusz Zaborski 254c501d73cSMariusz Zaborski int 255c501d73cSMariusz Zaborski cap_getpwnam_r(cap_channel_t *chan, const char *name, struct passwd *pwd, 256c501d73cSMariusz Zaborski char *buffer, size_t bufsize, struct passwd **result) 257c501d73cSMariusz Zaborski { 258c501d73cSMariusz Zaborski 259c501d73cSMariusz Zaborski return (cap_getpwcommon_r(chan, "getpwnam_r", name, 0, pwd, buffer, 260c501d73cSMariusz Zaborski bufsize, result)); 261c501d73cSMariusz Zaborski } 262c501d73cSMariusz Zaborski 263c501d73cSMariusz Zaborski int 264c501d73cSMariusz Zaborski cap_getpwuid_r(cap_channel_t *chan, uid_t uid, struct passwd *pwd, char *buffer, 265c501d73cSMariusz Zaborski size_t bufsize, struct passwd **result) 266c501d73cSMariusz Zaborski { 267c501d73cSMariusz Zaborski 268c501d73cSMariusz Zaborski return (cap_getpwcommon_r(chan, "getpwuid_r", NULL, uid, pwd, buffer, 269c501d73cSMariusz Zaborski bufsize, result)); 270c501d73cSMariusz Zaborski } 271c501d73cSMariusz Zaborski 272c501d73cSMariusz Zaborski int 273c501d73cSMariusz Zaborski cap_setpassent(cap_channel_t *chan, int stayopen) 274c501d73cSMariusz Zaborski { 275c501d73cSMariusz Zaborski nvlist_t *nvl; 276c501d73cSMariusz Zaborski 277c501d73cSMariusz Zaborski nvl = nvlist_create(0); 278c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", "setpassent"); 279c501d73cSMariusz Zaborski nvlist_add_bool(nvl, "stayopen", stayopen != 0); 2804fc0a279SMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 281c501d73cSMariusz Zaborski if (nvl == NULL) 282c501d73cSMariusz Zaborski return (0); 283c501d73cSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 284c501d73cSMariusz Zaborski errno = nvlist_get_number(nvl, "error"); 285c501d73cSMariusz Zaborski nvlist_destroy(nvl); 286c501d73cSMariusz Zaborski return (0); 287c501d73cSMariusz Zaborski } 288c501d73cSMariusz Zaborski nvlist_destroy(nvl); 289c501d73cSMariusz Zaborski 290c501d73cSMariusz Zaborski return (1); 291c501d73cSMariusz Zaborski } 292c501d73cSMariusz Zaborski 293c501d73cSMariusz Zaborski static void 294c501d73cSMariusz Zaborski cap_set_end_pwent(cap_channel_t *chan, const char *cmd) 295c501d73cSMariusz Zaborski { 296c501d73cSMariusz Zaborski nvlist_t *nvl; 297c501d73cSMariusz Zaborski 298c501d73cSMariusz Zaborski nvl = nvlist_create(0); 299c501d73cSMariusz Zaborski nvlist_add_string(nvl, "cmd", cmd); 300c501d73cSMariusz Zaborski /* Ignore any errors, we have no way to report them. */ 3014fc0a279SMariusz Zaborski nvlist_destroy(cap_xfer_nvlist(chan, nvl)); 302c501d73cSMariusz Zaborski } 303c501d73cSMariusz Zaborski 304c501d73cSMariusz Zaborski void 305c501d73cSMariusz Zaborski cap_setpwent(cap_channel_t *chan) 306c501d73cSMariusz Zaborski { 307c501d73cSMariusz Zaborski 308c501d73cSMariusz Zaborski cap_set_end_pwent(chan, "setpwent"); 309c501d73cSMariusz Zaborski } 310c501d73cSMariusz Zaborski 311c501d73cSMariusz Zaborski void 312c501d73cSMariusz Zaborski cap_endpwent(cap_channel_t *chan) 313c501d73cSMariusz Zaborski { 314c501d73cSMariusz Zaborski 315c501d73cSMariusz Zaborski cap_set_end_pwent(chan, "endpwent"); 316c501d73cSMariusz Zaborski } 317c501d73cSMariusz Zaborski 318c501d73cSMariusz Zaborski int 319c501d73cSMariusz Zaborski cap_pwd_limit_cmds(cap_channel_t *chan, const char * const *cmds, size_t ncmds) 320c501d73cSMariusz Zaborski { 321c501d73cSMariusz Zaborski nvlist_t *limits, *nvl; 322c501d73cSMariusz Zaborski unsigned int i; 323c501d73cSMariusz Zaborski 324c501d73cSMariusz Zaborski if (cap_limit_get(chan, &limits) < 0) 325c501d73cSMariusz Zaborski return (-1); 326c501d73cSMariusz Zaborski if (limits == NULL) { 327c501d73cSMariusz Zaborski limits = nvlist_create(0); 328c501d73cSMariusz Zaborski } else { 329c501d73cSMariusz Zaborski if (nvlist_exists_nvlist(limits, "cmds")) 330c501d73cSMariusz Zaborski nvlist_free_nvlist(limits, "cmds"); 331c501d73cSMariusz Zaborski } 332c501d73cSMariusz Zaborski nvl = nvlist_create(0); 333c501d73cSMariusz Zaborski for (i = 0; i < ncmds; i++) 334c501d73cSMariusz Zaborski nvlist_add_null(nvl, cmds[i]); 335c501d73cSMariusz Zaborski nvlist_move_nvlist(limits, "cmds", nvl); 336c501d73cSMariusz Zaborski return (cap_limit_set(chan, limits)); 337c501d73cSMariusz Zaborski } 338c501d73cSMariusz Zaborski 339c501d73cSMariusz Zaborski int 340c501d73cSMariusz Zaborski cap_pwd_limit_fields(cap_channel_t *chan, const char * const *fields, 341c501d73cSMariusz Zaborski size_t nfields) 342c501d73cSMariusz Zaborski { 343c501d73cSMariusz Zaborski nvlist_t *limits, *nvl; 344c501d73cSMariusz Zaborski unsigned int i; 345c501d73cSMariusz Zaborski 346c501d73cSMariusz Zaborski if (cap_limit_get(chan, &limits) < 0) 347c501d73cSMariusz Zaborski return (-1); 348c501d73cSMariusz Zaborski if (limits == NULL) { 349c501d73cSMariusz Zaborski limits = nvlist_create(0); 350c501d73cSMariusz Zaborski } else { 351c501d73cSMariusz Zaborski if (nvlist_exists_nvlist(limits, "fields")) 352c501d73cSMariusz Zaborski nvlist_free_nvlist(limits, "fields"); 353c501d73cSMariusz Zaborski } 354c501d73cSMariusz Zaborski nvl = nvlist_create(0); 355c501d73cSMariusz Zaborski for (i = 0; i < nfields; i++) 356c501d73cSMariusz Zaborski nvlist_add_null(nvl, fields[i]); 357c501d73cSMariusz Zaborski nvlist_move_nvlist(limits, "fields", nvl); 358c501d73cSMariusz Zaborski return (cap_limit_set(chan, limits)); 359c501d73cSMariusz Zaborski } 360c501d73cSMariusz Zaborski 361c501d73cSMariusz Zaborski int 362c501d73cSMariusz Zaborski cap_pwd_limit_users(cap_channel_t *chan, const char * const *names, 363c501d73cSMariusz Zaborski size_t nnames, uid_t *uids, size_t nuids) 364c501d73cSMariusz Zaborski { 365c501d73cSMariusz Zaborski nvlist_t *limits, *users; 366c501d73cSMariusz Zaborski char nvlname[64]; 367c501d73cSMariusz Zaborski unsigned int i; 368c501d73cSMariusz Zaborski int n; 369c501d73cSMariusz Zaborski 370c501d73cSMariusz Zaborski if (cap_limit_get(chan, &limits) < 0) 371c501d73cSMariusz Zaborski return (-1); 372c501d73cSMariusz Zaborski if (limits == NULL) { 373c501d73cSMariusz Zaborski limits = nvlist_create(0); 374c501d73cSMariusz Zaborski } else { 375c501d73cSMariusz Zaborski if (nvlist_exists_nvlist(limits, "users")) 376c501d73cSMariusz Zaborski nvlist_free_nvlist(limits, "users"); 377c501d73cSMariusz Zaborski } 378c501d73cSMariusz Zaborski users = nvlist_create(0); 379c501d73cSMariusz Zaborski for (i = 0; i < nuids; i++) { 380c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "uid%u", i); 381c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 382c501d73cSMariusz Zaborski nvlist_add_number(users, nvlname, (uint64_t)uids[i]); 383c501d73cSMariusz Zaborski } 384c501d73cSMariusz Zaborski for (i = 0; i < nnames; i++) { 385c501d73cSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "name%u", i); 386c501d73cSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 387c501d73cSMariusz Zaborski nvlist_add_string(users, nvlname, names[i]); 388c501d73cSMariusz Zaborski } 389c501d73cSMariusz Zaborski nvlist_move_nvlist(limits, "users", users); 390c501d73cSMariusz Zaborski return (cap_limit_set(chan, limits)); 391c501d73cSMariusz Zaborski } 392c501d73cSMariusz Zaborski 393c501d73cSMariusz Zaborski 394c501d73cSMariusz Zaborski /* 395c501d73cSMariusz Zaborski * Service functions. 396c501d73cSMariusz Zaborski */ 397c501d73cSMariusz Zaborski static bool 398c501d73cSMariusz Zaborski pwd_allowed_cmd(const nvlist_t *limits, const char *cmd) 399c501d73cSMariusz Zaborski { 400c501d73cSMariusz Zaborski 401c501d73cSMariusz Zaborski if (limits == NULL) 402c501d73cSMariusz Zaborski return (true); 403c501d73cSMariusz Zaborski 404c501d73cSMariusz Zaborski /* 405c501d73cSMariusz Zaborski * If no limit was set on allowed commands, then all commands 406c501d73cSMariusz Zaborski * are allowed. 407c501d73cSMariusz Zaborski */ 408c501d73cSMariusz Zaborski if (!nvlist_exists_nvlist(limits, "cmds")) 409c501d73cSMariusz Zaborski return (true); 410c501d73cSMariusz Zaborski 411c501d73cSMariusz Zaborski limits = nvlist_get_nvlist(limits, "cmds"); 412c501d73cSMariusz Zaborski return (nvlist_exists_null(limits, cmd)); 413c501d73cSMariusz Zaborski } 414c501d73cSMariusz Zaborski 415c501d73cSMariusz Zaborski static int 416c501d73cSMariusz Zaborski pwd_allowed_cmds(const nvlist_t *oldlimits, const nvlist_t *newlimits) 417c501d73cSMariusz Zaborski { 418c501d73cSMariusz Zaborski const char *name; 419c501d73cSMariusz Zaborski void *cookie; 420c501d73cSMariusz Zaborski int type; 421c501d73cSMariusz Zaborski 422c501d73cSMariusz Zaborski cookie = NULL; 423c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { 424c501d73cSMariusz Zaborski if (type != NV_TYPE_NULL) 425c501d73cSMariusz Zaborski return (EINVAL); 426c501d73cSMariusz Zaborski if (!pwd_allowed_cmd(oldlimits, name)) 427c501d73cSMariusz Zaborski return (ENOTCAPABLE); 428c501d73cSMariusz Zaborski } 429c501d73cSMariusz Zaborski 430c501d73cSMariusz Zaborski return (0); 431c501d73cSMariusz Zaborski } 432c501d73cSMariusz Zaborski 433c501d73cSMariusz Zaborski static bool 434c501d73cSMariusz Zaborski pwd_allowed_user(const nvlist_t *limits, const char *uname, uid_t uid) 435c501d73cSMariusz Zaborski { 436c501d73cSMariusz Zaborski const char *name; 437c501d73cSMariusz Zaborski void *cookie; 438c501d73cSMariusz Zaborski int type; 439c501d73cSMariusz Zaborski 440c501d73cSMariusz Zaborski if (limits == NULL) 441c501d73cSMariusz Zaborski return (true); 442c501d73cSMariusz Zaborski 443c501d73cSMariusz Zaborski /* 444c501d73cSMariusz Zaborski * If no limit was set on allowed users, then all users are allowed. 445c501d73cSMariusz Zaborski */ 446c501d73cSMariusz Zaborski if (!nvlist_exists_nvlist(limits, "users")) 447c501d73cSMariusz Zaborski return (true); 448c501d73cSMariusz Zaborski 449c501d73cSMariusz Zaborski limits = nvlist_get_nvlist(limits, "users"); 450c501d73cSMariusz Zaborski cookie = NULL; 451c501d73cSMariusz Zaborski while ((name = nvlist_next(limits, &type, &cookie)) != NULL) { 452c501d73cSMariusz Zaborski switch (type) { 453c501d73cSMariusz Zaborski case NV_TYPE_NUMBER: 454c501d73cSMariusz Zaborski if (uid != (uid_t)-1 && 455c501d73cSMariusz Zaborski nvlist_get_number(limits, name) == (uint64_t)uid) { 456c501d73cSMariusz Zaborski return (true); 457c501d73cSMariusz Zaborski } 458c501d73cSMariusz Zaborski break; 459c501d73cSMariusz Zaborski case NV_TYPE_STRING: 460c501d73cSMariusz Zaborski if (uname != NULL && 461c501d73cSMariusz Zaborski strcmp(nvlist_get_string(limits, name), 462c501d73cSMariusz Zaborski uname) == 0) { 463c501d73cSMariusz Zaborski return (true); 464c501d73cSMariusz Zaborski } 465c501d73cSMariusz Zaborski break; 466c501d73cSMariusz Zaborski default: 467c501d73cSMariusz Zaborski abort(); 468c501d73cSMariusz Zaborski } 469c501d73cSMariusz Zaborski } 470c501d73cSMariusz Zaborski 471c501d73cSMariusz Zaborski return (false); 472c501d73cSMariusz Zaborski } 473c501d73cSMariusz Zaborski 474c501d73cSMariusz Zaborski static int 475c501d73cSMariusz Zaborski pwd_allowed_users(const nvlist_t *oldlimits, const nvlist_t *newlimits) 476c501d73cSMariusz Zaborski { 477c501d73cSMariusz Zaborski const char *name, *uname; 478c501d73cSMariusz Zaborski void *cookie; 479c501d73cSMariusz Zaborski uid_t uid; 480c501d73cSMariusz Zaborski int type; 481c501d73cSMariusz Zaborski 482c501d73cSMariusz Zaborski cookie = NULL; 483c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { 484c501d73cSMariusz Zaborski switch (type) { 485c501d73cSMariusz Zaborski case NV_TYPE_NUMBER: 486c501d73cSMariusz Zaborski uid = (uid_t)nvlist_get_number(newlimits, name); 487c501d73cSMariusz Zaborski uname = NULL; 488c501d73cSMariusz Zaborski break; 489c501d73cSMariusz Zaborski case NV_TYPE_STRING: 490c501d73cSMariusz Zaborski uid = (uid_t)-1; 491c501d73cSMariusz Zaborski uname = nvlist_get_string(newlimits, name); 492c501d73cSMariusz Zaborski break; 493c501d73cSMariusz Zaborski default: 494c501d73cSMariusz Zaborski return (EINVAL); 495c501d73cSMariusz Zaborski } 496c501d73cSMariusz Zaborski if (!pwd_allowed_user(oldlimits, uname, uid)) 497c501d73cSMariusz Zaborski return (ENOTCAPABLE); 498c501d73cSMariusz Zaborski } 499c501d73cSMariusz Zaborski 500c501d73cSMariusz Zaborski return (0); 501c501d73cSMariusz Zaborski } 502c501d73cSMariusz Zaborski 503c501d73cSMariusz Zaborski static bool 504c501d73cSMariusz Zaborski pwd_allowed_field(const nvlist_t *limits, const char *field) 505c501d73cSMariusz Zaborski { 506c501d73cSMariusz Zaborski 507c501d73cSMariusz Zaborski if (limits == NULL) 508c501d73cSMariusz Zaborski return (true); 509c501d73cSMariusz Zaborski 510c501d73cSMariusz Zaborski /* 511c501d73cSMariusz Zaborski * If no limit was set on allowed fields, then all fields are allowed. 512c501d73cSMariusz Zaborski */ 513c501d73cSMariusz Zaborski if (!nvlist_exists_nvlist(limits, "fields")) 514c501d73cSMariusz Zaborski return (true); 515c501d73cSMariusz Zaborski 516c501d73cSMariusz Zaborski limits = nvlist_get_nvlist(limits, "fields"); 517c501d73cSMariusz Zaborski return (nvlist_exists_null(limits, field)); 518c501d73cSMariusz Zaborski } 519c501d73cSMariusz Zaborski 520c501d73cSMariusz Zaborski static int 521c501d73cSMariusz Zaborski pwd_allowed_fields(const nvlist_t *oldlimits, const nvlist_t *newlimits) 522c501d73cSMariusz Zaborski { 523c501d73cSMariusz Zaborski const char *name; 524c501d73cSMariusz Zaborski void *cookie; 525c501d73cSMariusz Zaborski int type; 526c501d73cSMariusz Zaborski 527c501d73cSMariusz Zaborski cookie = NULL; 528c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { 529c501d73cSMariusz Zaborski if (type != NV_TYPE_NULL) 530c501d73cSMariusz Zaborski return (EINVAL); 531c501d73cSMariusz Zaborski if (!pwd_allowed_field(oldlimits, name)) 532c501d73cSMariusz Zaborski return (ENOTCAPABLE); 533c501d73cSMariusz Zaborski } 534c501d73cSMariusz Zaborski 535c501d73cSMariusz Zaborski return (0); 536c501d73cSMariusz Zaborski } 537c501d73cSMariusz Zaborski 538c501d73cSMariusz Zaborski static bool 539c501d73cSMariusz Zaborski pwd_pack(const nvlist_t *limits, const struct passwd *pwd, nvlist_t *nvl) 540c501d73cSMariusz Zaborski { 541c501d73cSMariusz Zaborski int fields; 542c501d73cSMariusz Zaborski 543c501d73cSMariusz Zaborski if (pwd == NULL) 544c501d73cSMariusz Zaborski return (true); 545c501d73cSMariusz Zaborski 546c501d73cSMariusz Zaborski /* 547c501d73cSMariusz Zaborski * If either name or UID is allowed, we allow it. 548c501d73cSMariusz Zaborski */ 549c501d73cSMariusz Zaborski if (!pwd_allowed_user(limits, pwd->pw_name, pwd->pw_uid)) 550c501d73cSMariusz Zaborski return (false); 551c501d73cSMariusz Zaborski 552c501d73cSMariusz Zaborski fields = pwd->pw_fields; 553c501d73cSMariusz Zaborski 554c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_name")) { 555c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_name", pwd->pw_name); 556c501d73cSMariusz Zaborski } else { 557c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_name", ""); 558c501d73cSMariusz Zaborski fields &= ~_PWF_NAME; 559c501d73cSMariusz Zaborski } 560c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_uid")) { 561c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_uid", (uint64_t)pwd->pw_uid); 562c501d73cSMariusz Zaborski } else { 563c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_uid", (uint64_t)-1); 564c501d73cSMariusz Zaborski fields &= ~_PWF_UID; 565c501d73cSMariusz Zaborski } 566c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_gid")) { 567c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_gid", (uint64_t)pwd->pw_gid); 568c501d73cSMariusz Zaborski } else { 569c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_gid", (uint64_t)-1); 570c501d73cSMariusz Zaborski fields &= ~_PWF_GID; 571c501d73cSMariusz Zaborski } 572c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_change")) { 573c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_change", (uint64_t)pwd->pw_change); 574c501d73cSMariusz Zaborski } else { 575c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_change", (uint64_t)0); 576c501d73cSMariusz Zaborski fields &= ~_PWF_CHANGE; 577c501d73cSMariusz Zaborski } 578c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_passwd")) { 579c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_passwd", pwd->pw_passwd); 580c501d73cSMariusz Zaborski } else { 581c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_passwd", ""); 582c501d73cSMariusz Zaborski fields &= ~_PWF_PASSWD; 583c501d73cSMariusz Zaborski } 584c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_class")) { 585c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_class", pwd->pw_class); 586c501d73cSMariusz Zaborski } else { 587c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_class", ""); 588c501d73cSMariusz Zaborski fields &= ~_PWF_CLASS; 589c501d73cSMariusz Zaborski } 590c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_gecos")) { 591c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_gecos", pwd->pw_gecos); 592c501d73cSMariusz Zaborski } else { 593c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_gecos", ""); 594c501d73cSMariusz Zaborski fields &= ~_PWF_GECOS; 595c501d73cSMariusz Zaborski } 596c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_dir")) { 597c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_dir", pwd->pw_dir); 598c501d73cSMariusz Zaborski } else { 599c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_dir", ""); 600c501d73cSMariusz Zaborski fields &= ~_PWF_DIR; 601c501d73cSMariusz Zaborski } 602c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_shell")) { 603c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_shell", pwd->pw_shell); 604c501d73cSMariusz Zaborski } else { 605c501d73cSMariusz Zaborski nvlist_add_string(nvl, "pw_shell", ""); 606c501d73cSMariusz Zaborski fields &= ~_PWF_SHELL; 607c501d73cSMariusz Zaborski } 608c501d73cSMariusz Zaborski if (pwd_allowed_field(limits, "pw_expire")) { 609c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_expire", (uint64_t)pwd->pw_expire); 610c501d73cSMariusz Zaborski } else { 611c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_expire", (uint64_t)0); 612c501d73cSMariusz Zaborski fields &= ~_PWF_EXPIRE; 613c501d73cSMariusz Zaborski } 614c501d73cSMariusz Zaborski nvlist_add_number(nvl, "pw_fields", (uint64_t)fields); 615c501d73cSMariusz Zaborski 616c501d73cSMariusz Zaborski return (true); 617c501d73cSMariusz Zaborski } 618c501d73cSMariusz Zaborski 619c501d73cSMariusz Zaborski static int 620c501d73cSMariusz Zaborski pwd_getpwent(const nvlist_t *limits, const nvlist_t *nvlin __unused, 621c501d73cSMariusz Zaborski nvlist_t *nvlout) 622c501d73cSMariusz Zaborski { 623c501d73cSMariusz Zaborski struct passwd *pwd; 624c501d73cSMariusz Zaborski 625c501d73cSMariusz Zaborski for (;;) { 626c501d73cSMariusz Zaborski errno = 0; 627c501d73cSMariusz Zaborski pwd = getpwent(); 628c501d73cSMariusz Zaborski if (errno != 0) 629c501d73cSMariusz Zaborski return (errno); 630c501d73cSMariusz Zaborski if (pwd_pack(limits, pwd, nvlout)) 631c501d73cSMariusz Zaborski return (0); 632c501d73cSMariusz Zaborski } 633c501d73cSMariusz Zaborski 634c501d73cSMariusz Zaborski /* NOTREACHED */ 635c501d73cSMariusz Zaborski } 636c501d73cSMariusz Zaborski 637c501d73cSMariusz Zaborski static int 638c501d73cSMariusz Zaborski pwd_getpwnam(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) 639c501d73cSMariusz Zaborski { 640c501d73cSMariusz Zaborski struct passwd *pwd; 641c501d73cSMariusz Zaborski const char *name; 642c501d73cSMariusz Zaborski 643c501d73cSMariusz Zaborski if (!nvlist_exists_string(nvlin, "name")) 644c501d73cSMariusz Zaborski return (EINVAL); 645c501d73cSMariusz Zaborski name = nvlist_get_string(nvlin, "name"); 646c501d73cSMariusz Zaborski assert(name != NULL); 647c501d73cSMariusz Zaborski 648c501d73cSMariusz Zaborski errno = 0; 649c501d73cSMariusz Zaborski pwd = getpwnam(name); 650c501d73cSMariusz Zaborski if (errno != 0) 651c501d73cSMariusz Zaborski return (errno); 652c501d73cSMariusz Zaborski 653c501d73cSMariusz Zaborski (void)pwd_pack(limits, pwd, nvlout); 654c501d73cSMariusz Zaborski 655c501d73cSMariusz Zaborski return (0); 656c501d73cSMariusz Zaborski } 657c501d73cSMariusz Zaborski 658c501d73cSMariusz Zaborski static int 659c501d73cSMariusz Zaborski pwd_getpwuid(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) 660c501d73cSMariusz Zaborski { 661c501d73cSMariusz Zaborski struct passwd *pwd; 662c501d73cSMariusz Zaborski uid_t uid; 663c501d73cSMariusz Zaborski 664c501d73cSMariusz Zaborski if (!nvlist_exists_number(nvlin, "uid")) 665c501d73cSMariusz Zaborski return (EINVAL); 666c501d73cSMariusz Zaborski 667c501d73cSMariusz Zaborski uid = (uid_t)nvlist_get_number(nvlin, "uid"); 668c501d73cSMariusz Zaborski 669c501d73cSMariusz Zaborski errno = 0; 670c501d73cSMariusz Zaborski pwd = getpwuid(uid); 671c501d73cSMariusz Zaborski if (errno != 0) 672c501d73cSMariusz Zaborski return (errno); 673c501d73cSMariusz Zaborski 674c501d73cSMariusz Zaborski (void)pwd_pack(limits, pwd, nvlout); 675c501d73cSMariusz Zaborski 676c501d73cSMariusz Zaborski return (0); 677c501d73cSMariusz Zaborski } 678c501d73cSMariusz Zaborski 679c501d73cSMariusz Zaborski static int 680c501d73cSMariusz Zaborski pwd_setpassent(const nvlist_t *limits __unused, const nvlist_t *nvlin, 681c501d73cSMariusz Zaborski nvlist_t *nvlout __unused) 682c501d73cSMariusz Zaborski { 683c501d73cSMariusz Zaborski int stayopen; 684c501d73cSMariusz Zaborski 685c501d73cSMariusz Zaborski if (!nvlist_exists_bool(nvlin, "stayopen")) 686c501d73cSMariusz Zaborski return (EINVAL); 687c501d73cSMariusz Zaborski 688c501d73cSMariusz Zaborski stayopen = nvlist_get_bool(nvlin, "stayopen") ? 1 : 0; 689c501d73cSMariusz Zaborski 690c501d73cSMariusz Zaborski return (setpassent(stayopen) == 0 ? EFAULT : 0); 691c501d73cSMariusz Zaborski } 692c501d73cSMariusz Zaborski 693c501d73cSMariusz Zaborski static int 694c501d73cSMariusz Zaborski pwd_setpwent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, 695c501d73cSMariusz Zaborski nvlist_t *nvlout __unused) 696c501d73cSMariusz Zaborski { 697c501d73cSMariusz Zaborski 698c501d73cSMariusz Zaborski setpwent(); 699c501d73cSMariusz Zaborski 700c501d73cSMariusz Zaborski return (0); 701c501d73cSMariusz Zaborski } 702c501d73cSMariusz Zaborski 703c501d73cSMariusz Zaborski static int 704c501d73cSMariusz Zaborski pwd_endpwent(const nvlist_t *limits __unused, const nvlist_t *nvlin __unused, 705c501d73cSMariusz Zaborski nvlist_t *nvlout __unused) 706c501d73cSMariusz Zaborski { 707c501d73cSMariusz Zaborski 708c501d73cSMariusz Zaborski endpwent(); 709c501d73cSMariusz Zaborski 710c501d73cSMariusz Zaborski return (0); 711c501d73cSMariusz Zaborski } 712c501d73cSMariusz Zaborski 713c501d73cSMariusz Zaborski static int 714c501d73cSMariusz Zaborski pwd_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) 715c501d73cSMariusz Zaborski { 716c501d73cSMariusz Zaborski const nvlist_t *limits; 717c501d73cSMariusz Zaborski const char *name; 718c501d73cSMariusz Zaborski void *cookie; 719c501d73cSMariusz Zaborski int error, type; 720c501d73cSMariusz Zaborski 721c501d73cSMariusz Zaborski if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "cmds") && 722c501d73cSMariusz Zaborski !nvlist_exists_nvlist(newlimits, "cmds")) { 723c501d73cSMariusz Zaborski return (ENOTCAPABLE); 724c501d73cSMariusz Zaborski } 725c501d73cSMariusz Zaborski if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "fields") && 726c501d73cSMariusz Zaborski !nvlist_exists_nvlist(newlimits, "fields")) { 727c501d73cSMariusz Zaborski return (ENOTCAPABLE); 728c501d73cSMariusz Zaborski } 729c501d73cSMariusz Zaborski if (oldlimits != NULL && nvlist_exists_nvlist(oldlimits, "users") && 730c501d73cSMariusz Zaborski !nvlist_exists_nvlist(newlimits, "users")) { 731c501d73cSMariusz Zaborski return (ENOTCAPABLE); 732c501d73cSMariusz Zaborski } 733c501d73cSMariusz Zaborski 734c501d73cSMariusz Zaborski cookie = NULL; 735c501d73cSMariusz Zaborski while ((name = nvlist_next(newlimits, &type, &cookie)) != NULL) { 736c501d73cSMariusz Zaborski if (type != NV_TYPE_NVLIST) 737c501d73cSMariusz Zaborski return (EINVAL); 738c501d73cSMariusz Zaborski limits = nvlist_get_nvlist(newlimits, name); 739c501d73cSMariusz Zaborski if (strcmp(name, "cmds") == 0) 740c501d73cSMariusz Zaborski error = pwd_allowed_cmds(oldlimits, limits); 741c501d73cSMariusz Zaborski else if (strcmp(name, "fields") == 0) 742c501d73cSMariusz Zaborski error = pwd_allowed_fields(oldlimits, limits); 743c501d73cSMariusz Zaborski else if (strcmp(name, "users") == 0) 744c501d73cSMariusz Zaborski error = pwd_allowed_users(oldlimits, limits); 745c501d73cSMariusz Zaborski else 746c501d73cSMariusz Zaborski error = EINVAL; 747c501d73cSMariusz Zaborski if (error != 0) 748c501d73cSMariusz Zaborski return (error); 749c501d73cSMariusz Zaborski } 750c501d73cSMariusz Zaborski 751c501d73cSMariusz Zaborski return (0); 752c501d73cSMariusz Zaborski } 753c501d73cSMariusz Zaborski 754c501d73cSMariusz Zaborski static int 755c501d73cSMariusz Zaborski pwd_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, 756c501d73cSMariusz Zaborski nvlist_t *nvlout) 757c501d73cSMariusz Zaborski { 758c501d73cSMariusz Zaborski int error; 759c501d73cSMariusz Zaborski 760c501d73cSMariusz Zaborski if (!pwd_allowed_cmd(limits, cmd)) 761c501d73cSMariusz Zaborski return (ENOTCAPABLE); 762c501d73cSMariusz Zaborski 763c501d73cSMariusz Zaborski if (strcmp(cmd, "getpwent") == 0 || strcmp(cmd, "getpwent_r") == 0) 764c501d73cSMariusz Zaborski error = pwd_getpwent(limits, nvlin, nvlout); 765c501d73cSMariusz Zaborski else if (strcmp(cmd, "getpwnam") == 0 || strcmp(cmd, "getpwnam_r") == 0) 766c501d73cSMariusz Zaborski error = pwd_getpwnam(limits, nvlin, nvlout); 767c501d73cSMariusz Zaborski else if (strcmp(cmd, "getpwuid") == 0 || strcmp(cmd, "getpwuid_r") == 0) 768c501d73cSMariusz Zaborski error = pwd_getpwuid(limits, nvlin, nvlout); 769c501d73cSMariusz Zaborski else if (strcmp(cmd, "setpassent") == 0) 770c501d73cSMariusz Zaborski error = pwd_setpassent(limits, nvlin, nvlout); 771c501d73cSMariusz Zaborski else if (strcmp(cmd, "setpwent") == 0) 772c501d73cSMariusz Zaborski error = pwd_setpwent(limits, nvlin, nvlout); 773c501d73cSMariusz Zaborski else if (strcmp(cmd, "endpwent") == 0) 774c501d73cSMariusz Zaborski error = pwd_endpwent(limits, nvlin, nvlout); 775c501d73cSMariusz Zaborski else 776c501d73cSMariusz Zaborski error = EINVAL; 777c501d73cSMariusz Zaborski 778c501d73cSMariusz Zaborski return (error); 779c501d73cSMariusz Zaborski } 780c501d73cSMariusz Zaborski 781920be817SMariusz Zaborski CREATE_SERVICE("system.pwd", pwd_limit, pwd_command, 0); 782