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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * tnchkdb.c - Trusted network database checking utility
37 #include <netinet/in.h>
38 #include <nss_dbdefs.h>
40 static void usage(void);
41 static void check_tnrhtp(const char *);
42 static void check_tnrhdb(const char *);
43 static void check_tnzonecfg(const char *);
45 static boolean_t tnrhtp_bad
;
48 struct tsol_name_list
{
49 struct tsol_name_list
*next
;
54 struct tsol_addr_list
{
55 struct tsol_addr_list
*next
;
61 static struct tsol_name_list
*tp_list_head
;
62 static struct tsol_addr_list
*rh_list_head
;
63 static struct tsol_name_list
*zc_list_head
;
65 typedef struct mlp_info_list_s
{
66 struct mlp_info_list_s
*next
;
72 static mlp_info_list_t
*global_mlps
;
75 add_name(struct tsol_name_list
**head
, const char *name
, int linenum
)
78 struct tsol_name_list
*entry
;
80 entry
= malloc(sizeof (struct tsol_name_list
));
84 (void) fprintf(stderr
,
85 gettext("tnchkdb: allocating name list: %s\n"),
89 (void) strlcpy(entry
->name
, name
, sizeof (entry
->name
));
91 entry
->linenum
= linenum
;
95 static struct tsol_name_list
*
96 find_name(struct tsol_name_list
*head
, const char *name
)
98 struct tsol_name_list
*entry
;
100 for (entry
= head
; entry
!= NULL
; entry
= entry
->next
)
101 if (strcmp(entry
->name
, name
) == 0)
107 add_addr(struct tsol_addr_list
**head
, int prefix_len
, in6_addr_t addr
,
111 struct tsol_addr_list
*entry
;
113 entry
= malloc(sizeof (struct tsol_addr_list
));
117 (void) fprintf(stderr
,
118 gettext("tnchkdb: allocating addr list: %s\n"),
122 entry
->prefix_len
= prefix_len
;
125 entry
->linenum
= linenum
;
129 static struct tsol_addr_list
*
130 find_addr(struct tsol_addr_list
*head
, int prefix_len
, in6_addr_t addr
)
132 struct tsol_addr_list
*entry
;
134 for (entry
= head
; entry
!= NULL
; entry
= entry
->next
)
135 if (entry
->prefix_len
== prefix_len
&&
136 IN6_ARE_ADDR_EQUAL(&entry
->addr
, &addr
))
142 add_template(const char *name
, int linenum
)
144 add_name(&tp_list_head
, name
, linenum
);
147 static struct tsol_name_list
*
148 find_template(const char *name
)
150 return (find_name(tp_list_head
, name
));
154 add_host(int prefix_len
, in6_addr_t addr
, int linenum
)
156 add_addr(&rh_list_head
, prefix_len
, addr
, linenum
);
159 static struct tsol_addr_list
*
160 find_host(int prefix_len
, in6_addr_t addr
)
162 return (find_addr(rh_list_head
, prefix_len
, addr
));
166 add_zone(const char *name
, int linenum
)
168 add_name(&zc_list_head
, name
, linenum
);
171 static struct tsol_name_list
*
172 find_zone(const char *name
)
174 return (find_name(zc_list_head
, name
));
178 main(int argc
, char **argv
)
180 const char *tnrhdb_file
= TNRHDB_PATH
;
181 const char *tnrhtp_file
= TNRHTP_PATH
;
182 const char *tnzonecfg_file
= TNZONECFG_PATH
;
185 /* set the locale for only the messages system (all else is clean) */
186 (void) setlocale(LC_ALL
, "");
187 #ifndef TEXT_DOMAIN /* Should be defined by cc -D */
188 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
190 (void) textdomain(TEXT_DOMAIN
);
192 while ((chr
= getopt(argc
, argv
, "h:t:z:")) != EOF
) {
195 tnrhdb_file
= optarg
;
198 tnrhtp_file
= optarg
;
201 tnzonecfg_file
= optarg
;
208 check_tnrhtp(tnrhtp_file
);
209 check_tnrhdb(tnrhdb_file
);
210 check_tnzonecfg(tnzonecfg_file
);
218 (void) fprintf(stderr
, gettext(
219 "usage: tnchkdb [-h path] [-t path] [-z path]\n"));
224 print_error(int linenum
, int err
, const char *errstr
)
226 (void) fprintf(stderr
, gettext("line %1$d: %2$s: %.32s\n"), linenum
,
227 tsol_strerror(err
, errno
), errstr
);
231 cipso_representable(const bslabel_t
*lab
, int linenum
, const char *template,
234 const _blevel_impl_t
*blab
= (const _blevel_impl_t
*)lab
;
238 if (!bltype(lab
, SUN_SL_ID
)) {
239 (void) fprintf(stderr
, gettext("tnchkdb: "
240 "%1$s type %2$d is invalid for cipso labels: "
241 "line %3$d entry %4$s\n"), name
, GETBLTYPE(lab
), linenum
,
245 lclass
= LCLASS(blab
);
246 if (lclass
& 0xff00) {
247 (void) fprintf(stderr
, gettext("tnchkdb: "
248 "%1$s classification %2$x is invalid for cipso labels: "
249 "line %3$d entry %4$s\n"), name
, lclass
, linenum
,
253 c8
= blab
->compartments
.c8
;
255 if (c8
& 0x0000ffff) {
257 if (c8
& 0xffff0000) {
259 (void) fprintf(stderr
, gettext("tnchkdb: %1$s "
260 "compartments 241-256 must be zero for cipso labels: "
261 "line %2$d entry %3$s\n"), name
, linenum
, template);
267 check_tnrhtp(const char *file
)
269 tsol_tpent_t
*tpentp
;
275 char line
[2048], *cp
;
277 struct tsol_name_list
*tnl
;
278 char buf
[NSS_BUFLEN_TSOL_TP
];
279 uint32_t initial_doi
= 0;
280 boolean_t multiple_doi_found
= B_FALSE
;
281 boolean_t doi_zero_found
= B_FALSE
;
283 (void) printf(gettext("checking %s ...\n"), file
);
285 if ((fp
= fopen(file
, "r")) == NULL
) {
287 (void) fprintf(stderr
,
288 gettext("tnchkdb: failed to open %1$s: %2$s\n"), file
,
295 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
299 if ((cp
= strchr(line
, '\n')) != NULL
)
301 (void) str_to_tpstr(line
, strlen(line
), &tpstr
, buf
,
303 tpentp
= tpstr_to_ent(&tpstr
, &err
, &errstr
);
304 if (tpentp
== NULL
) {
305 if (err
== LTSNET_EMPTY
)
307 print_error(linenum
, err
, errstr
);
310 * Flag is set *only* for parsing errors, which result
311 * in omitting the entry from tsol_name_list.
317 switch (tpentp
->host_type
) {
322 if (initial_doi
== 0)
323 initial_doi
= tpentp
->tp_cipso_doi_unl
;
324 if (tpentp
->tp_cipso_doi_unl
!= initial_doi
)
325 multiple_doi_found
= B_TRUE
;
326 if (tpentp
->tp_cipso_doi_unl
== 0)
327 doi_zero_found
= B_TRUE
;
329 cipso_representable(&tpentp
->tp_def_label
, linenum
,
330 tpentp
->name
, TP_DEFLABEL
);
333 * check max_sl dominates min_sl
335 l1
= &tpentp
->tp_gw_sl_range
.lower_bound
;
336 l2
= &tpentp
->tp_gw_sl_range
.upper_bound
;
337 if (!bldominates(l2
, l1
)) {
338 (void) fprintf(stderr
,
339 gettext("tnchkdb: max_sl does not "
340 "dominate min_sl: line %1$d entry %2$s\n"),
341 linenum
, tpentp
->name
);
345 cipso_representable(l1
, linenum
, tpentp
->name
,
347 l1
= (blevel_t
*)&tpentp
->tp_gw_sl_set
[0];
348 l2
= (blevel_t
*)&tpentp
->tp_gw_sl_set
[NSLS_MAX
];
349 for (; l1
< l2
; l1
++) {
352 cipso_representable(l1
, linenum
, tpentp
->name
,
359 * check max_sl dominates min_sl
361 l1
= &tpentp
->tp_sl_range_cipso
.lower_bound
;
362 l2
= &tpentp
->tp_sl_range_cipso
.upper_bound
;
363 if (!bldominates(l2
, l1
)) {
364 (void) fprintf(stderr
,
365 gettext("tnchkdb: max_sl does not "
366 "dominate min_sl: line %1$d entry %2$s\n"),
367 linenum
, tpentp
->name
);
371 cipso_representable(l1
, linenum
, tpentp
->name
,
374 l1
= (blevel_t
*)&tpentp
->tp_sl_set_cipso
[0];
375 l2
= (blevel_t
*)&tpentp
->tp_sl_set_cipso
[NSLS_MAX
];
376 for (; l1
< l2
; l1
++) {
379 cipso_representable(l1
, linenum
, tpentp
->name
,
386 if (initial_doi
== 0)
387 initial_doi
= tpentp
->tp_cipso_doi_cipso
;
388 if (tpentp
->tp_cipso_doi_cipso
!= initial_doi
)
389 multiple_doi_found
= B_TRUE
;
390 if (tpentp
->tp_cipso_doi_cipso
== 0)
391 doi_zero_found
= B_TRUE
;
395 (void) fprintf(stderr
, gettext("tnchkdb: unknown host "
396 "type %1$d: line %2$d entry %3$s\n"),
397 tpentp
->host_type
, linenum
, tpentp
->name
);
402 * check if a duplicated entry
404 if ((tnl
= find_template(tpentp
->name
)) != NULL
) {
405 (void) fprintf(stderr
, gettext("tnchkdb: duplicated "
406 "entry: %1$s at lines %2$d and %3$d\n"),
407 tpentp
->name
, tnl
->linenum
, linenum
);
410 add_template(tpentp
->name
, linenum
);
412 tsol_freetpent(tpentp
);
414 if (multiple_doi_found
== B_TRUE
) {
415 (void) fprintf(stderr
,
416 gettext("tnchkdb: Warning: tnrhtp entries do not all "
417 "contain the same DOI value\n"));
419 if (doi_zero_found
== B_TRUE
) {
420 (void) fprintf(stderr
,
421 gettext("tnchkdb: Warning: DOI=0 found in some "
422 "tnrhtp entries\n"));
428 check_tnrhdb(const char *file
)
430 tsol_rhent_t
*rhentp
;
435 char line
[2048], *cp
;
438 struct tsol_addr_list
*tal
;
439 char buf
[NSS_BUFLEN_TSOL_RH
];
441 (void) printf(gettext("checking %s ...\n"), file
);
443 if ((fp
= fopen(file
, "r")) == NULL
) {
445 (void) fprintf(stderr
,
446 gettext("tnchkdb: failed to open %s: %s\n"), file
,
453 * check that all templates used in tnrhdb file are defined by tnrhtp
456 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
460 if ((cp
= strchr(line
, '\n')) != NULL
)
462 (void) str_to_rhstr(line
, strlen(line
), &rhstr
, buf
,
464 rhentp
= rhstr_to_ent(&rhstr
, &err
, &errstr
);
465 if (rhentp
== NULL
) {
466 if (err
== LTSNET_EMPTY
)
468 print_error(linenum
, err
, errstr
);
473 if (rhentp
->rh_address
.ta_family
== AF_INET
) {
474 IN6_INADDR_TO_V4MAPPED(&rhentp
->rh_address
.ta_addr_v4
,
477 addr
= rhentp
->rh_address
.ta_addr_v6
;
479 if ((tal
= find_host(rhentp
->rh_prefix
, addr
)) != NULL
) {
480 (void) fprintf(stderr
,
481 gettext("tnchkdb: duplicate entry: lines %1$d and "
482 "%2$d\n"), tal
->linenum
, linenum
);
485 add_host(rhentp
->rh_prefix
, addr
, linenum
);
488 if (!tnrhtp_bad
&& find_template(rhentp
->rh_template
) == NULL
) {
489 (void) fprintf(stderr
,
490 gettext("tnchkdb: unknown template name: %1$s at "
491 "line %2$d\n"), rhentp
->rh_template
, linenum
);
495 tsol_freerhent(rhentp
);
501 check_mlp_conflicts(tsol_mlp_t
*mlps
, boolean_t isglobal
, const char *name
,
504 tsol_mlp_t
*mlpptr
, *mlp2
;
505 mlp_info_list_t
*mil
;
507 for (mlpptr
= mlps
; !TSOL_MLP_END(mlpptr
); mlpptr
++) {
508 if (mlpptr
->mlp_port_upper
== 0)
509 mlpptr
->mlp_port_upper
= mlpptr
->mlp_port
;
511 /* First, validate against self for duplicates */
512 for (mlp2
= mlps
; mlp2
< mlpptr
; mlp2
++) {
513 if (mlp2
->mlp_ipp
== mlpptr
->mlp_ipp
&&
514 !(mlp2
->mlp_port_upper
< mlpptr
->mlp_port
||
515 mlp2
->mlp_port
> mlpptr
->mlp_port_upper
))
520 (void) fprintf(stderr
, gettext("tnchkdb: self-overlap "
521 "of %1$s MLP protocol %2$d port %3$d-%4$d with "
522 "%5$d-%6$d: zone %7$s line %8$d\n"),
523 gettext(isglobal
? "global" : "zone-specific"),
524 mlpptr
->mlp_ipp
, mlpptr
->mlp_port
,
525 mlpptr
->mlp_port_upper
, mlp2
->mlp_port
,
526 mlp2
->mlp_port_upper
, name
, linenum
);
531 /* Next, validate against list for duplicates */
532 for (mil
= global_mlps
; mil
!= NULL
; mil
= mil
->next
) {
533 if (strcmp(mil
->name
, name
) == 0)
535 if (mil
->mlp
.mlp_ipp
== mlpptr
->mlp_ipp
&&
536 !(mil
->mlp
.mlp_port_upper
<
539 mlpptr
->mlp_port_upper
))
544 (void) fprintf(stderr
, gettext("tnchkdb: "
545 "overlap of global MLP protocol %1$d port "
546 "%2$d-%3$d with zone %4$s %5$d-%6$d: zone "
547 "%7$s lines %8$d and %9$d\n"),
548 mlpptr
->mlp_ipp
, mlpptr
->mlp_port
,
549 mlpptr
->mlp_port_upper
, mil
->name
,
550 mil
->mlp
.mlp_port
, mil
->mlp
.mlp_port_upper
,
551 name
, mil
->linenum
, linenum
);
555 /* Now throw into list */
556 if ((mil
= malloc(sizeof (*mil
))) == NULL
) {
557 (void) fprintf(stderr
, gettext("tnchkdb: "
558 "malloc error: %s\n"), strerror(errno
));
561 (void) strlcpy(mil
->name
, name
, sizeof (mil
->name
));
562 mil
->linenum
= linenum
;
564 mil
->next
= global_mlps
;
571 check_tnzonecfg(const char *file
)
577 char line
[2048], *cp
;
579 boolean_t saw_global
;
580 struct tsol_name_list
*tnl
;
582 (void) printf(gettext("checking %s ...\n"), file
);
584 if ((fp
= fopen(file
, "r")) == NULL
) {
586 (void) fprintf(stderr
,
587 gettext("tnchkdb: failed to open %s: %s\n"), file
,
593 saw_global
= B_FALSE
;
595 while (fgets(line
, sizeof (line
), fp
) != NULL
) {
596 if ((cp
= strchr(line
, '\n')) != NULL
)
600 if ((zc
= tsol_sgetzcent(line
, &err
, &errstr
)) == NULL
) {
601 if (err
== LTSNET_EMPTY
)
603 print_error(linenum
, err
, errstr
);
608 cipso_representable(&zc
->zc_label
, linenum
, zc
->zc_name
,
611 if (strcmp(zc
->zc_name
, "global") == 0)
614 if ((tnl
= find_zone(zc
->zc_name
)) != NULL
) {
615 (void) fprintf(stderr
,
616 gettext("tnchkdb: duplicate zones: %1$s at lines "
617 "%2$d and %3$d\n"), zc
->zc_name
, tnl
->linenum
,
621 add_zone(zc
->zc_name
, linenum
);
624 if (zc
->zc_private_mlp
!= NULL
)
625 check_mlp_conflicts(zc
->zc_private_mlp
, B_FALSE
,
626 zc
->zc_name
, linenum
);
627 if (zc
->zc_shared_mlp
!= NULL
)
628 check_mlp_conflicts(zc
->zc_shared_mlp
, B_TRUE
,
629 zc
->zc_name
, linenum
);
636 (void) fprintf(stderr
, gettext("tnchkdb: missing required "
637 "entry for global zone in %s\n"), file
);