4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
38 #include <nss_dbdefs.h>
39 #include <sys/types.h>
42 #include <tsol/label.h>
44 #include <bsm/devalloc.h>
47 #if !defined(TEXT_DOMAIN)
48 #define TEXT_DOMAIN "SUNW_OST_OSCMD"
51 #define ALLOC "allocate"
52 #define DEALLOC "deallocate"
53 #define LIST "list_devices"
55 extern void audit_allocate_argv(int, int, char *[]);
56 extern int audit_allocate_record(int);
58 int system_labeled
= 0;
59 static int windowing
= 0;
60 static int wdwmsg(char *name
, char *msg
);
68 use
[0] = gettext("allocate [-s] [-w] [-U uname] [-z zonename] "
69 "[-F] device|-g dev-type");
70 use
[1] = gettext("deallocate [-s] [-w] [-z zonename] "
71 "[-F] device|-c dev-class|-g dev-type");
72 use
[2] = gettext("deallocate [-s] [-w] [-z zonename] -I");
73 use
[3] = gettext("list_devices [-s] [-U uid] [-z zonename] "
74 "[-a [-w]] -l|-n|-u [device]");
75 use
[4] = gettext("list_devices [-s] [-U uid] [-z zonename] "
76 "[-a [-w]] [-l|-n|-u] -c dev-class");
77 use
[5] = gettext("list_devices [-s] -d [dev-type]");
81 (void) fprintf(stderr
, "%s\n", use
[0]);
84 (void) fprintf(stderr
, "%s\n%s\n",
88 (void) fprintf(stderr
, "%s\n%s\n%s\n",
89 use
[3], use
[4], use
[5]);
92 (void) fprintf(stderr
,
93 "%s\n%s\n%s\n%s\n%s\n%s\n",
94 use
[0], use
[1], use
[2], use
[3], use
[4],
100 use
[0] = gettext("allocate "
101 "[-s] [-U uname] [-F] device|-g dev-type");
102 use
[1] = gettext("deallocate [-s] [-F] device|-c dev-class");
103 use
[2] = gettext("deallocate [-s] -I");
104 use
[3] = gettext("list_devices "
105 "[-s] [-U uid] -l|-n|-u [device]");
106 use
[4] = gettext("list_devices "
107 "[-s] [-U uid] [-l|-n|-u] -c dev-class");
111 (void) fprintf(stderr
, "%s\n", use
[0]);
114 (void) fprintf(stderr
, "%s\n%s\n",
118 (void) fprintf(stderr
, "%s\n%s\n",
122 (void) fprintf(stderr
, "%s\n%s\n%s\n%s\n%s\n",
123 use
[0], use
[1], use
[2], use
[3], use
[4]);
130 print_error(int error
, char *name
)
137 msg
= gettext("Specified device is allocated to another user.");
140 msg
= gettext("Failed to chown.");
143 msg
= gettext("Unable to clean up device.");
147 "Can't exec device-clean program for specified device.");
150 msg
= gettext("Can't force deallocate specified device.");
154 "Can't access DAC file for the device specified.");
158 "Device allocation feature is not activated "
162 msg
= gettext("Device not allocatable.");
165 msg
= gettext("No default attributes for specified "
169 msg
= gettext("Concurrent operations for specified device, "
173 msg
= gettext("Device name is too long.");
176 msg
= gettext("Device not allocated.");
179 msg
= gettext("Device name error.");
182 msg
= gettext("Device specified is in allocate error state.");
185 msg
= gettext("Can't find name of the zone to which "
186 "device is allocated.");
190 "Device special file(s) missing for specified device.");
194 "Operation inconsistent with device's label range.");
196 case LOGINDEVPERMERR
:
197 msg
= gettext("Device controlled by logindevperm(4)");
200 msg
= gettext("No entry for specified device.");
203 msg
= gettext("No entry for specified device.");
206 msg
= gettext("Device already allocated.");
209 msg
= gettext("Failed to set ACL.");
213 "User lacks authorization required for this operation.");
216 msg
= gettext("Failed to configure device in zone.");
219 msg
= gettext("Unknown error code.");
224 (void) snprintf(msgbuf
, sizeof (msgbuf
), "%s: %s\n", name
, msg
);
225 (void) wdwmsg(name
, msgbuf
);
227 (void) fprintf(stderr
, "%s: %s\n", name
, msg
);
228 (void) fflush(stderr
);
232 char *newenv
[] = {"PATH=/usr/bin:/usr/sbin",
233 NULL
, /* for LC_ALL */
234 NULL
, /* for LC_COLLATE */
235 NULL
, /* for LC_CTYPE */
236 NULL
, /* for LC_MESSAGES */
237 NULL
, /* for LC_NUMERIC */
238 NULL
, /* for LC_TIME */
244 getenvent(char *name
, char *env
[])
246 for (; *env
!= NULL
; env
++) {
247 if (strncmp(*env
, name
, strlen(name
)) == 0)
254 main(int argc
, char *argv
[], char *envp
[])
257 int func
= -1, optflg
= 0, error
= 0, c
;
260 char *uname
= NULL
, *device
= NULL
, *zonename
= NULL
;
262 char pw_buf
[NSS_BUFLEN_PASSWD
];
263 struct passwd pw_ent
;
264 int env_num
= 1; /* PATH= is 0 entry */
269 (void) setlocale(LC_ALL
, "");
270 (void) textdomain(TEXT_DOMAIN
);
272 system_labeled
= is_system_labeled();
274 /* test hook: see also mkdevalloc.c and devfsadm.c */
275 if (!system_labeled
) {
276 system_labeled
= is_system_labeled_debug(&statbuf
);
277 if (system_labeled
) {
278 fprintf(stderr
, "/ALLOCATE_FORCE_LABEL is set,\n"
279 "forcing system label on for testing...\n");
284 * get all enviroment variables
285 * which affect on internationalization.
287 env
= getenvent("LC_ALL=", envp
);
289 newenv
[env_num
++] = env
;
290 env
= getenvent("LC_COLLATE=", envp
);
292 newenv
[env_num
++] = env
;
293 env
= getenvent("LC_CTYPE=", envp
);
295 newenv
[env_num
++] = env
;
296 env
= getenvent("LC_MESSAGES=", envp
);
298 newenv
[env_num
++] = env
;
299 env
= getenvent("LC_NUMERIC=", envp
);
301 newenv
[env_num
++] = env
;
302 env
= getenvent("LC_TIME=", envp
);
304 newenv
[env_num
++] = env
;
305 env
= getenvent("LANG=", envp
);
307 newenv
[env_num
] = env
;
309 if ((name
= strrchr(argv
[0], '/')) == NULL
)
314 if (strcmp(name
, ALLOC
) == 0)
316 else if (strcmp(name
, DEALLOC
) == 0)
318 else if (strcmp(name
, LIST
) == 0)
323 audit_allocate_argv(func
, argc
, argv
);
325 if (system_labeled
) {
327 * allocate, deallocate, list_devices run in
330 zoneid
= getzoneid();
331 if (zoneid
!= GLOBAL_ZONEID
)
333 zname
= GLOBAL_ZONENAME
;
335 * check if device allocation is activated.
337 if (da_is_on() == 0) {
338 (void) fprintf(stderr
, "%s%s",
339 gettext("Turn device allocation on"),
340 gettext(" to use this feature.\n"));
345 if (func
== 0) { /* allocate */
346 while ((c
= getopt(argc
, argv
, "g:swz:FU:")) != -1) {
356 if (system_labeled
) {
364 if (system_labeled
) {
385 * allocate(1) must be supplied with one device argument
387 if (device
&& ((argc
- optind
) >= 1))
389 if (device
== NULL
) {
390 if ((argc
- optind
) != 1)
392 device
= argv
[optind
];
396 else if (func
== 1) { /* deallocate */
397 while ((c
= getopt(argc
, argv
, "c:g:swz:FI")) != -1) {
400 if (optflg
& (TYPE
| FORCE_ALL
))
406 if (system_labeled
) {
407 if (optflg
& (CLASS
| FORCE_ALL
))
419 if (system_labeled
) {
427 if (system_labeled
) {
435 if (optflg
& FORCE_ALL
)
440 if (optflg
& (CLASS
| TYPE
| FORCE
))
451 * deallocate(1) must be supplied with one device
452 * argument unless the '-I' argument is supplied
454 if (device
|| (optflg
& FORCE_ALL
)) {
455 if ((argc
- optind
) >= 1)
457 } else if (device
== NULL
) {
458 if ((argc
- optind
) != 1)
460 device
= argv
[optind
];
464 else if (func
== 2) { /* list_devices */
465 while ((c
= getopt(argc
, argv
, "ac:dlnsuwz:U:")) != -1) {
468 if (system_labeled
) {
470 * list auths, cleaning programs,
473 if (optflg
& LISTDEFS
)
485 if (system_labeled
) {
487 * List devalloc_defaults
488 * This cannot used with anything other
491 if (optflg
& (LISTATTRS
| CLASS
|
492 LISTALL
| LISTFREE
| LISTALLOC
|
493 WINDOWING
| ZONENAME
| USERID
))
501 if (optflg
& (LISTFREE
| LISTALLOC
| LISTDEFS
))
506 if (optflg
& (LISTALL
| LISTALLOC
| LISTDEFS
))
514 if (optflg
& (LISTALL
| LISTFREE
| LISTDEFS
))
519 if (system_labeled
) {
520 if (optflg
& LISTDEFS
)
528 if (system_labeled
) {
529 if (optflg
& LISTDEFS
)
538 if (optflg
& LISTDEFS
)
549 if (system_labeled
) {
550 if (!(optflg
& (LISTALL
| LISTFREE
| LISTALLOC
|
551 LISTDEFS
| WINDOWING
))) {
552 if (!(optflg
& CLASS
))
555 } else if (!(optflg
& (LISTALL
| LISTFREE
| LISTALLOC
))) {
556 if (!(optflg
& CLASS
))
561 * list_devices(1) takes an optional device argument.
563 if (device
&& ((argc
- optind
) >= 1))
565 if (device
== NULL
) {
566 if ((argc
- optind
) == 1)
567 device
= argv
[optind
];
568 else if ((argc
- optind
) > 1)
573 if (optflg
& USERNAME
) {
574 if (getpwnam_r(uname
, &pw_ent
, pw_buf
, sizeof (pw_buf
)) ==
576 (void) fprintf(stderr
,
577 gettext("Invalid user name -- %s -- \n"), uname
);
581 } else if (optflg
& USERID
) {
582 if (getpwuid_r(uid
, &pw_ent
, pw_buf
, sizeof (pw_buf
)) == NULL
) {
583 (void) fprintf(stderr
,
584 gettext("Invalid user ID -- %d -- \n"), uid
);
590 * caller's uid is the default if no user specified.
596 * global zone is the default if no zonename specified.
598 if (zonename
== NULL
) {
601 if (zone_get_id(zonename
, &zoneid
) != 0) {
602 (void) fprintf(stderr
,
603 gettext("Invalid zone name -- %s -- \n"), zonename
);
609 error
= allocate(optflg
, uid
, device
, zonename
);
611 error
= deallocate(optflg
, uid
, device
, zonename
);
613 error
= list_devices(optflg
, uid
, device
, zonename
);
615 (void) audit_allocate_record(error
);
618 if (!(optflg
& SILENT
))
619 print_error(error
, name
);
627 * Display error message via /etc/security/lib/wdwmsg script
630 wdwmsg(char *name
, char *msg
)
637 switch (child_pid
= fork()) {
638 case -1: /* FAILURE */
643 (void) execl("/etc/security/lib/wdwmsg", "wdwmsg", msg
,
645 /* If exec failed, send message to stderr */
646 (void) fprintf(stderr
, "%s", msg
);
649 default: /* PARENT */
650 /* Wait for child to exit */
651 wait_pid
= waitpid(child_pid
, &child_status
, 0);
652 if ((wait_pid
< 0) && (errno
== ECHILD
))
654 if ((wait_pid
< 0) || (wait_pid
!= child_pid
))
656 if (WIFEXITED(child_status
))
657 return (WEXITSTATUS(child_status
));
658 if (WIFSIGNALED(child_status
))
659 return (WTERMSIG(child_status
));