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