/*---[ modrules.c ]---------------------------------------------------
 * Copyright (C) 2000 Tomas Junnonen (majix@sci.fi)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * The modrule fuctions use data from the selected line in the hitlog CList
 * to make specials rules which override the basic druid generated rules.
 * Functions to remove these rules are also listed here.
 *--------------------------------------------------------------------*/

#include <sys/stat.h>
#include <sys/types.h>

#include "modrules.h"
#include "firestarter.h"
#include "parse.h"

gboolean restart = TRUE;
extern gboolean NETFILTER;

/* [ clear_rule ]
 * Removes the select dynamic rule row from the clist and the disk file
 */
void
clear_rule (void)
{
	if (dynclist != NULL) {
		GList *list = NULL;
		GList *li;
		gchar buf[100];
		gint row = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (dynclist), "row"));

		FILE *file = fopen (gtk_object_get_data (GTK_OBJECT (dynclist), "path"), "r");
		if (file == NULL) {
			g_print ("Failed to open file for reading");
			return;
		}

		while (fgets (buf, 100, file) != NULL) {
			list = g_list_append (list, g_strdup_printf ("%s", buf));
		}

		li = g_list_nth (list, row);
		list = g_list_remove_link (list, li);

		fclose (file);

		file = fopen (gtk_object_get_data (GTK_OBJECT (dynclist), "path"), "w");
		if (file == NULL) {
			g_print ("Failed to open file for writing");
			return;
		}

		for (li = list; li != NULL; li = li->next)
			fprintf (file, "%s", (char *)li->data);
		fclose (file);

		restart_firewall ();

	/* Reload the dynamic rules clists */
		parse_allow_and_deny_all ();
		parse_allow_service_machine ();
		parse_allow_service_all ();

		gtk_signal_emit_by_name (GTK_OBJECT (dynclist), "unselect-row");
	}
}

/*---[ clear_group ]--------------------------------------------------
 * Clears and entire group of rules, resetting the rule file
 *--------------------------------------------------------------------*/
void
clear_group (void)
{
	if (geteuid ())
		return;

	if (dynclist != NULL) {
		FILE *file = fopen (gtk_object_get_data (GTK_OBJECT (dynclist), "path"), "w");
		if (file == NULL) {
			g_print ("Failed to open file for writing");
			return;
		}

		chmod (gtk_object_get_data (GTK_OBJECT (dynclist), "path"), 00700);
		fprintf (file, "#!/bin/sh\n");
		fclose (file);

		gtk_clist_clear (GTK_CLIST (dynclist));

		if (restart)
			restart_firewall ();

		gtk_signal_emit_by_name (GTK_OBJECT (dynclist), "unselect-row");
	}
}

/*---[ clear_all_groups ]---------------------------------------------
 * Calls clear_group for every group
 *--------------------------------------------------------------------*/
void
clear_all_groups (void)
{
	if (geteuid ())
		return;

	restart = FALSE;

	dynclist = (gpointer *) denyallclist;
	clear_group ();
	dynclist = (gpointer *) allowallclist;
	clear_group ();
	dynclist = (gpointer *) allowsmclist;
	clear_group ();
	dynclist = (gpointer *) allowsaclist;
	clear_group ();

	restart = TRUE;
	restart_firewall ();
}

/*---[ allow_all_from_machine ]---------------------------------------
 * Allow all traffic from selected machine
 *--------------------------------------------------------------------*/
void
allow_all_from_machine (GtkWidget *widget, gpointer data)
{
	gpointer *clistrow = gtk_object_get_data (GTK_OBJECT (hitlogclist), "row");

	if (clistrow != NULL) {
		gchar *ip;
		char *logpath = FIRESTARTER_RULES_DIR "/firestarter/allow-all";
		FILE *f = fopen (logpath, "a");
		if (f == NULL) {
			g_print ("Failed to open file %s", logpath);
			return;
		}

		gtk_clist_get_text (GTK_CLIST (hitlogclist), GPOINTER_TO_INT (clistrow)-1, 1, &ip);

		if (NETFILTER)
			fprintf (f, "$IPT -A INPUT -s %s -d 0/0 -j ACCEPT\n", ip);
                else
			fprintf (f, "$IPC -A input -s %s -d 0/0 -j ACCEPT\n", ip);

		fclose (f);
		parse_allow_and_deny_all ();

		restart_firewall ();
	}
}

/*---[ deny_all_from_machine ]----------------------------------------
 * Deny all traffic from selected machine
 *--------------------------------------------------------------------*/
void
deny_all_from_machine (GtkWidget *widget, gpointer data)
{
	gpointer *clistrow = gtk_object_get_data (GTK_OBJECT (hitlogclist), "row");

	if (clistrow != NULL) {
		gchar *ip;
		char *logpath = FIRESTARTER_RULES_DIR "/firestarter/deny-all";
		FILE *f = fopen (logpath, "a");
		if (f == NULL) {
			g_print ("Failed to open file %s", logpath);
			return;
		}

		gtk_clist_get_text (GTK_CLIST (hitlogclist), GPOINTER_TO_INT (clistrow)-1, 1, &ip);

                if (NETFILTER)
			fprintf (f, "$IPT -A INPUT -s %s -d 0/0 -j DROP\n", ip);
		else
			fprintf (f, "$IPC -A input -s %s -d 0/0 -j DENY\n", ip);

		fclose (f);
		parse_allow_and_deny_all ();

		restart_firewall ();
	}
}

/*---[ open_service_to_machine ]--------------------------------------
 * Open a specific service to a specific machine
 *--------------------------------------------------------------------*/
void
open_service_to_machine (GtkWidget *widget, gpointer data)
{
	gpointer *clistrow = gtk_object_get_data (GTK_OBJECT (hitlogclist), "row");

	if (clistrow != NULL) {
		gchar *proto;
		gchar *port;
		gchar *ip;
		char *logpath = FIRESTARTER_RULES_DIR "/firestarter/allow-service-machine";
		FILE *f = fopen (logpath, "a");
		if (f == NULL) {
			g_print ("Failed to open file %s", logpath);
			return;
		}

		gtk_clist_get_text (GTK_CLIST (hitlogclist), GPOINTER_TO_INT (clistrow)-1, 0, &port);
		gtk_clist_get_text (GTK_CLIST (hitlogclist), GPOINTER_TO_INT (clistrow)-1, 1, &ip);

		proto = (char*) gtk_object_get_data (GTK_OBJECT (hitlogclist),
			g_strdup_printf ("%d", GPOINTER_TO_INT (clistrow)));

                if (NETFILTER)
			fprintf (f, "$IPT -A INPUT -p %s -s %s -d $NET --dport %s -j ACCEPT\n",
				proto, ip, port);
		else
			fprintf (f, "$IPC -A input -p %s -s %s -d $NET %s -j ACCEPT\n",
				proto, ip, port);

		fclose (f);
		parse_allow_service_machine ();

		restart_firewall ();
	}
}

/*---[ open_service_to_anyone ]---------------------------------------
 * Open a specific service to everyone
 *--------------------------------------------------------------------*/
void
open_service_to_anyone (GtkWidget *widget, gpointer data)
{
	gpointer *clistrow = gtk_object_get_data (GTK_OBJECT (hitlogclist), "row");

	if (clistrow != NULL) {
		gchar *proto;
		gchar *port;
		char *logpath = FIRESTARTER_RULES_DIR "/firestarter/allow-service-all";
		FILE *f = fopen (logpath, "a");
		if (f == NULL) {
			g_print ("Failed to open file %s", logpath);
			return;
		}

		gtk_clist_get_text (GTK_CLIST (hitlogclist), GPOINTER_TO_INT (clistrow)-1, 0, &port);

		proto = (char*) gtk_object_get_data (GTK_OBJECT (hitlogclist),
			g_strdup_printf ("%d", GPOINTER_TO_INT (clistrow)));

		if (NETFILTER)
			fprintf (f, "$IPT -A INPUT -p %s -s 0/0 -d $NET --dport %s -j ACCEPT\n", proto, port);
		else
			fprintf (f, "$IPC -A input -p %s -s 0/0 -d $NET %s -j ACCEPT\n", proto, port);

		fclose (f);
		parse_allow_service_all ();

		restart_firewall ();
	}
}

void
do_not_log_port (gint port)
{
	gchar *logpath = FIRESTARTER_RULES_DIR "/firestarter/block-ports";
	FILE *f = fopen (logpath, "a");
	if (f == NULL) {
		g_print ("Failed to open file %s", logpath);
		return;
	}

	if (NETFILTER) {
		fprintf (f, "$IPT -A INPUT -p 6 -s 0/0 -d 0/0 --dport %d -j DROP\n", port);
		fprintf (f, "$IPT -A INPUT -p 17 -s 0/0 -d 0/0 --dport %d -j DROP\n", port);
	}
	else {
		fprintf (f, "$IPC -A input -p 6 -s 0/0 -d 0/0 %d -j $STOP\n", port);
		fprintf (f, "$IPC -A input -p 17 -s 0/0 -d 0/0 %d -j $STOP\n", port);
	}

	fclose (f);
}

void
do_not_log_port_clist (void)
{
	gpointer *clistrow = gtk_object_get_data (GTK_OBJECT (hitlogclist), "row");

	if (clistrow != NULL) {
		gchar *port;

		gtk_clist_get_text (GTK_CLIST (hitlogclist), GPOINTER_TO_INT (clistrow)-1, 0, &port);

		do_not_log_port (atoi (port));

		restart_firewall ();
	}
}
