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"
31 * a command-line interface to add device to device_allocate and
35 #ifndef __EXTENSIONS__
36 #define __EXTENSIONS__ /* needed for _strtok_r */
39 #include <sys/types.h>
47 #include <nss_dbdefs.h>
48 #include <auth_attr.h>
49 #include <auth_list.h>
51 #include <tsol/label.h>
52 #include <bsm/devices.h>
53 #include <bsm/devalloc.h>
55 #define NO_OVERRIDE -1
57 int check_args(da_args
*);
58 int process_args(int, char **, da_args
*, char *);
59 int scan_label(char *, char *);
60 void usage(da_args
*, char *);
62 int system_labeled
= 0;
65 main(int argc
, char *argv
[])
70 char pwbuf
[NSS_LINELEN_PASSWD
];
75 (void) setlocale(LC_ALL
, "");
76 #if !defined(TEXT_DOMAIN)
77 #define TEXT_DOMAIN "SYS_TEST"
79 (void) textdomain(TEXT_DOMAIN
);
80 if ((progname
= strrchr(argv
[0], '/')) == NULL
)
85 system_labeled
= is_system_labeled();
88 * this command can be run only in the global zone.
90 if (getzoneid() != GLOBAL_ZONEID
) {
91 (void) fprintf(stderr
, "%s%s", progname
,
92 gettext(" : must be run in global zone\n"));
97 * this command works in Trusted Extensions only.
99 (void) fprintf(stderr
, "%s%s", progname
,
100 gettext(" : need to install Trusted Extensions\n"));
105 dargs
.rootdir
= NULL
;
106 dargs
.devnames
= NULL
;
107 dargs
.devinfo
= &devinfo
;
109 if (strcmp(progname
, "add_allocatable") == 0) {
110 dargs
.optflag
|= DA_ADD
;
111 } else if (strcmp(progname
, "remove_allocatable") == 0) {
112 dargs
.optflag
|= DA_REMOVE
;
114 usage(&dargs
, progname
);
119 if ((getpwuid_r(uid
, &pwd
, pwbuf
, sizeof (pwbuf
))) == NULL
) {
120 (void) fprintf(stderr
, "%s%s", progname
,
121 gettext(" : getpwuid_r failed: "));
122 (void) fprintf(stderr
, "%s\n", strerror(errno
));
126 if (chkauthattr(DEVICE_CONFIG_AUTH
, pwd
.pw_name
) != 1) {
127 (void) fprintf(stderr
, "%s%s%s", progname
,
128 gettext(" : user lacks authorization: \n"),
133 if (process_args(argc
, argv
, &dargs
, progname
) != 0) {
134 usage(&dargs
, progname
);
138 if (dargs
.optflag
& DA_ADD
) {
139 if (check_args(&dargs
) == NO_OVERRIDE
) {
140 (void) fprintf(stderr
, "%s%s%s%s", progname
,
141 gettext(" : entry exists for "),
142 dargs
.devinfo
->devname
, gettext("\n"));
143 usage(&dargs
, progname
);
148 if (dargs
.optflag
& DA_DEFATTRS
)
149 rc
= da_update_defattrs(&dargs
);
151 rc
= da_update_device(&dargs
);
153 if ((rc
!= 0) && (!(dargs
.optflag
& DA_SILENT
))) {
155 (void) fprintf(stderr
, "%s%s", progname
,
156 gettext(" : device name/type/list missing\n"));
157 else if (dargs
.optflag
& DA_ADD
)
158 (void) fprintf(stderr
, "%s%s", progname
,
159 gettext(" : error adding/updating device\n"));
160 else if (dargs
.optflag
& DA_REMOVE
)
161 (void) fprintf(stderr
, "%s%s", progname
,
162 gettext(" : error removing device\n"));
163 rc
= 2; /* exit code for 'Unknown system error' in man page */
170 process_args(int argc
, char **argv
, da_args
*dargs
, char *progname
)
173 int aflag
, cflag
, dflag
, fflag
, lflag
, nflag
, oflag
, tflag
;
177 devinfo
= dargs
->devinfo
;
178 aflag
= cflag
= dflag
= fflag
= lflag
= nflag
= oflag
= tflag
= 0;
179 devinfo
->devname
= devinfo
->devtype
= devinfo
->devauths
=
180 devinfo
->devexec
= devinfo
->devopts
= devinfo
->devlist
= NULL
;
181 devinfo
->instance
= 0;
183 while ((c
= getopt(argc
, argv
, "a:c:dfl:n:o:st:")) != EOF
) {
186 devinfo
->devauths
= optarg
;
190 devinfo
->devexec
= optarg
;
191 if (strlen(devinfo
->devexec
) == 0) {
192 if (!(dargs
->optflag
& DA_SILENT
))
193 (void) fprintf(stderr
, "%s%s", progname
,
194 gettext(" : device clean program"
195 " name not found\n"));
201 dargs
->optflag
|= DA_DEFATTRS
;
205 devinfo
->devlist
= optarg
;
206 if (strlen(devinfo
->devlist
) == 0) {
207 if (!(dargs
->optflag
& DA_SILENT
))
208 (void) fprintf(stderr
, "%s%s", progname
,
209 gettext(" : device file list"
216 dargs
->optflag
|= DA_FORCE
;
220 devinfo
->devname
= optarg
;
221 if (strlen(devinfo
->devname
) == 0) {
222 if (!(dargs
->optflag
& DA_SILENT
))
223 (void) fprintf(stderr
, "%s%s", progname
,
224 gettext(" : device name "
231 /* check for field delimiters in the option */
232 if (strpbrk(optarg
, ":;=") == NULL
) {
233 if (!(dargs
->optflag
& DA_SILENT
)) {
234 (void) fprintf(stderr
, "%s%s%s",
236 gettext(" : invalid "
239 (void) fprintf(stderr
, "%s",
244 devinfo
->devopts
= optarg
;
245 if (dargs
->optflag
& DA_ADD
) {
246 if (scan_label(devinfo
->devopts
, progname
) != 0)
252 dargs
->optflag
|= DA_SILENT
;
255 devinfo
->devtype
= optarg
;
256 if (strlen(devinfo
->devtype
) == 0) {
257 if (!(dargs
->optflag
& DA_SILENT
))
258 (void) fprintf(stderr
, "%s%s", progname
,
259 gettext(" : device type "
271 if (dargs
->optflag
& DA_ADD
) {
273 /* -d requires -t, but does not like -n */
274 if (nflag
|| tflag
== 0)
276 } else if (nflag
== 0 && tflag
== 0 && lflag
== 0) {
277 /* require at least -n or -t or -l to be specified */
278 if (!(dargs
->optflag
& DA_SILENT
))
279 (void) fprintf(stderr
, "%s%s", progname
,
280 gettext(" : required options missing\n"));
283 } else if (dargs
->optflag
& DA_REMOVE
) {
285 /* -d requires -t, but does not like -n */
286 if (nflag
|| tflag
== 0)
288 } else if (nflag
== 0 && tflag
== 0) {
289 /* require at least -n or -t to be specified */
290 if (!(dargs
->optflag
& DA_SILENT
))
291 (void) fprintf(stderr
, "%s%s", progname
,
292 gettext(" : required options missing\n"));
295 /* there's a bunch not accepted by remove_allocatable */
296 if (aflag
|| cflag
|| lflag
|| oflag
)
302 /* check for option specified more than once */
303 if (aflag
> 1 || cflag
> 1 || lflag
> 1 || fflag
> 1 ||
304 nflag
> 1 || tflag
> 1) {
305 if (!(dargs
->optflag
& DA_SILENT
))
306 (void) fprintf(stderr
, "%s%s", progname
,
307 gettext(" : multiple-defined options\n"));
315 verify_label(char *token
, char *progname
)
320 if ((strstr(token
, DAOPT_MINLABEL
) == NULL
) &&
321 (strstr(token
, DAOPT_MAXLABEL
) == NULL
)) {
322 /* no label specified */
325 if ((val
= strchr(token
, '=')) == NULL
)
329 * if non-default labels are specified, check if they are correct
331 if ((strcmp(val
, DA_DEFAULT_MIN
) != 0) &&
332 (strcmp(val
, DA_DEFAULT_MAX
) != 0)) {
333 m_label_t
*slabel
= NULL
;
336 /* get rid of double quotes if they exist */
339 if ((p
= strchr(str
, '"')) != NULL
)
341 if (str_to_label(str
, &slabel
, MAC_LABEL
, L_NO_CORRECTION
,
343 (void) fprintf(stderr
, "%s%s%s", progname
,
344 gettext(" : bad label input: "),
346 (void) fprintf(stderr
, "%s", gettext("\n"));
348 m_label_free(slabel
);
352 m_label_free(slabel
);
359 scan_label(char *devopts
, char *progname
)
362 char *lasts
, *optsarg
;
367 if ((optsarg
= strdup(devopts
)) == NULL
)
370 if ((tok
= strtok_r(optsarg
, KV_TOKEN_DELIMIT
, &lasts
)) == NULL
)
373 if (verify_label(tok
, progname
) != 0) {
378 while ((tok
= strtok_r(NULL
, KV_TOKEN_DELIMIT
, &lasts
)) != NULL
) {
379 if (verify_label(tok
, progname
) != 0) {
389 check_args(da_args
*dargs
)
392 char *kval
, *nopts
, *ntok
, *nstr
,
393 *defmin
, *defmax
, *defauths
, *defexec
;
396 devalloc_t
*da
= NULL
;
397 da_defs_t
*da_defs
= NULL
;
399 devinfo
= dargs
->devinfo
;
401 * check if we're updating an existing entry without -f
404 da
= getdanam(devinfo
->devname
);
406 if (da
&& !(dargs
->optflag
& DA_FORCE
)) {
408 return (NO_OVERRIDE
);
410 if ((devinfo
->devopts
== NULL
) ||
411 (strstr(devinfo
->devopts
, DAOPT_MINLABEL
) == NULL
) ||
412 (strstr(devinfo
->devopts
, DAOPT_MAXLABEL
) == NULL
) ||
413 (devinfo
->devauths
== NULL
) ||
414 (devinfo
->devexec
== NULL
)) {
415 /* fill in defaults as required */
416 defmin
= DA_DEFAULT_MIN
;
417 defmax
= DA_DEFAULT_MAX
;
418 defauths
= DEFAULT_DEV_ALLOC_AUTH
;
419 defexec
= DA_DEFAULT_CLEAN
;
421 if (da_defs
= getdadeftype(devinfo
->devtype
)) {
422 kva
= da_defs
->devopts
;
423 if ((kval
= kva_match(kva
, DAOPT_MINLABEL
)) != NULL
)
424 defmin
= strdup(kval
);
425 if ((kval
= kva_match(kva
, DAOPT_MAXLABEL
)) != NULL
)
426 defmax
= strdup(kval
);
427 if ((kval
= kva_match(kva
, DAOPT_AUTHS
)) != NULL
)
428 defauths
= strdup(kval
);
429 if ((kval
= kva_match(kva
, DAOPT_CSCRIPT
)) != NULL
)
430 defexec
= strdup(kval
);
431 freedadefent(da_defs
);
434 if (devinfo
->devauths
== NULL
)
435 devinfo
->devauths
= defauths
;
436 if (devinfo
->devexec
== NULL
)
437 devinfo
->devexec
= defexec
;
438 if (devinfo
->devopts
== NULL
) {
439 /* add default minlabel and maxlabel */
440 nlen
= strlen(DAOPT_MINLABEL
) + strlen(KV_ASSIGN
) +
441 strlen(defmin
) + strlen(KV_TOKEN_DELIMIT
) +
442 strlen(DAOPT_MAXLABEL
) + strlen(KV_ASSIGN
) +
443 strlen(defmax
) + 1; /* +1 for terminator */
444 if (nopts
= (char *)malloc(nlen
)) {
445 (void) snprintf(nopts
, nlen
, "%s%s%s%s%s%s%s",
446 DAOPT_MINLABEL
, KV_ASSIGN
, defmin
,
448 DAOPT_MAXLABEL
, KV_ASSIGN
, defmax
);
449 devinfo
->devopts
= nopts
;
452 if (strstr(devinfo
->devopts
, DAOPT_MINLABEL
) == NULL
) {
453 /* add default minlabel */
454 ntok
= DAOPT_MINLABEL
;
456 nlen
= strlen(devinfo
->devopts
) +
457 strlen(KV_TOKEN_DELIMIT
) +
458 strlen(ntok
) + strlen(KV_ASSIGN
) +
460 if (nopts
= (char *)malloc(nlen
)) {
461 (void) snprintf(nopts
, nlen
,
463 devinfo
->devopts
, KV_TOKEN_DELIMIT
,
464 ntok
, KV_ASSIGN
, nstr
);
465 devinfo
->devopts
= nopts
;
468 if (strstr(devinfo
->devopts
, DAOPT_MAXLABEL
) == NULL
) {
469 /* add default maxlabel */
470 ntok
= DAOPT_MAXLABEL
;
472 nlen
= strlen(devinfo
->devopts
) +
473 strlen(KV_TOKEN_DELIMIT
) +
474 strlen(ntok
) + strlen(KV_ASSIGN
) +
476 if (nopts
= (char *)malloc(nlen
)) {
477 (void) snprintf(nopts
, nlen
,
479 devinfo
->devopts
, KV_TOKEN_DELIMIT
,
480 ntok
, KV_ASSIGN
, nstr
);
481 devinfo
->devopts
= nopts
;
491 usage(da_args
*dargs
, char *progname
)
493 if (dargs
->optflag
& DA_SILENT
)
495 if (dargs
->optflag
& DA_ADD
)
496 (void) fprintf(stderr
, "%s%s%s", gettext("Usage: "), progname
,
497 gettext(" [-f][-s][-d] -n name -t type -l device-list"
498 "\n\t[-a authorization] [-c cleaning program] "
499 "[-o key=value]\n"));
500 else if (dargs
->optflag
& DA_REMOVE
)
501 (void) fprintf(stderr
, "%s%s%s", gettext("Usage: "), progname
,
502 gettext(" [-f][-s][-d] [-n name|-t type]\n"));
504 (void) fprintf(stderr
, gettext("Invalid usage\n"), progname
);