Added a protocol check mechanism to form cleaning
[flowspy] / flowspec / forms.py
index bc8916e..3d7230f 100644 (file)
@@ -27,7 +27,8 @@ class RouteForm(forms.ModelForm):
         model = Route
     
     def clean_source(self):
-        user = User.objects.get(pk=self.data['applier'][0])
+        user = User.objects.get(pk=self.data['applier'])
+        peer = user.get_profile().peer
         data = self.cleaned_data['source']
         private_error = False
         protected_error = False
@@ -37,10 +38,10 @@ class RouteForm(forms.ModelForm):
                 for net in settings.PROTECTED_SUBNETS:
                     if address in IPNetwork(net):
                         protected_error = True
-                        mail_body = "User %s:%s attempted to set %s as the source address in a firewall rule" %(user.username, user.email, data)
+                        mail_body = "User %s %s (%s) attempted to set %s as the source address in a firewall rule" %(user.username, user.email, peer.peer_name, data)
                         send_mail(settings.EMAIL_SUBJECT_PREFIX + "Caught an attempt to set a protected IP/network as a source address",
                               mail_body, settings.SERVER_EMAIL,
-                              [settings.NOC_MAIL], fail_silently=True)
+                              settings.NOTIFY_ADMIN_MAILS, fail_silently=True)
                         raise forms.ValidationError("Not allowed")
                 if address.is_private:
                     private_error = True
@@ -56,7 +57,8 @@ class RouteForm(forms.ModelForm):
                 raise forms.ValidationError(error_text)
 
     def clean_destination(self):
-        user = User.objects.get(pk=self.data['applier'][0])
+        user = User.objects.get(pk=self.data['applier'])
+        peer = user.get_profile().peer        
         data = self.cleaned_data['destination']
         error = None
         protected_error = False
@@ -66,10 +68,10 @@ class RouteForm(forms.ModelForm):
                 for net in settings.PROTECTED_SUBNETS:
                     if address in IPNetwork(net):
                         protected_error = True
-                        mail_body = "User %s:%s attempted to set %s as the destination address in a firewall rule" %(user.username, user.email, data)
+                        mail_body = "User %s %s (%s) attempted to set %s as the destination address in a firewall rule" %(user.username, user.email, peer.peer_name, data)
                         send_mail(settings.EMAIL_SUBJECT_PREFIX + "Caught an attempt to set a protected IP/network as the destination address",
                               mail_body, settings.SERVER_EMAIL,
-                              [settings.NOC_MAIL], fail_silently=True)
+                              settings.NOTIFY_ADMIN_MAILS, fail_silently=True)
                         raise forms.ValidationError("Not allowed")
                 if address.prefixlen < settings.PREFIX_LENGTH:
                     error = "Currently no prefix lengths < %s are allowed" %settings.PREFIX_LENGTH
@@ -100,6 +102,7 @@ class RouteForm(forms.ModelForm):
         then = self.cleaned_data.get('then', None)
         destination = self.cleaned_data.get('destination', None)
         destinationports = self.cleaned_data.get('destinationport', None)
+        protocols = self.cleaned_data.get('protocol', None)
         user = self.cleaned_data.get('applier', None)
         peer = user.get_profile().peer
         networks = peer.networks.all()
@@ -121,16 +124,24 @@ class RouteForm(forms.ModelForm):
         if destinationports and not destination:
             raise forms.ValidationError('Once destination port is matched, destination has to be filled as well. Either deselect destination port or fill destination address')
         if not (source or sourceports or ports or destination or destinationports):
-            raise forms.ValidationError('Fill at least a Route Match Condition')
+            raise forms.ValidationError('Fill at least a Rule Match Condition')
         if not user.is_superuser and then[0].action not in settings.UI_USER_THEN_ACTIONS:
             raise forms.ValidationError('This action "%s" is not permitted' %(then[0].action))
-        existing_routes = Route.objects.exclude(status='EXPIRED').exclude(status='PENDING').exclude(status='ERROR').exclude(status='ADMININACTIVE')
+        existing_routes = Route.objects.exclude(status='EXPIRED').exclude(status='ERROR').exclude(status='ADMININACTIVE')
         existing_routes = existing_routes.filter(applier__userprofile__peer=peer)
         if source:
             source = IPNetwork(source).compressed
             existing_routes = existing_routes.filter(source=source)
         else:
             existing_routes = existing_routes.filter(source=None)
+        if protocols:
+            route_pk_list=get_matchingprotocol_route_pks(protocols, existing_routes)
+            if route_pk_list:
+                existing_routes = existing_routes.filter(pk__in=route_pk_list)
+            else:
+                existing_routes = existing_routes.filter(protocol=None)
+        else:
+            existing_routes = existing_routes.filter(protocol=None)
         if sourceports:
             route_pk_list=get_matchingport_route_pks(sourceports, existing_routes)
             if route_pk_list:
@@ -149,7 +160,6 @@ class RouteForm(forms.ModelForm):
                 existing_routes = existing_routes.filter(pk__in=route_pk_list)              
         else:
             existing_routes = existing_routes.filter(port=None)
-        
         for route in existing_routes:
             if name != route.name:
                 existing_url = reverse('edit-route', args=[route.name])
@@ -212,4 +222,13 @@ def get_matchingport_route_pks(portlist, routes):
         rsp = value_list_to_list(route.destinationport.all().values_list('port').order_by('port'))
         if rsp and rsp == ports_value_list:
             route_pk_list.append(route.pk)
+    return route_pk_list
+
+def get_matchingprotocol_route_pks(protocolist, routes):
+    route_pk_list = []
+    protocols_value_list = value_list_to_list(protocolist.values_list('protocol').order_by('protocol'))
+    for route in routes:
+        rsp = value_list_to_list(route.protocol.all().values_list('protocol').order_by('protocol'))
+        if rsp and rsp == protocols_value_list:
+            route_pk_list.append(route.pk)
     return route_pk_list
\ No newline at end of file