1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "conf-files.h"
26 #include "bus-internal.h"
27 #include "bus-message.h"
28 #include "bus-policy.h"
30 static void policy_item_free(PolicyItem
*i
) {
41 DEFINE_TRIVIAL_CLEANUP_FUNC(PolicyItem
*, policy_item_free
);
43 static void item_append(PolicyItem
*i
, PolicyItem
**list
) {
47 LIST_FIND_TAIL(items
, *list
, tail
);
48 LIST_INSERT_AFTER(items
, *list
, tail
, i
);
51 static int file_load(Policy
*p
, const char *path
) {
53 _cleanup_free_
char *c
= NULL
, *policy_user
= NULL
, *policy_group
= NULL
;
54 _cleanup_(policy_item_freep
) PolicyItem
*i
= NULL
;
55 void *xml_state
= NULL
;
67 STATE_POLICY_OTHER_ATTRIBUTE
,
69 STATE_ALLOW_DENY_INTERFACE
,
70 STATE_ALLOW_DENY_MEMBER
,
71 STATE_ALLOW_DENY_ERROR
,
72 STATE_ALLOW_DENY_PATH
,
73 STATE_ALLOW_DENY_MESSAGE_TYPE
,
74 STATE_ALLOW_DENY_NAME
,
75 STATE_ALLOW_DENY_OTHER_ATTRIBUTE
,
77 } state
= STATE_OUTSIDE
;
81 POLICY_CATEGORY_DEFAULT
,
82 POLICY_CATEGORY_MANDATORY
,
85 } policy_category
= POLICY_CATEGORY_NONE
;
91 r
= read_full_file(path
, &c
, NULL
);
98 log_error_errno(-r
, "Failed to load %s: %m", path
);
104 _cleanup_free_
char *name
= NULL
;
107 t
= xml_tokenize(&q
, &name
, &xml_state
, &line
);
109 log_error_errno(-t
, "XML parse failure in %s: %m", path
);
117 if (t
== XML_TAG_OPEN
) {
118 if (streq(name
, "busconfig"))
119 state
= STATE_BUSCONFIG
;
121 log_error("Unexpected tag %s at %s:%u.", name
, path
, line
);
125 } else if (t
== XML_END
)
127 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
128 log_error("Unexpected token (1) at %s:%u.", path
, line
);
134 case STATE_BUSCONFIG
:
136 if (t
== XML_TAG_OPEN
) {
137 if (streq(name
, "policy")) {
138 state
= STATE_POLICY
;
139 policy_category
= POLICY_CATEGORY_NONE
;
142 policy_user
= policy_group
= NULL
;
147 } else if (t
== XML_TAG_CLOSE_EMPTY
||
148 (t
== XML_TAG_CLOSE
&& streq(name
, "busconfig")))
149 state
= STATE_OUTSIDE
;
150 else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
151 log_error("Unexpected token (2) at %s:%u.", path
, line
);
159 if (t
== XML_ATTRIBUTE_NAME
) {
160 if (streq(name
, "context"))
161 state
= STATE_POLICY_CONTEXT
;
162 else if (streq(name
, "user"))
163 state
= STATE_POLICY_USER
;
164 else if (streq(name
, "group"))
165 state
= STATE_POLICY_GROUP
;
167 if (streq(name
, "at_console"))
168 log_debug("Attribute %s of <policy> tag unsupported at %s:%u, ignoring.", name
, path
, line
);
170 log_warning("Attribute %s of <policy> tag unknown at %s:%u, ignoring.", name
, path
, line
);
171 state
= STATE_POLICY_OTHER_ATTRIBUTE
;
173 } else if (t
== XML_TAG_CLOSE_EMPTY
||
174 (t
== XML_TAG_CLOSE
&& streq(name
, "policy")))
175 state
= STATE_BUSCONFIG
;
176 else if (t
== XML_TAG_OPEN
) {
179 if (streq(name
, "allow"))
180 it
= POLICY_ITEM_ALLOW
;
181 else if (streq(name
, "deny"))
182 it
= POLICY_ITEM_DENY
;
184 log_warning("Unknown tag %s in <policy> %s:%u.", name
, path
, line
);
189 i
= new0(PolicyItem
, 1);
194 state
= STATE_ALLOW_DENY
;
196 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
197 log_error("Unexpected token (3) at %s:%u.", path
, line
);
203 case STATE_POLICY_CONTEXT
:
205 if (t
== XML_ATTRIBUTE_VALUE
) {
206 if (streq(name
, "default")) {
207 policy_category
= POLICY_CATEGORY_DEFAULT
;
208 state
= STATE_POLICY
;
209 } else if (streq(name
, "mandatory")) {
210 policy_category
= POLICY_CATEGORY_MANDATORY
;
211 state
= STATE_POLICY
;
213 log_error("context= parameter %s unknown for <policy> at %s:%u.", name
, path
, line
);
217 log_error("Unexpected token (4) at %s:%u.", path
, line
);
223 case STATE_POLICY_USER
:
225 if (t
== XML_ATTRIBUTE_VALUE
) {
229 policy_category
= POLICY_CATEGORY_USER
;
230 state
= STATE_POLICY
;
232 log_error("Unexpected token (5) in %s:%u.", path
, line
);
238 case STATE_POLICY_GROUP
:
240 if (t
== XML_ATTRIBUTE_VALUE
) {
244 policy_category
= POLICY_CATEGORY_GROUP
;
245 state
= STATE_POLICY
;
247 log_error("Unexpected token (6) at %s:%u.", path
, line
);
253 case STATE_POLICY_OTHER_ATTRIBUTE
:
255 if (t
== XML_ATTRIBUTE_VALUE
)
256 state
= STATE_POLICY
;
258 log_error("Unexpected token (7) in %s:%u.", path
, line
);
264 case STATE_ALLOW_DENY
:
268 if (t
== XML_ATTRIBUTE_NAME
) {
271 if (startswith(name
, "send_"))
272 ic
= POLICY_ITEM_SEND
;
273 else if (startswith(name
, "receive_"))
274 ic
= POLICY_ITEM_RECV
;
275 else if (streq(name
, "own"))
276 ic
= POLICY_ITEM_OWN
;
277 else if (streq(name
, "own_prefix"))
278 ic
= POLICY_ITEM_OWN_PREFIX
;
279 else if (streq(name
, "user"))
280 ic
= POLICY_ITEM_USER
;
281 else if (streq(name
, "group"))
282 ic
= POLICY_ITEM_GROUP
;
283 else if (streq(name
, "eavesdrop")) {
284 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
285 i
->class = POLICY_ITEM_IGNORE
;
286 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
289 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
290 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
294 if (i
->class != _POLICY_ITEM_CLASS_UNSET
&& ic
!= i
->class) {
295 log_error("send_ and receive_ fields mixed on same tag at %s:%u.", path
, line
);
301 if (ic
== POLICY_ITEM_SEND
|| ic
== POLICY_ITEM_RECV
) {
304 u
= strchr(name
, '_');
309 if (streq(u
, "interface"))
310 state
= STATE_ALLOW_DENY_INTERFACE
;
311 else if (streq(u
, "member"))
312 state
= STATE_ALLOW_DENY_MEMBER
;
313 else if (streq(u
, "error"))
314 state
= STATE_ALLOW_DENY_ERROR
;
315 else if (streq(u
, "path"))
316 state
= STATE_ALLOW_DENY_PATH
;
317 else if (streq(u
, "type"))
318 state
= STATE_ALLOW_DENY_MESSAGE_TYPE
;
319 else if ((streq(u
, "destination") && ic
== POLICY_ITEM_SEND
) ||
320 (streq(u
, "sender") && ic
== POLICY_ITEM_RECV
))
321 state
= STATE_ALLOW_DENY_NAME
;
323 if (streq(u
, "requested_reply"))
324 log_debug("Unsupported attribute %s= at %s:%u, ignoring.", name
, path
, line
);
326 log_error("Unknown attribute %s= at %s:%u, ignoring.", name
, path
, line
);
327 state
= STATE_ALLOW_DENY_OTHER_ATTRIBUTE
;
331 state
= STATE_ALLOW_DENY_NAME
;
333 } else if (t
== XML_TAG_CLOSE_EMPTY
||
334 (t
== XML_TAG_CLOSE
&& streq(name
, i
->type
== POLICY_ITEM_ALLOW
? "allow" : "deny"))) {
336 if (i
->class == _POLICY_ITEM_CLASS_UNSET
) {
337 log_error("Policy not set at %s:%u.", path
, line
);
341 if (policy_category
== POLICY_CATEGORY_DEFAULT
)
342 item_append(i
, &p
->default_items
);
343 else if (policy_category
== POLICY_CATEGORY_MANDATORY
)
344 item_append(i
, &p
->mandatory_items
);
345 else if (policy_category
== POLICY_CATEGORY_USER
) {
346 const char *u
= policy_user
;
348 assert_cc(sizeof(uid_t
) == sizeof(uint32_t));
350 r
= hashmap_ensure_allocated(&p
->user_items
, NULL
);
355 log_error("User policy without name");
359 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
361 log_error_errno(-r
, "Failed to resolve user %s, ignoring policy: %m", u
);
366 first
= hashmap_get(p
->user_items
, UINT32_TO_PTR(i
->uid
));
367 item_append(i
, &first
);
370 r
= hashmap_replace(p
->user_items
, UINT32_TO_PTR(i
->uid
), first
);
372 LIST_REMOVE(items
, first
, i
);
377 } else if (policy_category
== POLICY_CATEGORY_GROUP
) {
378 const char *g
= policy_group
;
380 assert_cc(sizeof(gid_t
) == sizeof(uint32_t));
382 r
= hashmap_ensure_allocated(&p
->group_items
, NULL
);
387 log_error("Group policy without name");
391 r
= get_group_creds(&g
, &i
->gid
);
393 log_error_errno(-r
, "Failed to resolve group %s, ignoring policy: %m", g
);
398 first
= hashmap_get(p
->group_items
, UINT32_TO_PTR(i
->gid
));
399 item_append(i
, &first
);
402 r
= hashmap_replace(p
->group_items
, UINT32_TO_PTR(i
->gid
), first
);
404 LIST_REMOVE(items
, first
, i
);
410 state
= STATE_POLICY
;
413 } else if (t
!= XML_TEXT
|| !in_charset(name
, WHITESPACE
)) {
414 log_error("Unexpected token (8) at %s:%u.", path
, line
);
420 case STATE_ALLOW_DENY_INTERFACE
:
422 if (t
== XML_ATTRIBUTE_VALUE
) {
425 log_error("Duplicate interface at %s:%u.", path
, line
);
431 state
= STATE_ALLOW_DENY
;
433 log_error("Unexpected token (9) at %s:%u.", path
, line
);
439 case STATE_ALLOW_DENY_MEMBER
:
441 if (t
== XML_ATTRIBUTE_VALUE
) {
444 log_error("Duplicate member in %s:%u.", path
, line
);
450 state
= STATE_ALLOW_DENY
;
452 log_error("Unexpected token (10) in %s:%u.", path
, line
);
458 case STATE_ALLOW_DENY_ERROR
:
460 if (t
== XML_ATTRIBUTE_VALUE
) {
463 log_error("Duplicate error in %s:%u.", path
, line
);
469 state
= STATE_ALLOW_DENY
;
471 log_error("Unexpected token (11) in %s:%u.", path
, line
);
477 case STATE_ALLOW_DENY_PATH
:
479 if (t
== XML_ATTRIBUTE_VALUE
) {
482 log_error("Duplicate path in %s:%u.", path
, line
);
488 state
= STATE_ALLOW_DENY
;
490 log_error("Unexpected token (12) in %s:%u.", path
, line
);
496 case STATE_ALLOW_DENY_MESSAGE_TYPE
:
498 if (t
== XML_ATTRIBUTE_VALUE
) {
501 if (i
->message_type
!= 0) {
502 log_error("Duplicate message type in %s:%u.", path
, line
);
506 r
= bus_message_type_from_string(name
, &i
->message_type
);
508 log_error("Invalid message type in %s:%u.", path
, line
);
512 state
= STATE_ALLOW_DENY
;
514 log_error("Unexpected token (13) in %s:%u.", path
, line
);
520 case STATE_ALLOW_DENY_NAME
:
522 if (t
== XML_ATTRIBUTE_VALUE
) {
525 log_error("Duplicate name in %s:%u.", path
, line
);
530 case POLICY_ITEM_USER
:
531 if (!streq(name
, "*")) {
532 const char *u
= name
;
534 r
= get_user_creds(&u
, &i
->uid
, NULL
, NULL
, NULL
);
536 log_error_errno(-r
, "Failed to resolve user %s: %m", name
);
541 case POLICY_ITEM_GROUP
:
542 if (!streq(name
, "*")) {
543 const char *g
= name
;
545 r
= get_group_creds(&g
, &i
->gid
);
547 log_error_errno(-r
, "Failed to resolve group %s: %m", name
);
559 state
= STATE_ALLOW_DENY
;
561 log_error("Unexpected token (14) in %s:%u.", path
, line
);
567 case STATE_ALLOW_DENY_OTHER_ATTRIBUTE
:
569 if (t
== XML_ATTRIBUTE_VALUE
)
570 state
= STATE_ALLOW_DENY
;
572 log_error("Unexpected token (15) in %s:%u.", path
, line
);
580 if (t
== XML_TAG_OPEN
)
582 else if (t
== XML_TAG_CLOSE
|| t
== XML_TAG_CLOSE_EMPTY
) {
585 state
= STATE_BUSCONFIG
;
601 static const char *verdict_to_string(int v
) {
615 struct policy_check_filter
{
616 PolicyItemClass
class;
621 const char *interface
;
626 static int is_permissive(PolicyItem
*i
) {
630 return (i
->type
== POLICY_ITEM_ALLOW
) ? ALLOW
: DENY
;
633 static int check_policy_item(PolicyItem
*i
, const struct policy_check_filter
*filter
) {
639 case POLICY_ITEM_SEND
:
640 case POLICY_ITEM_RECV
:
642 if (i
->name
&& !streq_ptr(i
->name
, filter
->name
))
645 if ((i
->message_type
!= 0) && (i
->message_type
!= filter
->message_type
))
648 if (i
->path
&& !streq_ptr(i
->path
, filter
->path
))
651 if (i
->member
&& !streq_ptr(i
->member
, filter
->member
))
654 if (i
->interface
&& !streq_ptr(i
->interface
, filter
->interface
))
657 return is_permissive(i
);
659 case POLICY_ITEM_OWN
:
660 assert(filter
->name
);
662 if (streq(i
->name
, "*") || streq(i
->name
, filter
->name
))
663 return is_permissive(i
);
666 case POLICY_ITEM_OWN_PREFIX
:
667 assert(filter
->name
);
669 if (streq(i
->name
, "*") || service_name_startswith(filter
->name
, i
->name
))
670 return is_permissive(i
);
673 case POLICY_ITEM_USER
:
674 if (filter
->uid
!= (uid_t
) -1)
675 if ((streq_ptr(i
->name
, "*") || (i
->uid_valid
&& i
->uid
== filter
->uid
)))
676 return is_permissive(i
);
679 case POLICY_ITEM_GROUP
:
680 if (filter
->gid
!= (gid_t
) -1)
681 if ((streq_ptr(i
->name
, "*") || (i
->gid_valid
&& i
->gid
== filter
->gid
)))
682 return is_permissive(i
);
685 case POLICY_ITEM_IGNORE
:
693 static int check_policy_items(PolicyItem
*items
, const struct policy_check_filter
*filter
) {
700 /* Check all policies in a set - a broader one might be followed by a more specific one,
701 * and the order of rules in policy definitions matters */
702 LIST_FOREACH(items
, i
, items
) {
705 if (i
->class != filter
->class &&
706 !(i
->class == POLICY_ITEM_OWN_PREFIX
&& filter
->class == POLICY_ITEM_OWN
))
709 v
= check_policy_item(i
, filter
);
717 static int policy_check(Policy
*p
, const struct policy_check_filter
*filter
) {
725 assert(IN_SET(filter
->class, POLICY_ITEM_SEND
, POLICY_ITEM_RECV
, POLICY_ITEM_OWN
, POLICY_ITEM_USER
, POLICY_ITEM_GROUP
));
728 * The policy check is implemented by the following logic:
730 * 1. Check default items
731 * 2. Check group items
732 * 3. Check user items
733 * 4. Check mandatory items
735 * Later rules override earlier rules.
738 verdict
= check_policy_items(p
->default_items
, filter
);
740 if (filter
->gid
!= (gid_t
) -1) {
741 items
= hashmap_get(p
->group_items
, UINT32_TO_PTR(filter
->gid
));
743 v
= check_policy_items(items
, filter
);
749 if (filter
->uid
!= (uid_t
) -1) {
750 items
= hashmap_get(p
->user_items
, UINT32_TO_PTR(filter
->uid
));
752 v
= check_policy_items(items
, filter
);
758 v
= check_policy_items(p
->mandatory_items
, filter
);
765 bool policy_check_own(Policy
*p
, uid_t uid
, gid_t gid
, const char *name
) {
767 struct policy_check_filter filter
= {
768 .class = POLICY_ITEM_OWN
,
779 verdict
= policy_check(p
, &filter
);
781 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
782 "Ownership permission check for uid=" UID_FMT
" gid=" GID_FMT
" name=%s: %s",
783 uid
, gid
, strna(name
), strna(verdict_to_string(verdict
)));
785 return verdict
== ALLOW
;
788 bool policy_check_hello(Policy
*p
, uid_t uid
, gid_t gid
) {
790 struct policy_check_filter filter
= {
798 filter
.class = POLICY_ITEM_USER
;
799 verdict
= policy_check(p
, &filter
);
801 if (verdict
!= DENY
) {
804 filter
.class = POLICY_ITEM_GROUP
;
805 v
= policy_check(p
, &filter
);
810 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
811 "Hello permission check for uid=" UID_FMT
" gid=" GID_FMT
": %s",
812 uid
, gid
, strna(verdict_to_string(verdict
)));
814 return verdict
== ALLOW
;
817 bool policy_check_recv(Policy
*p
,
823 const char *interface
,
824 const char *member
) {
826 struct policy_check_filter filter
= {
827 .class = POLICY_ITEM_RECV
,
830 .message_type
= message_type
,
832 .interface
= interface
,
841 verdict
= policy_check(p
, &filter
);
843 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
844 "Recieve permission check for uid=" UID_FMT
" gid=" GID_FMT
" message=%s name=%s interface=%s path=%s member=%s: %s",
845 uid
, gid
, bus_message_type_to_string(message_type
), strna(name
), strna(path
), strna(interface
), strna(member
), strna(verdict_to_string(verdict
)));
847 return verdict
== ALLOW
;
850 bool policy_check_send(Policy
*p
,
856 const char *interface
,
857 const char *member
) {
859 struct policy_check_filter filter
= {
860 .class = POLICY_ITEM_SEND
,
863 .message_type
= message_type
,
865 .interface
= interface
,
874 verdict
= policy_check(p
, &filter
);
876 log_full(LOG_AUTH
| (verdict
!= ALLOW
? LOG_WARNING
: LOG_DEBUG
),
877 "Send permission check for uid=" UID_FMT
" gid=" GID_FMT
" message=%s name=%s interface=%s path=%s member=%s: %s",
878 uid
, gid
, bus_message_type_to_string(message_type
), strna(name
), strna(path
), strna(interface
), strna(member
), strna(verdict_to_string(verdict
)));
880 return verdict
== ALLOW
;
883 int policy_load(Policy
*p
, char **files
) {
889 STRV_FOREACH(i
, files
) {
891 r
= file_load(p
, *i
);
893 _cleanup_strv_free_
char **l
= NULL
;
896 r
= conf_files_list(&l
, ".conf", NULL
, *i
, NULL
);
898 log_error_errno(-r
, "Failed to get configuration file list: %m");
906 /* We ignore all errors but EISDIR, and just proceed. */
912 void policy_free(Policy
*p
) {
913 PolicyItem
*i
, *first
;
918 while ((i
= p
->default_items
)) {
919 LIST_REMOVE(items
, p
->default_items
, i
);
923 while ((i
= p
->mandatory_items
)) {
924 LIST_REMOVE(items
, p
->mandatory_items
, i
);
928 while ((first
= hashmap_steal_first(p
->user_items
))) {
930 while ((i
= first
)) {
931 LIST_REMOVE(items
, first
, i
);
936 while ((first
= hashmap_steal_first(p
->group_items
))) {
938 while ((i
= first
)) {
939 LIST_REMOVE(items
, first
, i
);
944 hashmap_free(p
->user_items
);
945 hashmap_free(p
->group_items
);
947 p
->user_items
= p
->group_items
= NULL
;
950 static void dump_items(PolicyItem
*items
, const char *prefix
) {
960 LIST_FOREACH(items
, i
, items
) {
962 printf("%sType: %s\n"
964 prefix
, policy_item_type_to_string(i
->type
),
965 prefix
, policy_item_class_to_string(i
->class));
968 printf("%sInterface: %s\n",
969 prefix
, i
->interface
);
972 printf("%sMember: %s\n",
976 printf("%sError: %s\n",
980 printf("%sPath: %s\n",
984 printf("%sName: %s\n",
987 if (i
->message_type
!= 0)
988 printf("%sMessage Type: %s\n",
989 prefix
, bus_message_type_to_string(i
->message_type
));
992 _cleanup_free_
char *user
;
994 user
= uid_to_name(i
->uid
);
996 printf("%sUser: %s (%d)\n",
997 prefix
, strna(user
), i
->uid
);
1001 _cleanup_free_
char *group
;
1003 group
= gid_to_name(i
->gid
);
1005 printf("%sGroup: %s (%d)\n",
1006 prefix
, strna(group
), i
->gid
);
1008 printf("%s-\n", prefix
);
1012 static void dump_hashmap_items(Hashmap
*h
) {
1017 HASHMAP_FOREACH_KEY(i
, k
, h
, j
) {
1018 printf("\t%s Item for %u:\n", draw_special_char(DRAW_ARROW
), PTR_TO_UINT(k
));
1019 dump_items(i
, "\t\t");
1023 void policy_dump(Policy
*p
) {
1025 printf("%s Default Items:\n", draw_special_char(DRAW_ARROW
));
1026 dump_items(p
->default_items
, "\t");
1028 printf("%s Group Items:\n", draw_special_char(DRAW_ARROW
));
1029 dump_hashmap_items(p
->group_items
);
1031 printf("%s User Items:\n", draw_special_char(DRAW_ARROW
));
1032 dump_hashmap_items(p
->user_items
);
1034 printf("%s Mandatory Items:\n", draw_special_char(DRAW_ARROW
));
1035 dump_items(p
->mandatory_items
, "\t");
1038 static const char* const policy_item_type_table
[_POLICY_ITEM_TYPE_MAX
] = {
1039 [_POLICY_ITEM_TYPE_UNSET
] = "unset",
1040 [POLICY_ITEM_ALLOW
] = "allow",
1041 [POLICY_ITEM_DENY
] = "deny",
1043 DEFINE_STRING_TABLE_LOOKUP(policy_item_type
, PolicyItemType
);
1045 static const char* const policy_item_class_table
[_POLICY_ITEM_CLASS_MAX
] = {
1046 [_POLICY_ITEM_CLASS_UNSET
] = "unset",
1047 [POLICY_ITEM_SEND
] = "send",
1048 [POLICY_ITEM_RECV
] = "recv",
1049 [POLICY_ITEM_OWN
] = "own",
1050 [POLICY_ITEM_OWN_PREFIX
] = "own-prefix",
1051 [POLICY_ITEM_USER
] = "user",
1052 [POLICY_ITEM_GROUP
] = "group",
1053 [POLICY_ITEM_IGNORE
] = "ignore",
1055 DEFINE_STRING_TABLE_LOOKUP(policy_item_class
, PolicyItemClass
);