オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Diff of /trunk/1.8.x/ccs-patch/security/ccsecurity/network.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 473 by kumaneko, Thu Sep 20 12:18:18 2007 UTC revision 808 by kumaneko, Mon Dec 17 04:06:21 2007 UTC
# Line 5  Line 5 
5   *   *
6   * Copyright (C) 2005-2007  NTT DATA CORPORATION   * Copyright (C) 2005-2007  NTT DATA CORPORATION
7   *   *
8   * Version: 1.5.0-rc   2007/09/20   * Version: 1.5.3-pre   2007/12/17
9   *   *
10   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
11   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 20  Line 20 
20    
21  /*************************  VARIABLES  *************************/  /*************************  VARIABLES  *************************/
22    
23  extern struct semaphore domain_acl_lock;  extern struct mutex domain_acl_lock;
24    
25  /*************************  AUDIT FUNCTIONS  *************************/  /*************************  AUDIT FUNCTIONS  *************************/
26    
27  static int AuditNetworkLog(const int is_ipv6, const char *operation, const u32 *address, const u16 port, const int is_granted)  static int AuditNetworkLog(const bool is_ipv6, const char *operation, const u32 *address, const u16 port, const bool is_granted)
28  {  {
29          char *buf;          char *buf;
30          int len = 256;          int len = 256;
# Line 32  static int AuditNetworkLog(const int is_ Line 32  static int AuditNetworkLog(const int is_
32          if ((buf = InitAuditLog(&len)) == NULL) return -ENOMEM;          if ((buf = InitAuditLog(&len)) == NULL) return -ENOMEM;
33          snprintf(buf + strlen(buf), len - strlen(buf) - 1, KEYWORD_ALLOW_NETWORK "%s ", operation);          snprintf(buf + strlen(buf), len - strlen(buf) - 1, KEYWORD_ALLOW_NETWORK "%s ", operation);
34          if (is_ipv6) {          if (is_ipv6) {
35                  print_ipv6(buf + strlen(buf), len - strlen(buf), (const u16 *) address);                  print_ipv6(buf + strlen(buf), len - strlen(buf), (const struct in6_addr *) address);
36          } else {          } else {
37                  u32 ip = *address;                  u32 ip = *address;
38                  snprintf(buf + strlen(buf), len - strlen(buf) - 1, "%u.%u.%u.%u", NIPQUAD(ip));                  snprintf(buf + strlen(buf), len - strlen(buf) - 1, "%u.%u.%u.%u", NIPQUAD(ip));
# Line 41  static int AuditNetworkLog(const int is_ Line 41  static int AuditNetworkLog(const int is_
41          return WriteAuditLog(buf, is_granted);          return WriteAuditLog(buf, is_granted);
42  }  }
43    
44    /*************************  UTILITY FUNCTIONS  *************************/
45    
46    /* Keep the given IPv6 address on the RAM. The RAM is shared, so NEVER try to modify or kfree() the returned address. */
47    static const struct in6_addr *SaveIPv6Address(const struct in6_addr *addr)
48    {
49            static const int block_size = 16;
50            struct addr_list {
51                    struct in6_addr addr[block_size];
52                    struct list1_head list;
53                    u32 in_use_count;
54            };
55            static LIST1_HEAD(address_list);
56            struct addr_list *ptr;
57            static DEFINE_MUTEX(lock);
58            int i = block_size;
59            if (!addr) return NULL;
60            mutex_lock(&lock);
61            list1_for_each_entry(ptr, &address_list, list) {
62                    for (i = 0; i < ptr->in_use_count; i++) {
63                            if (memcmp(&ptr->addr[i], addr, sizeof(*addr)) == 0) goto ok;
64                    }
65                    if (i < block_size) break;
66            }
67            if (i == block_size) {
68                    ptr = alloc_element(sizeof(*ptr));
69                    if (!ptr) goto ok;
70                    list1_add_tail_mb(&ptr->list, &address_list);
71                    i = 0;
72            }
73            ptr->addr[ptr->in_use_count++] = *addr;
74    ok:
75            mutex_unlock(&lock);
76            return ptr ? &ptr->addr[i] : NULL;
77    }
78    
79  /*************************  ADDRESS GROUP HANDLER  *************************/  /*************************  ADDRESS GROUP HANDLER  *************************/
80    
81  static struct address_group_entry *group_list = NULL;  static LIST1_HEAD(address_group_list);
82    
83  static int AddAddressGroupEntry(const char *group_name, const u8 is_ipv6, const u16 *min_address, const u16 *max_address, const int is_delete)  static int AddAddressGroupEntry(const char *group_name, const bool is_ipv6, const u16 *min_address, const u16 *max_address, const bool is_delete)
84  {  {
85          static DECLARE_MUTEX(lock);          static DEFINE_MUTEX(lock);
86          struct address_group_entry *new_group, *group;          struct address_group_entry *new_group, *group;
87          struct address_group_member *new_member, *member;          struct address_group_member *new_member, *member;
88          const struct path_info *saved_group_name;          const struct path_info *saved_group_name;
89            const struct in6_addr *saved_min_address = NULL, *saved_max_address = NULL;
90          int error = -ENOMEM;          int error = -ENOMEM;
91            bool found = 0;
92          if (!IsCorrectPath(group_name, 0, 0, 0, __FUNCTION__) || !group_name[0]) return -EINVAL;          if (!IsCorrectPath(group_name, 0, 0, 0, __FUNCTION__) || !group_name[0]) return -EINVAL;
93          if ((saved_group_name = SaveName(group_name)) == NULL) return -ENOMEM;          if ((saved_group_name = SaveName(group_name)) == NULL) return -ENOMEM;
94          down(&lock);          if (is_ipv6) {
95          for (group = group_list; group; group = group->next) {                  if ((saved_min_address = SaveIPv6Address((struct in6_addr *) min_address)) == NULL
96                        || (saved_max_address = SaveIPv6Address((struct in6_addr *) max_address)) == NULL) return -ENOMEM;
97            }
98            mutex_lock(&lock);
99            list1_for_each_entry(group, &address_group_list, list) {
100                  if (saved_group_name != group->group_name) continue;                  if (saved_group_name != group->group_name) continue;
101                  for (member = group->first_member; member; member = member->next) {                  list1_for_each_entry(member, &group->address_group_member_list, list) {
102                          if (member->is_ipv6 != is_ipv6) continue;                          if (member->is_ipv6 != is_ipv6) continue;
103                          if (is_ipv6) {                          if (is_ipv6) {
104                                  if (memcmp(member->min.ipv6, min_address, 16) || memcmp(member->max.ipv6, max_address, 16)) continue;                                  if (member->min.ipv6 != saved_min_address || member->max.ipv6 != saved_max_address) continue;
105                          } else {                          } else {
106                                  if (member->min.ipv4 != * (u32 *) min_address || member->max.ipv4 != * (u32 *) max_address) continue;                                  if (member->min.ipv4 != * (u32 *) min_address || member->max.ipv4 != * (u32 *) max_address) continue;
107                          }                          }
# Line 68  static int AddAddressGroupEntry(const ch Line 109  static int AddAddressGroupEntry(const ch
109                          error = 0;                          error = 0;
110                          goto out;                          goto out;
111                  }                  }
112                    found = 1;
113                  break;                  break;
114          }          }
115          if (is_delete) {          if (is_delete) {
116                  error = -ENOENT;                  error = -ENOENT;
117                  goto out;                  goto out;
118          }          }
119          if (!group) {          if (!found) {
120                  if ((new_group = alloc_element(sizeof(*new_group))) == NULL) goto out;                  if ((new_group = alloc_element(sizeof(*new_group))) == NULL) goto out;
121                    INIT_LIST1_HEAD(&new_group->address_group_member_list);
122                  new_group->group_name = saved_group_name;                  new_group->group_name = saved_group_name;
123                  mb(); /* Instead of using spinlock. */                  list1_add_tail_mb(&new_group->list, &address_group_list);
                 if ((group = group_list) != NULL) {  
                         while (group->next) group = group->next; group->next = new_group;  
                 } else {  
                         group_list= new_group;  
                 }  
124                  group = new_group;                  group = new_group;
125          }          }
126          if ((new_member = alloc_element(sizeof(*new_member))) == NULL) goto out;          if ((new_member = alloc_element(sizeof(*new_member))) == NULL) goto out;
127          new_member->is_ipv6 = is_ipv6;          new_member->is_ipv6 = is_ipv6;
128          if (is_ipv6) {          if (is_ipv6) {
129                  memmove(new_member->min.ipv6, min_address, 16);                  new_member->min.ipv6 = saved_min_address;
130                  memmove(new_member->max.ipv6, max_address, 16);                  new_member->max.ipv6 = saved_max_address;
131          } else {          } else {
132                  new_member->min.ipv4 = * (u32 *) min_address;                  new_member->min.ipv4 = * (u32 *) min_address;
133                  new_member->max.ipv4 = * (u32 *) max_address;                  new_member->max.ipv4 = * (u32 *) max_address;
134          }          }
135          mb(); /* Instead of using spinlock. */          list1_add_tail_mb(&new_member->list, &group->address_group_member_list);
         if ((member = group->first_member) != NULL) {  
                 while (member->next) member = member->next; member->next = new_member;  
         } else {  
                 group->first_member = new_member;  
         }  
136          error = 0;          error = 0;
137   out:   out:
138          up(&lock);          mutex_unlock(&lock);
139          return error;          return error;
140  }  }
141    
142  int AddAddressGroupPolicy(char *data, const int is_delete)  int AddAddressGroupPolicy(char *data, const bool is_delete)
143  {  {
144          int count, is_ipv6;          int count, is_ipv6;
145          u16 min_address[8], max_address[8];          u16 min_address[8], max_address[8];
# Line 114  int AddAddressGroupPolicy(char *data, co Line 147  int AddAddressGroupPolicy(char *data, co
147          if (!cp) return -EINVAL;          if (!cp) return -EINVAL;
148          *cp++ = '\0';          *cp++ = '\0';
149          if ((count = sscanf(cp, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",          if ((count = sscanf(cp, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
150                                                  &min_address[0], &min_address[1], &min_address[2], &min_address[3],                              &min_address[0], &min_address[1], &min_address[2], &min_address[3],
151                                                  &min_address[4], &min_address[5], &min_address[6], &min_address[7],                              &min_address[4], &min_address[5], &min_address[6], &min_address[7],
152                                                  &max_address[0], &max_address[1], &max_address[2], &max_address[3],                              &max_address[0], &max_address[1], &max_address[2], &max_address[3],
153                                                  &max_address[4], &max_address[5], &max_address[6], &max_address[7])) == 8 || count == 16) {                              &max_address[4], &max_address[5], &max_address[6], &max_address[7])) == 8 || count == 16) {
154                  int i;                  int i;
155                  for (i = 0; i < 8; i++) {                  for (i = 0; i < 8; i++) {
156                          min_address[i] = htons(min_address[i]);                          min_address[i] = htons(min_address[i]);
# Line 126  int AddAddressGroupPolicy(char *data, co Line 159  int AddAddressGroupPolicy(char *data, co
159                  if (count == 8) memmove(max_address, min_address, sizeof(min_address));                  if (count == 8) memmove(max_address, min_address, sizeof(min_address));
160                  is_ipv6 = 1;                  is_ipv6 = 1;
161          } else if ((count = sscanf(cp, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",          } else if ((count = sscanf(cp, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
162                                                             &min_address[0], &min_address[1], &min_address[2], &min_address[3],                                     &min_address[0], &min_address[1], &min_address[2], &min_address[3],
163                                                             &max_address[0], &max_address[1], &max_address[2], &max_address[3])) == 4 || count == 8) {                                     &max_address[0], &max_address[1], &max_address[2], &max_address[3])) == 4 || count == 8) {
164                  u32 ip = ((((u8) min_address[0]) << 24) + (((u8) min_address[1]) << 16) + (((u8) min_address[2]) << 8) + (u8) min_address[3]);                  u32 ip = ((((u8) min_address[0]) << 24) + (((u8) min_address[1]) << 16) + (((u8) min_address[2]) << 8) + (u8) min_address[3]);
165                  * (u32 *) min_address = ip;                  * (u32 *) min_address = ip;
166                  if (count == 8) ip = ((((u8) max_address[0]) << 24) + (((u8) max_address[1]) << 16) + (((u8) max_address[2]) << 8) + (u8) max_address[3]);                  if (count == 8) ip = ((((u8) max_address[0]) << 24) + (((u8) max_address[1]) << 16) + (((u8) max_address[2]) << 8) + (u8) max_address[3]);
# Line 144  static struct address_group_entry *FindO Line 177  static struct address_group_entry *FindO
177          int i;          int i;
178          struct address_group_entry *group;          struct address_group_entry *group;
179          for (i = 0; i <= 1; i++) {          for (i = 0; i <= 1; i++) {
180                  for (group = group_list; group; group = group->next) {                  list1_for_each_entry(group, &address_group_list, list) {
181                          if (strcmp(group_name, group->group_name->name) == 0) return group;                          if (strcmp(group_name, group->group_name->name) == 0) return group;
182                  }                  }
183                  if (i == 0) {                  if (i == 0) {
# Line 156  static struct address_group_entry *FindO Line 189  static struct address_group_entry *FindO
189          return NULL;          return NULL;
190  }  }
191    
192  static int AddressMatchesToGroup(const u8 is_ipv6, const u32 *address, const struct address_group_entry *group)  static int AddressMatchesToGroup(const bool is_ipv6, const u32 *address, const struct address_group_entry *group)
193  {  {
194          struct address_group_member *member;          struct address_group_member *member;
195          const u32 ip = ntohl(*address);          const u32 ip = ntohl(*address);
196          for (member = group->first_member; member; member = member->next) {          list1_for_each_entry(member, &group->address_group_member_list, list) {
197                  if (member->is_deleted) continue;                  if (member->is_deleted) continue;
198                  if (member->is_ipv6) {                  if (member->is_ipv6) {
199                          if (is_ipv6 && memcmp(member->min.ipv6, address, 16) <= 0 && memcmp(address, member->max.ipv6, 16) <= 0) return 1;                          if (is_ipv6 && memcmp(member->min.ipv6, address, 16) <= 0 && memcmp(address, member->max.ipv6, 16) <= 0) return 1;
# Line 173  static int AddressMatchesToGroup(const u Line 206  static int AddressMatchesToGroup(const u
206    
207  int ReadAddressGroupPolicy(struct io_buffer *head)  int ReadAddressGroupPolicy(struct io_buffer *head)
208  {  {
209          struct address_group_entry *group = head->read_var1;          struct list1_head *gpos;
210          struct address_group_member *member = head->read_var2;          struct list1_head *mpos;
211          if (!group) group = group_list;          list1_for_each_cookie(gpos, head->read_var1, &address_group_list) {
212          while (group) {                  struct address_group_entry *group;
213                  head->read_var1 = group;                  group = list1_entry(gpos, struct address_group_entry, list);
214                  if (!member) member = group->first_member;                  list1_for_each_cookie(mpos, head->read_var2, &group->address_group_member_list) {
215                  while (member) {                          char buf[128];
216                          head->read_var2 = member;                          struct address_group_member *member;
217                          if (!member->is_deleted) {                          member = list1_entry(mpos, struct address_group_member, list);
218                                  char buf[128];                          if (member->is_deleted) continue;
219                                  if (member->is_ipv6) {                          if (member->is_ipv6) {
220                                          const u16 *min_address = member->min.ipv6, *max_address = member->max.ipv6;                                  const struct in6_addr *min_address = member->min.ipv6, *max_address = member->max.ipv6;
221                                          print_ipv6(buf, sizeof(buf), min_address);                                  print_ipv6(buf, sizeof(buf), min_address);
222                                          if (memcmp(min_address, max_address, 16)) {                                  if (min_address != max_address) {
223                                                  char *cp = strchr(buf, '\0');                                          char *cp = strchr(buf, '\0');
224                                                  *cp++ = '-';                                          *cp++ = '-';
225                                                  print_ipv6(cp, sizeof(buf) - strlen(buf), max_address);                                          print_ipv6(cp, sizeof(buf) - strlen(buf), max_address);
226                                          }                                  }
227                                  } else {                          } else {
228                                          const u32 min_address = member->min.ipv4, max_address = member->max.ipv4;                                  const u32 min_address = member->min.ipv4, max_address = member->max.ipv4;
229                                          memset(buf, 0, sizeof(buf));                                  memset(buf, 0, sizeof(buf));
230                                          snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(min_address));                                  snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(min_address));
231                                          if (min_address != max_address) {                                  if (min_address != max_address) {
232                                                  const int len = strlen(buf);                                          const int len = strlen(buf);
233                                                  snprintf(buf + len, sizeof(buf) - 1 - len, "-%u.%u.%u.%u", HIPQUAD(max_address));                                          snprintf(buf + len, sizeof(buf) - 1 - len, "-%u.%u.%u.%u", HIPQUAD(max_address));
                                         }  
234                                  }                                  }
                                 if (io_printf(head, KEYWORD_ADDRESS_GROUP "%s %s\n", group->group_name->name, buf)) break;  
235                          }                          }
236                          member = member->next;                          if (io_printf(head, KEYWORD_ADDRESS_GROUP "%s %s\n", group->group_name->name, buf)) return -ENOMEM;
237                  }                  }
                 if (member) break;  
                 head->read_var2 = NULL;  
                 group = group->next;  
238          }          }
239          return group ? -ENOMEM : 0;          return 0;
240  }  }
241    
242  /*************************  NETWORK NETWORK ACL HANDLER  *************************/  /*************************  NETWORK NETWORK ACL HANDLER  *************************/
243    
244  char *print_ipv6(char *buffer, const int buffer_len, const u16 *ip)  #if !defined(NIP6)
245    #define NIP6(addr) \
246            ntohs((addr).s6_addr16[0]), \
247            ntohs((addr).s6_addr16[1]), \
248            ntohs((addr).s6_addr16[2]), \
249            ntohs((addr).s6_addr16[3]), \
250            ntohs((addr).s6_addr16[4]), \
251            ntohs((addr).s6_addr16[5]), \
252            ntohs((addr).s6_addr16[6]), \
253            ntohs((addr).s6_addr16[7])
254    #endif
255    
256    char *print_ipv6(char *buffer, const int buffer_len, const struct in6_addr *ip)
257  {  {
258          memset(buffer, 0, buffer_len);          memset(buffer, 0, buffer_len);
259          snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(ip[0]), ntohs(ip[1]), ntohs(ip[2]), ntohs(ip[3]), ntohs(ip[4]), ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7]));          snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));
260          return buffer;          return buffer;
261  }  }
262    
# Line 252  const char *network2keyword(const unsign Line 292  const char *network2keyword(const unsign
292          return keyword;          return keyword;
293  }  }
294    
295  static int AddNetworkEntry(const u8 operation, const u8 record_type, const struct address_group_entry *group, const u32 *min_address, const u32 *max_address, const u16 min_port, const u16 max_port, struct domain_info *domain, const u8 is_add, const struct condition_list *condition)  static int AddNetworkEntry(const u8 operation, const u8 record_type, const struct address_group_entry *group, const u32 *min_address, const u32 *max_address, const u16 min_port, const u16 max_port, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)
296  {  {
297          struct acl_info *ptr;          struct acl_info *ptr;
298            struct ip_network_acl_record *acl;
299          int error = -ENOMEM;          int error = -ENOMEM;
300          const u32 min_ip = ntohl(*min_address), max_ip = ntohl(*max_address); /* using host byte order to allow u32 comparison than memcmp().*/          const u32 min_ip = ntohl(*min_address), max_ip = ntohl(*max_address); /* using host byte order to allow u32 comparison than memcmp().*/
301            const struct in6_addr *saved_min_address = NULL, *saved_max_address = NULL;
302          if (!domain) return -EINVAL;          if (!domain) return -EINVAL;
303          down(&domain_acl_lock);          if (record_type == IP_RECORD_TYPE_IPv6) {
304          if (is_add) {                  if ((saved_min_address = SaveIPv6Address((struct in6_addr *) min_address)) == NULL
305                  if ((ptr = domain->first_acl_ptr) == NULL) goto first_entry;                      || (saved_max_address = SaveIPv6Address((struct in6_addr *) max_address)) == NULL) return -ENOMEM;
306                  while (1) {          }
307                          struct ip_network_acl_record *new_ptr = (struct ip_network_acl_record *) ptr;          mutex_lock(&domain_acl_lock);
308                          if (ptr->type == TYPE_IP_NETWORK_ACL && new_ptr->operation_type == operation && new_ptr->record_type == record_type && ptr->cond == condition && new_ptr->min_port == min_port && max_port == new_ptr->max_port) {          if (!is_delete) {
309                    list1_for_each_entry(ptr, &domain->acl_info_list, list) {
310                            acl = container_of(ptr, struct ip_network_acl_record, head);
311                            if (ptr->type == TYPE_IP_NETWORK_ACL && acl->operation_type == operation && acl->record_type == record_type && ptr->cond == condition && acl->min_port == min_port && max_port == acl->max_port) {
312                                  if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                                  if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
313                                          if (new_ptr->u.group == group) {                                          if (acl->u.group == group) {
314                                                  ptr->is_deleted = 0;                                                  ptr->is_deleted = 0;
315                                                  /* Found. Nothing to do. */                                                  /* Found. Nothing to do. */
316                                                  error = 0;                                                  error = 0;
317                                                  break;                                                  goto out;
318                                          }                                          }
319                                  } else if (record_type == IP_RECORD_TYPE_IPv4) {                                  } else if (record_type == IP_RECORD_TYPE_IPv4) {
320                                          if (new_ptr->u.ipv4.min == min_ip && max_ip == new_ptr->u.ipv4.max) {                                          if (acl->u.ipv4.min == min_ip && max_ip == acl->u.ipv4.max) {
321                                                  ptr->is_deleted = 0;                                                  ptr->is_deleted = 0;
322                                                  /* Found. Nothing to do. */                                                  /* Found. Nothing to do. */
323                                                  error = 0;                                                  error = 0;
324                                                  break;                                                  goto out;
325                                          }                                          }
326                                  } else if (record_type == IP_RECORD_TYPE_IPv6) {                                  } else if (record_type == IP_RECORD_TYPE_IPv6) {
327                                          if (memcmp(new_ptr->u.ipv6.min, min_address, 16) == 0 && memcmp(max_address, new_ptr->u.ipv6.max, 16) == 0) {                                          if (acl->u.ipv6.min == saved_min_address && saved_max_address == acl->u.ipv6.max) {
328                                                  ptr->is_deleted = 0;                                                  ptr->is_deleted = 0;
329                                                  /* Found. Nothing to do. */                                                  /* Found. Nothing to do. */
330                                                  error = 0;                                                  error = 0;
331                                                  break;                                                  goto out;
332                                          }                                          }
333                                  }                                  }
334                          }                          }
                         if (ptr->next) {  
                                 ptr = ptr->next;  
                                 continue;  
                         }  
                 first_entry: ;  
                         if (is_add == 1 && TooManyDomainACL(domain)) break;  
                         /* Not found. Append it to the tail. */  
                         if ((new_ptr = alloc_element(sizeof(*new_ptr))) == NULL) break;  
                         new_ptr->head.type = TYPE_IP_NETWORK_ACL;  
                         new_ptr->operation_type = operation;  
                         new_ptr->record_type = record_type;  
                         new_ptr->head.cond = condition;  
                         if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {  
                                 new_ptr->u.group = group;  
                         } else if (record_type == IP_RECORD_TYPE_IPv4) {  
                                 new_ptr->u.ipv4.min = min_ip;  
                                 new_ptr->u.ipv4.max = max_ip;  
                         } else {  
                                 memmove(new_ptr->u.ipv6.min, min_address, 16);  
                                 memmove(new_ptr->u.ipv6.max, max_address, 16);  
                         }  
                         new_ptr->min_port = min_port;  
                         new_ptr->max_port = max_port;  
                         error = AddDomainACL(ptr, domain, (struct acl_info *) new_ptr);  
                         break;  
335                  }                  }
336                    /* Not found. Append it to the tail. */
337                    if ((acl = alloc_element(sizeof(*acl))) == NULL) goto out;
338                    acl->head.type = TYPE_IP_NETWORK_ACL;
339                    acl->operation_type = operation;
340                    acl->record_type = record_type;
341                    acl->head.cond = condition;
342                    if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
343                            acl->u.group = group;
344                    } else if (record_type == IP_RECORD_TYPE_IPv4) {
345                            acl->u.ipv4.min = min_ip;
346                            acl->u.ipv4.max = max_ip;
347                    } else {
348                            acl->u.ipv6.min = saved_min_address;
349                            acl->u.ipv6.max = saved_max_address;
350                    }
351                    acl->min_port = min_port;
352                    acl->max_port = max_port;
353                    error = AddDomainACL(domain, &acl->head);
354          } else {          } else {
355                  error = -ENOENT;                  error = -ENOENT;
356                  for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) {                  list1_for_each_entry(ptr, &domain->acl_info_list, list) {
357                          struct ip_network_acl_record *ptr2 = (struct ip_network_acl_record *) ptr;                          acl = container_of(ptr, struct ip_network_acl_record, head);
358                          if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || ptr2->operation_type != operation || ptr2->record_type != record_type || ptr->cond != condition || ptr2->min_port != min_port || ptr2->max_port != max_port) continue;                          if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || acl->operation_type != operation || acl->record_type != record_type || ptr->cond != condition || acl->min_port != min_port || acl->max_port != max_port) continue;
359                          if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                          if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
360                                  if (ptr2->u.group != group) continue;                                  if (acl->u.group != group) continue;
361                          } else if (record_type == IP_RECORD_TYPE_IPv4) {                          } else if (record_type == IP_RECORD_TYPE_IPv4) {
362                                  if (ptr2->u.ipv4.min != min_ip || max_ip != ptr2->u.ipv4.max) continue;                                  if (acl->u.ipv4.min != min_ip || max_ip != acl->u.ipv4.max) continue;
363                          } else if (record_type == IP_RECORD_TYPE_IPv6) {                          } else if (record_type == IP_RECORD_TYPE_IPv6) {
364                                  if (memcmp(ptr2->u.ipv6.min, min_address, 16) || memcmp(max_address, ptr2->u.ipv6.max, 16)) continue;                                  if (acl->u.ipv6.min != saved_min_address || saved_max_address != acl->u.ipv6.max) continue;
365                          }                          }
366                          error = DelDomainACL(ptr);                          error = DelDomainACL(ptr);
367                          break;                          break;
368                  }                  }
369          }          }
370          up(&domain_acl_lock);   out: ;
371            mutex_unlock(&domain_acl_lock);
372          return error;          return error;
373  }  }
374    
375  static int CheckNetworkEntry(const int is_ipv6, const int operation, const u32 *address, const u16 port)  static int CheckNetworkEntry(const bool is_ipv6, const int operation, const u32 *address, const u16 port)
376  {  {
377          struct domain_info * const domain = current->domain_info;          struct domain_info * const domain = current->domain_info;
378          struct acl_info *ptr;          struct acl_info *ptr;
379          const char *keyword = network2keyword(operation);          const char *keyword = network2keyword(operation);
380          const int is_enforce = CheckCCSEnforce(CCS_TOMOYO_MAC_FOR_NETWORK);          const bool is_enforce = CheckCCSEnforce(CCS_TOMOYO_MAC_FOR_NETWORK);
381          const u32 ip = ntohl(*address); /* using host byte order to allow u32 comparison than memcmp().*/          const u32 ip = ntohl(*address); /* using host byte order to allow u32 comparison than memcmp().*/
382            bool found = 0;
383          if (!CheckCCSFlags(CCS_TOMOYO_MAC_FOR_NETWORK)) return 0;          if (!CheckCCSFlags(CCS_TOMOYO_MAC_FOR_NETWORK)) return 0;
384          for (ptr = domain->first_acl_ptr; ptr; ptr = ptr->next) {          list1_for_each_entry(ptr, &domain->acl_info_list, list) {
385                  struct ip_network_acl_record *ptr2 = (struct ip_network_acl_record *) ptr;                  struct ip_network_acl_record *acl;
386                  if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || ptr2->operation_type != operation || port < ptr2->min_port || ptr2->max_port < port || CheckCondition(ptr->cond, NULL)) continue;                  acl = container_of(ptr, struct ip_network_acl_record, head);
387                  if (ptr2->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {                  if (ptr->type != TYPE_IP_NETWORK_ACL || ptr->is_deleted || acl->operation_type != operation || port < acl->min_port || acl->max_port < port || CheckCondition(ptr->cond, NULL)) continue;
388                          if (AddressMatchesToGroup(is_ipv6, address, ptr2->u.group)) break;                  if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
389                  } else if (ptr2->record_type == IP_RECORD_TYPE_IPv4) {                          if (!AddressMatchesToGroup(is_ipv6, address, acl->u.group)) continue;
390                          if (!is_ipv6 && ptr2->u.ipv4.min <= ip && ip <= ptr2->u.ipv4.max) break;                  } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
391                            if (is_ipv6 || ip < acl->u.ipv4.min || acl->u.ipv4.max < ip) continue;
392                  } else {                  } else {
393                          if (is_ipv6 && memcmp(ptr2->u.ipv6.min, address, 16) <= 0 && memcmp(address, ptr2->u.ipv6.max, 16) <= 0) break;                          if (!is_ipv6 || memcmp(acl->u.ipv6.min, address, 16) > 0 || memcmp(address, acl->u.ipv6.max, 16) > 0) continue;
394                  }                  }
395                    found = 1;
396                    break;
397                            
398          }          }
399          if (ptr) {          AuditNetworkLog(is_ipv6, keyword, address, port, found);
400                  AuditNetworkLog(is_ipv6, keyword, address, port, 1);          if (found) return 0;
                 return 0;  
         }  
401          if (TomoyoVerboseMode()) {          if (TomoyoVerboseMode()) {
402                  if (is_ipv6) {                  if (is_ipv6) {
403                          char buf[64];                          char buf[64];
404                          print_ipv6(buf, sizeof(buf), (const u16 *) address);                          print_ipv6(buf, sizeof(buf), (const struct in6_addr *) address);
405                          printk("TOMOYO-%s: %s to %s %u denied for %s\n", GetMSG(is_enforce), keyword, buf, port, GetLastName(domain));                          printk("TOMOYO-%s: %s to %s %u denied for %s\n", GetMSG(is_enforce), keyword, buf, port, GetLastName(domain));
406                  } else {                  } else {
407                          printk("TOMOYO-%s: %s to %u.%u.%u.%u %u denied for %s\n", GetMSG(is_enforce), keyword, HIPQUAD(ip), port, GetLastName(domain));                          printk("TOMOYO-%s: %s to %u.%u.%u.%u %u denied for %s\n", GetMSG(is_enforce), keyword, HIPQUAD(ip), port, GetLastName(domain));
# Line 369  static int CheckNetworkEntry(const int i Line 411  static int CheckNetworkEntry(const int i
411          if (is_enforce) {          if (is_enforce) {
412                  if (is_ipv6) {                  if (is_ipv6) {
413                          char buf[64];                          char buf[64];
414                          print_ipv6(buf, sizeof(buf), (const u16 *) address);                          print_ipv6(buf, sizeof(buf), (const struct in6_addr *) address);
415                          return CheckSupervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s %s %u\n", domain->domainname->name, keyword, buf, port);                          return CheckSupervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s %s %u\n", domain->domainname->name, keyword, buf, port);
416                  }                  }
417                  return CheckSupervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s %u.%u.%u.%u %u\n", domain->domainname->name, keyword, HIPQUAD(ip), port);                  return CheckSupervisor("%s\n" KEYWORD_ALLOW_NETWORK "%s %u.%u.%u.%u %u\n", domain->domainname->name, keyword, HIPQUAD(ip), port);
418          }          }
419          if (CheckCCSAccept(CCS_TOMOYO_MAC_FOR_NETWORK)) AddNetworkEntry(operation, is_ipv6 ? IP_RECORD_TYPE_IPv6: IP_RECORD_TYPE_IPv4, NULL, address, address, port, port, domain, 1, NULL);          if (CheckCCSAccept(CCS_TOMOYO_MAC_FOR_NETWORK, domain)) AddNetworkEntry(operation, is_ipv6 ? IP_RECORD_TYPE_IPv6 : IP_RECORD_TYPE_IPv4, NULL, address, address, port, port, domain, NULL, 0);
420          return 0;          return 0;
421  }  }
422    
423  int AddNetworkPolicy(char *data, struct domain_info *domain, const int is_delete)  int AddNetworkPolicy(char *data, struct domain_info *domain, const struct condition_list *condition, const bool is_delete)
424  {  {
425          u8 sock_type, operation, record_type;          u8 sock_type, operation, record_type;
426          u16 min_address[8], max_address[8];          u16 min_address[8], max_address[8];
# Line 386  int AddNetworkPolicy(char *data, struct Line 428  int AddNetworkPolicy(char *data, struct
428          u16 min_port, max_port;          u16 min_port, max_port;
429          int count;          int count;
430          char *cp1 = NULL, *cp2 = NULL;          char *cp1 = NULL, *cp2 = NULL;
         const struct condition_list *condition = NULL;  
         cp1 = FindConditionPart(data);  
         if (cp1 && (condition = FindOrAssignNewCondition(cp1)) == NULL) goto out;  
431          if ((cp1 = strchr(data, ' ')) == NULL) goto out; cp1++;          if ((cp1 = strchr(data, ' ')) == NULL) goto out; cp1++;
432          if (strncmp(data, "TCP ", 4) == 0) sock_type = SOCK_STREAM;          if (strncmp(data, "TCP ", 4) == 0) sock_type = SOCK_STREAM;
433          else if (strncmp(data, "UDP ", 4) == 0) sock_type = SOCK_DGRAM;          else if (strncmp(data, "UDP ", 4) == 0) sock_type = SOCK_DGRAM;
# Line 408  int AddNetworkPolicy(char *data, struct Line 447  int AddNetworkPolicy(char *data, struct
447          }          }
448          if ((cp1 = strchr(cp2, ' ')) == NULL) goto out; *cp1++ = '\0';          if ((cp1 = strchr(cp2, ' ')) == NULL) goto out; *cp1++ = '\0';
449          if ((count = sscanf(cp2, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",          if ((count = sscanf(cp2, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
450                                                  &min_address[0], &min_address[1], &min_address[2], &min_address[3],                              &min_address[0], &min_address[1], &min_address[2], &min_address[3],
451                                                  &min_address[4], &min_address[5], &min_address[6], &min_address[7],                              &min_address[4], &min_address[5], &min_address[6], &min_address[7],
452                                                  &max_address[0], &max_address[1], &max_address[2], &max_address[3],                              &max_address[0], &max_address[1], &max_address[2], &max_address[3],
453                                                  &max_address[4], &max_address[5], &max_address[6], &max_address[7])) == 8 || count == 16) {                              &max_address[4], &max_address[5], &max_address[6], &max_address[7])) == 8 || count == 16) {
454                  int i;                  int i;
455                  for (i = 0; i < 8; i++) {                  for (i = 0; i < 8; i++) {
456                          min_address[i] = htons(min_address[i]);                          min_address[i] = htons(min_address[i]);
# Line 420  int AddNetworkPolicy(char *data, struct Line 459  int AddNetworkPolicy(char *data, struct
459                  if (count == 8) memmove(max_address, min_address, sizeof(min_address));                  if (count == 8) memmove(max_address, min_address, sizeof(min_address));
460                  record_type = IP_RECORD_TYPE_IPv6;                  record_type = IP_RECORD_TYPE_IPv6;
461          } else if ((count = sscanf(cp2, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",          } else if ((count = sscanf(cp2, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
462                                                             &min_address[0], &min_address[1], &min_address[2], &min_address[3],                                     &min_address[0], &min_address[1], &min_address[2], &min_address[3],
463                                                             &max_address[0], &max_address[1], &max_address[2], &max_address[3])) == 4 || count == 8) {                                     &max_address[0], &max_address[1], &max_address[2], &max_address[3])) == 4 || count == 8) {
464                  u32 ip = htonl((((u8) min_address[0]) << 24) + (((u8) min_address[1]) << 16) + (((u8) min_address[2]) << 8) + (u8) min_address[3]);                  u32 ip = htonl((((u8) min_address[0]) << 24) + (((u8) min_address[1]) << 16) + (((u8) min_address[2]) << 8) + (u8) min_address[3]);
465                  * (u32 *) min_address = ip;                  * (u32 *) min_address = ip;
466                  if (count == 8) ip = htonl((((u8) max_address[0]) << 24) + (((u8) max_address[1]) << 16) + (((u8) max_address[2]) << 8) + (u8) max_address[3]);                  if (count == 8) ip = htonl((((u8) max_address[0]) << 24) + (((u8) max_address[1]) << 16) + (((u8) max_address[2]) << 8) + (u8) max_address[3]);
# Line 436  int AddNetworkPolicy(char *data, struct Line 475  int AddNetworkPolicy(char *data, struct
475          if (strchr(cp1, ' ')) goto out;          if (strchr(cp1, ' ')) goto out;
476          if ((count = sscanf(cp1, "%hu-%hu", &min_port, &max_port)) == 1 || count == 2) {          if ((count = sscanf(cp1, "%hu-%hu", &min_port, &max_port)) == 1 || count == 2) {
477                  if (count == 1) max_port = min_port;                  if (count == 1) max_port = min_port;
478                  return AddNetworkEntry(operation, record_type, group, (u32 *) min_address, (u32 *) max_address, min_port, max_port, domain, is_delete ? 0 : -1, condition);                  return AddNetworkEntry(operation, record_type, group, (u32 *) min_address, (u32 *) max_address, min_port, max_port, domain, condition, is_delete);
479          }          }
480   out: ;   out: ;
481          return -EINVAL;          return -EINVAL;
482  }  }
483    
484  int CheckNetworkListenACL(const int is_ipv6, const u8 *address, const u16 port)  int CheckNetworkListenACL(const _Bool is_ipv6, const u8 *address, const u16 port)
485  {  {
486          return CheckNetworkEntry(is_ipv6, NETWORK_ACL_TCP_LISTEN, (const u32 *) address, ntohs(port));          return CheckNetworkEntry(is_ipv6, NETWORK_ACL_TCP_LISTEN, (const u32 *) address, ntohs(port));
487  }  }
 EXPORT_SYMBOL(CheckNetworkListenACL);  
488    
489  int CheckNetworkConnectACL(const int is_ipv6, const int sock_type, const u8 *address, const u16 port)  int CheckNetworkConnectACL(const _Bool is_ipv6, const int sock_type, const u8 *address, const u16 port)
490  {  {
491          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_STREAM ? NETWORK_ACL_TCP_CONNECT : (sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT), (const u32 *) address, ntohs(port));          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_STREAM ? NETWORK_ACL_TCP_CONNECT : (sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT), (const u32 *) address, ntohs(port));
492  }  }
 EXPORT_SYMBOL(CheckNetworkConnectACL);  
493    
494  int CheckNetworkBindACL(const int is_ipv6, const int sock_type, const u8 *address, const u16 port)  int CheckNetworkBindACL(const _Bool is_ipv6, const int sock_type, const u8 *address, const u16 port)
495  {  {
496          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_STREAM ? NETWORK_ACL_TCP_BIND : (sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_BIND : NETWORK_ACL_RAW_BIND), (const u32 *) address, ntohs(port));          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_STREAM ? NETWORK_ACL_TCP_BIND : (sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_BIND : NETWORK_ACL_RAW_BIND), (const u32 *) address, ntohs(port));
497  }  }
 EXPORT_SYMBOL(CheckNetworkBindACL);  
498    
499  int CheckNetworkAcceptACL(const int is_ipv6, const u8 *address, const u16 port)  int CheckNetworkAcceptACL(const _Bool is_ipv6, const u8 *address, const u16 port)
500  {  {
501          return CheckNetworkEntry(is_ipv6, NETWORK_ACL_TCP_ACCEPT, (const u32 *) address, ntohs(port));          int retval;
502            current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
503            retval = CheckNetworkEntry(is_ipv6, NETWORK_ACL_TCP_ACCEPT, (const u32 *) address, ntohs(port));
504            current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
505            return retval;
506  }  }
 EXPORT_SYMBOL(CheckNetworkAcceptACL);  
507    
508  int CheckNetworkSendMsgACL(const int is_ipv6, const int sock_type, const u8 *address, const u16 port)  int CheckNetworkSendMsgACL(const _Bool is_ipv6, const int sock_type, const u8 *address, const u16 port)
509  {  {
510          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT, (const u32 *) address, ntohs(port));          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT, (const u32 *) address, ntohs(port));
511  }  }
 EXPORT_SYMBOL(CheckNetworkSendMsgACL);  
512    
513  int CheckNetworkRecvMsgACL(const int is_ipv6, const int sock_type, const u8 *address, const u16 port)  int CheckNetworkRecvMsgACL(const _Bool is_ipv6, const int sock_type, const u8 *address, const u16 port)
514  {  {
515          return CheckNetworkEntry(is_ipv6, sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT, (const u32 *) address, ntohs(port));          int retval;
516            current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
517            retval = CheckNetworkEntry(is_ipv6, sock_type == SOCK_DGRAM ? NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT, (const u32 *) address, ntohs(port));
518            current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
519            return retval;
520  }  }
 EXPORT_SYMBOL(CheckNetworkRecvMsgACL);  
521    
522  /***** TOMOYO Linux end. *****/  /***** TOMOYO Linux end. *****/

Legend:
Removed from v.473  
changed lines
  Added in v.808

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26