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

Subversion リポジトリの参照

Diff of /branches/ccs-patch/security/ccsecurity/network.c

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

revision 2888 by kumaneko, Mon Aug 10 07:31:29 2009 UTC revision 2890 by kumaneko, Tue Aug 11 00:44:58 2009 UTC
# Line 104  static struct ccs_address_group_entry *c Line 104  static struct ccs_address_group_entry *c
104  }  }
105    
106  /**  /**
107     * ccs_parse_ip_address - Parse an IP address.
108     *
109     * @address: String to parse.
110     * @min:     Pointer to store min address.
111     * @max:     Pointer to store max address.
112     *
113     * Returns 2 if @address is an IPv6, 1 if @address is an IPv4, 0 otherwise.
114     */
115    static int ccs_parse_ip_address(char *address, u16 *min, u16 *max)
116    {
117            int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
118                               "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
119                               &min[0], &min[1], &min[2], &min[3],
120                               &min[4], &min[5], &min[6], &min[7],
121                               &max[0], &max[1], &max[2], &max[3],
122                               &max[4], &max[5], &max[6], &max[7]);
123            if (count == 8 || count == 16) {
124                    u8 i;
125                    if (count == 8)
126                            memmove(max, min, sizeof(u16) * 8);
127                    for (i = 0; i < 8; i++) {
128                            min[i] = htons(min[i]);
129                            max[i] = htons(max[i]);
130                    }
131                    return 2;
132            }
133            count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
134                           &min[0], &min[1], &min[2], &min[3],
135                           &max[0], &max[1], &max[2], &max[3]);
136            if (count == 4 || count == 8) {
137                    u32 ip = htonl((((u8) min[0]) << 24) + (((u8) min[1]) << 16)
138                                   + (((u8) min[2]) << 8) + (u8) min[3]);
139                    memmove(min, &ip, sizeof(ip));
140                    if (count == 8)
141                            ip = htonl((((u8) max[0]) << 24) + (((u8) max[1]) << 16)
142                                       + (((u8) max[2]) << 8) + (u8) max[3]);
143                    memmove(max, &ip, sizeof(ip));
144                    return 1;
145            }
146            return 0;
147    }
148    
149    /**
150   * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.   * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.
151   *   *
152   * @group_name:  The name of address group.   * @group_name:  The name of address group.
153   * @is_ipv6:     True if @min_address and @max_address are IPv6 addresses.   * @address:     IP address.
  * @min_address: Start of IPv4 or IPv6 address range.  
  * @max_address: End of IPv4 or IPv6 address range.  
154   * @is_delete:   True if it is a delete request.   * @is_delete:   True if it is a delete request.
155   *   *
156   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
157   */   */
158  static int ccs_update_address_group_entry(const char *group_name,  static int ccs_update_address_group_entry(const char *group_name,
159                                            const bool is_ipv6,                                            char *address, const bool is_delete)
                                           const u16 *min_address,  
                                           const u16 *max_address,  
                                           const bool is_delete)  
160  {  {
161          struct ccs_address_group_entry *group;          struct ccs_address_group_entry *group;
162          struct ccs_address_group_member *entry = NULL;          struct ccs_address_group_member *entry = NULL;
# Line 126  static int ccs_update_address_group_entr Line 164  static int ccs_update_address_group_entr
164          const struct in6_addr *saved_min_address = NULL;          const struct in6_addr *saved_min_address = NULL;
165          const struct in6_addr *saved_max_address = NULL;          const struct in6_addr *saved_max_address = NULL;
166          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
167          const u32 min_ipv4_address = ntohl(*(u32 *) min_address);          u32 min_ipv4_address = 0;
168          const u32 max_ipv4_address = ntohl(*(u32 *) max_address);          u32 max_ipv4_address = 0;
169            u16 min_address[8];
170            u16 max_address[8];
171            bool is_ipv6 = false;
172          group = ccs_get_address_group(group_name);          group = ccs_get_address_group(group_name);
173          if (!group)          if (!group)
174                  return -ENOMEM;                  return -ENOMEM;
175          if (is_ipv6) {          switch (ccs_parse_ip_address(address, min_address, max_address)) {
176            case 2:
177                    is_ipv6 = true;
178                  saved_min_address                  saved_min_address
179                          = ccs_get_ipv6_address((struct in6_addr *)                          = ccs_get_ipv6_address((struct in6_addr *)
180                                                 min_address);                                                 min_address);
# Line 140  static int ccs_update_address_group_entr Line 183  static int ccs_update_address_group_entr
183                                                 max_address);                                                 max_address);
184                  if (!saved_min_address || !saved_max_address)                  if (!saved_min_address || !saved_max_address)
185                          goto out;                          goto out;
186                    break;
187            case 1:
188                    min_ipv4_address = ntohl(*(u32 *) min_address);
189                    max_ipv4_address = ntohl(*(u32 *) max_address);
190                    break;
191            default:
192                    goto out;
193          }          }
194          if (!is_delete)          if (!is_delete)
195                  entry = kzalloc(sizeof(*entry), GFP_KERNEL);                  entry = kzalloc(sizeof(*entry), GFP_KERNEL);
# Line 186  static int ccs_update_address_group_entr Line 236  static int ccs_update_address_group_entr
236  }  }
237    
238  /**  /**
  * ccs_parse_ip_address - Parse an IP address.  
  *  
  * @address: String to parse.  
  * @min:     Pointer to store min address.  
  * @max:     Pointer to store max address.  
  *  
  * Returns 2 if @address is an IPv6, 1 if @address is an IPv4, 0 otherwise.  
  */  
 static int ccs_parse_ip_address(char *address, u16 *min, u16 *max)  
 {  
         int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"  
                            "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",  
                            &min[0], &min[1], &min[2], &min[3],  
                            &min[4], &min[5], &min[6], &min[7],  
                            &max[0], &max[1], &max[2], &max[3],  
                            &max[4], &max[5], &max[6], &max[7]);  
         if (count == 8 || count == 16) {  
                 u8 i;  
                 if (count == 8)  
                         memmove(max, min, sizeof(u16) * 8);  
                 for (i = 0; i < 8; i++) {  
                         min[i] = htons(min[i]);  
                         max[i] = htons(max[i]);  
                 }  
                 return 2;  
         }  
         count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",  
                        &min[0], &min[1], &min[2], &min[3],  
                        &max[0], &max[1], &max[2], &max[3]);  
         if (count == 4 || count == 8) {  
                 u32 ip = htonl((((u8) min[0]) << 24) + (((u8) min[1]) << 16)  
                                + (((u8) min[2]) << 8) + (u8) min[3]);  
                 memmove(min, &ip, sizeof(ip));  
                 if (count == 8)  
                         ip = htonl((((u8) max[0]) << 24) + (((u8) max[1]) << 16)  
                                    + (((u8) max[2]) << 8) + (u8) max[3]);  
                 memmove(max, &ip, sizeof(ip));  
                 return 1;  
         }  
         return 0;  
 }  
   
 /**  
239   * ccs_write_address_group_policy - Write "struct ccs_address_group_entry" list.   * ccs_write_address_group_policy - Write "struct ccs_address_group_entry" list.
240   *   *
241   * @data:      String to parse.   * @data:      String to parse.
# Line 239  static int ccs_parse_ip_address(char *ad Line 246  static int ccs_parse_ip_address(char *ad
246  int ccs_write_address_group_policy(char *data, const bool is_delete)  int ccs_write_address_group_policy(char *data, const bool is_delete)
247  {  {
248          char *w[2];          char *w[2];
         bool is_ipv6;  
         u16 min_address[8];  
         u16 max_address[8];  
249          if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])          if (!ccs_tokenize(data, w, sizeof(w)) || !w[1][0])
250                  return -EINVAL;                  return -EINVAL;
251          switch (ccs_parse_ip_address(w[1], min_address, max_address)) {          return ccs_update_address_group_entry(w[0], w[1], is_delete);
         case 2:  
                 is_ipv6 = true;  
                 break;  
         case 1:  
                 is_ipv6 = false;  
                 break;  
         default:  
                 return -EINVAL;  
         }  
         return ccs_update_address_group_entry(w[0], is_ipv6, min_address,  
                                               max_address, is_delete);  
252  }  }
253    
254  /**  /**
# Line 432  const char *ccs_net2keyword(const u8 ope Line 425  const char *ccs_net2keyword(const u8 ope
425  /**  /**
426   * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.   * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.
427   *   *
428     * @protocol:    Protocol name.
429   * @operation:   Type of operation.   * @operation:   Type of operation.
430   * @record_type: Type of address.   * @address:     Address.
431   * @group:       Name of group. May be NULL.   * @port:        Port number.
  * @min_address: Start of IPv4 or IPv6 address range.  
  * @max_address: End of IPv4 or IPv6 address range.  
  * @min_port:    Start of port number range.  
  * @max_port:    End of port number range.  
432   * @domain:      Pointer to "struct ccs_domain_info".   * @domain:      Pointer to "struct ccs_domain_info".
433   * @condition:   Pointer to "struct ccs_condition". May be NULL.   * @condition:   Pointer to "struct ccs_condition". May be NULL.
434   * @is_delete:   True if it is a delete request.   * @is_delete:   True if it is a delete request.
435   *   *
436   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
437   */   */
438  static int ccs_update_network_entry(const u8 operation, const u8 record_type,  static int ccs_update_network_entry(const char *protocol,
439                                      const char *address_group_name,                                      const char *operation, char *address,
440                                      const char *port_group_name,                                      char *port, struct ccs_domain_info *domain,
                                     const u32 *min_address,  
                                     const u32 *max_address,  
                                     const u16 min_port, const u16 max_port,  
                                     struct ccs_domain_info *domain,  
441                                      struct ccs_condition *condition,                                      struct ccs_condition *condition,
442                                      const bool is_delete)                                      const bool is_delete)
443  {  {
# Line 460  static int ccs_update_network_entry(cons Line 446  static int ccs_update_network_entry(cons
446          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
447          struct ccs_ip_network_acl_record e;          struct ccs_ip_network_acl_record e;
448          struct ccs_ip_network_acl_record *entry = NULL;          struct ccs_ip_network_acl_record *entry = NULL;
449            u16 min_address[8];
450            u16 max_address[8];
451          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
452            u8 sock_type;
453          memset(&e, 0, sizeof(e));          memset(&e, 0, sizeof(e));
454          e.head.type = TYPE_IP_NETWORK_ACL;          e.head.type = TYPE_IP_NETWORK_ACL;
455          e.head.cond = condition;          e.head.cond = condition;
         e.operation_type = operation;  
         e.record_type = record_type;  
456          if (!domain)          if (!domain)
457                  return -EINVAL;                  return -EINVAL;
458          if (address_group_name) {          if (!strcmp(protocol, "TCP"))
459                  e.address.group = ccs_get_address_group(address_group_name);                  sock_type = SOCK_STREAM;
460                  if (!e.address.group)          else if (!strcmp(protocol, "UDP"))
461                          return -ENOMEM;                  sock_type = SOCK_DGRAM;
462          } else if (record_type == IP_RECORD_TYPE_IPv6) {          else if (!strcmp(protocol, "RAW"))
463                    sock_type = SOCK_RAW;
464            else
465                    return -EINVAL;
466            if (!strcmp(operation, "bind"))
467                    switch (sock_type) {
468                    case SOCK_STREAM:
469                            e.operation_type = NETWORK_ACL_TCP_BIND;
470                            break;
471                    case SOCK_DGRAM:
472                            e.operation_type = NETWORK_ACL_UDP_BIND;
473                            break;
474                    default:
475                            e.operation_type = NETWORK_ACL_RAW_BIND;
476                            break;
477                    }
478            else if (!strcmp(operation, "connect"))
479                    switch (sock_type) {
480                    case SOCK_STREAM:
481                            e.operation_type = NETWORK_ACL_TCP_CONNECT;
482                            break;
483                    case SOCK_DGRAM:
484                            e.operation_type = NETWORK_ACL_UDP_CONNECT;
485                            break;
486                    default:
487                            e.operation_type = NETWORK_ACL_RAW_CONNECT;
488                            break;
489                    }
490            else if (sock_type == SOCK_STREAM && !strcmp(operation, "listen"))
491                    e.operation_type = NETWORK_ACL_TCP_LISTEN;
492            else if (sock_type == SOCK_STREAM && !strcmp(operation, "accept"))
493                    e.operation_type = NETWORK_ACL_TCP_ACCEPT;
494            else
495                    return -EINVAL;
496            switch (ccs_parse_ip_address(address, min_address, max_address)) {
497            case 2:
498                    e.record_type = IP_RECORD_TYPE_IPv6;
499                  e.address.ipv6.min = ccs_get_ipv6_address((struct in6_addr *)                  e.address.ipv6.min = ccs_get_ipv6_address((struct in6_addr *)
500                                                            min_address);                                                            min_address);
501                  e.address.ipv6.max = ccs_get_ipv6_address((struct in6_addr *)                  e.address.ipv6.max = ccs_get_ipv6_address((struct in6_addr *)
502                                                            max_address);                                                            max_address);
503                  if (!e.address.ipv6.min || !e.address.ipv6.max)                  if (!e.address.ipv6.min || !e.address.ipv6.max)
504                          goto out;                          goto out;
505          } else {                  break;
506                  /* use host byte order to allow u32 comparison than memcmp().*/          case 1:
507                  e.address.ipv4.min = ntohl(*min_address);                  e.record_type = IP_RECORD_TYPE_IPv4;
508                  e.address.ipv4.max = ntohl(*max_address);                  /* use host byte order to allow u32 comparison.*/
509          }                  e.address.ipv4.min = ntohl(* (u32 *) min_address);
510          if (port_group_name) {                  e.address.ipv4.max = ntohl(* (u32 *) max_address);
511                  if (!ccs_check_and_save_number(port_group_name, &e.port))                  break;
512                      goto out;          default:
513          } else {                  if (address[0] != '@')
514                  e.port.values[0] = min_port;                          return -EINVAL;
515                  e.port.values[1] = max_port;                  e.record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
516                    e.address.group = ccs_get_address_group(address + 1);
517                    if (!e.address.group)
518                            return -ENOMEM;
519                    break;
520          }          }
521            if (!ccs_parse_number_union(port, &e.port))
522                    goto out;
523          if (is_delete)          if (is_delete)
524                  goto delete;                  goto delete;
525          entry = kzalloc(sizeof(*entry), GFP_KERNEL);          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
# Line 533  static int ccs_update_network_entry(cons Line 562  static int ccs_update_network_entry(cons
562          }          }
563          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
564   out:   out:
565          if (address_group_name)          if (address[0] == '@')
566                  ccs_put_address_group(e.address.group);                  ccs_put_address_group(e.address.group);
567          else if (record_type == IP_RECORD_TYPE_IPv6) {          else if (e.record_type == IP_RECORD_TYPE_IPv6) {
568                  ccs_put_ipv6_address(e.address.ipv6.min);                  ccs_put_ipv6_address(e.address.ipv6.min);
569                  ccs_put_ipv6_address(e.address.ipv6.max);                  ccs_put_ipv6_address(e.address.ipv6.max);
570          }          }
571          if (port_group_name)          ccs_put_number_union(&e.port);
                 ccs_put_number_group(e.port.group);  
572          kfree(entry);          kfree(entry);
573          return error;          return error;
574  }  }
# Line 622  static int ccs_check_network_entry2(cons Line 650  static int ccs_check_network_entry2(cons
650                          goto retry;                          goto retry;
651                  return err;                  return err;
652          } else if (ccs_domain_quota_ok(&r)) {          } else if (ccs_domain_quota_ok(&r)) {
653                  struct ccs_condition *cond = ccs_handler_cond();                  char *tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
654                  ccs_update_network_entry(operation, is_ipv6 ?                  if (tmp) {
655                                           IP_RECORD_TYPE_IPv6 :                          struct ccs_condition *cond = ccs_handler_cond();
656                                           IP_RECORD_TYPE_IPv4,                          snprintf(tmp, PAGE_SIZE - 1, "%s %s %u", keyword, buf,
657                                           NULL, NULL, address, address, port,                                   port);
658                                           port, r.domain, cond, false);                          ccs_write_network_policy(tmp, r.domain, cond, false);
659                  ccs_put_condition(cond);                          ccs_put_condition(cond);
660                            kfree(tmp);
661                    }
662          }          }
663          return 0;          return 0;
664  }  }
# Line 668  int ccs_write_network_policy(char *data, Line 698  int ccs_write_network_policy(char *data,
698                               const bool is_delete)                               const bool is_delete)
699  {  {
700          char *w[4];          char *w[4];
         u8 sock_type;  
         u8 operation;  
         u8 record_type;  
         u16 min_address[8];  
         u16 max_address[8];  
         const char *address_group_name = NULL;  
         const char *port_group_name = NULL;  
         u16 min_port;  
         u16 max_port;  
701          if (!ccs_tokenize(data, w, sizeof(w)) || !w[3][0])          if (!ccs_tokenize(data, w, sizeof(w)) || !w[3][0])
702                  return -EINVAL;                  return -EINVAL;
703          if (!strcmp(w[0], "TCP"))          return ccs_update_network_entry(w[0], w[1], w[2], w[3], domain,
704                  sock_type = SOCK_STREAM;                                          condition, is_delete);
         else if (!strcmp(w[0], "UDP"))  
                 sock_type = SOCK_DGRAM;  
         else if (!strcmp(w[0], "RAW"))  
                 sock_type = SOCK_RAW;  
         else  
                 goto out;  
         if (!strcmp(w[1], "bind"))  
                 switch (sock_type) {  
                 case SOCK_STREAM:  
                         operation = NETWORK_ACL_TCP_BIND;  
                         break;  
                 case SOCK_DGRAM:  
                         operation = NETWORK_ACL_UDP_BIND;  
                         break;  
                 default:  
                         operation = NETWORK_ACL_RAW_BIND;  
                 }  
         else if (!strcmp(w[1], "connect"))  
                 switch (sock_type) {  
                 case SOCK_STREAM:  
                         operation = NETWORK_ACL_TCP_CONNECT;  
                         break;  
                 case SOCK_DGRAM:  
                         operation = NETWORK_ACL_UDP_CONNECT;  
                         break;  
                 default:  
                         operation = NETWORK_ACL_RAW_CONNECT;  
                 }  
         else if (sock_type == SOCK_STREAM && !strcmp(w[1], "listen"))  
                 operation = NETWORK_ACL_TCP_LISTEN;  
         else if (sock_type == SOCK_STREAM && !strcmp(w[1], "accept"))  
                 operation = NETWORK_ACL_TCP_ACCEPT;  
         else  
                 goto out;  
         switch (ccs_parse_ip_address(w[2], min_address, max_address)) {  
         case 2:  
                 record_type = IP_RECORD_TYPE_IPv6;  
                 break;  
         case 1:  
                 record_type = IP_RECORD_TYPE_IPv4;  
                 break;  
         default:  
                 if (w[2][0] != '@')  
                         goto out;  
                 address_group_name = w[2] + 1;  
                 record_type = IP_RECORD_TYPE_ADDRESS_GROUP;  
                 break;  
         }  
         switch (sscanf(w[3], "%hu-%hu", &min_port, &max_port)) {  
         case 2:  
                 break;  
         case 1:  
                 max_port = min_port;  
                 break;  
         default:  
                 if (w[3][0] != '@')  
                         goto out;  
                 port_group_name = w[3];  
                 break;  
         }  
         return ccs_update_network_entry(operation, record_type,  
                                         address_group_name, port_group_name,  
                                         (u32 *) min_address,  
                                         (u32 *) max_address,  
                                         min_port, max_port, domain, condition,  
                                         is_delete);  
  out:  
         return -EINVAL;  
705  }  }
706    
707  /**  /**

Legend:
Removed from v.2888  
changed lines
  Added in v.2890

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