Logo Search packages:      
Sourcecode: gadmin-openvpn-client version File versions  Download package

apply_client_settings.c

/* GAdmin-OpenVPN - An easy to use GTK+ frontend for the openvpn client.
 * Copyright (C) 2008 Magnus Loef <magnus-swe@telia.com> 
 *
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
*/



#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "widgets.h"
#include "gettext.h"
#include "show_info.h"
#include "functions.h"
#include "apply_client_settings.h"
#include "allocate.h"
#include "commented.h"
#include "commands.h"
#include "populate_client_settings.h"
#include "populate_conf_tab.h"


extern gchar *selected_connection;

extern int activated;



int has_value(gchar *input)
{
    int have_value = 0;

    if( input!=NULL && strlen(input) > 2 )
      have_value = 1;

    return have_value;
}


/* Make firestarter/iptables accept tap+ interfaces */
void add_firestarter_user_pre()
{
    FILE *fp;
    long file_size = 0;
    char *line;
    gchar *conf;
    int have_tap_lines = 0;

    if((fp=fopen(FIRESTARTER_USER_PRE, "r"))==NULL)
    {
      /* Dont show a popup */
      return;
    }
    fseek(fp, 0, SEEK_END);
    file_size = ftell(fp);
    rewind(fp);

    line = allocate(file_size);

    if( file_size > 1 )
    while(fgets(line, file_size, fp)!=NULL)
    {
        if( line==NULL || strlen(line) < 10 || commented(line) )
            continue;

        if( cmplowercase(line, "-a input -i tap+ -j accept") )
          have_tap_lines++;

        if( cmplowercase(line, "-a output -o tap+ -j accept") )
          have_tap_lines++;

        if( cmplowercase(line, "-a forward -i tap+ -j accept") )
          have_tap_lines++;
    }
    fclose(fp);
    free(line);

    /* Dont add the tap+ lines if they already exist */
    if( have_tap_lines >= 3 )
      return;

    /* Append the lines. Does Firestarter allow tap broadcast traffic ? Fix: If it doesnt  */
    conf = g_strdup_printf("$IPT -A INPUT -i tap+ -j ACCEPT\n$IPT -A OUTPUT -o tap+ -j ACCEPT\n$IPT -A FORWARD -i tap+ -j ACCEPT\n");
    if((fp=fopen(FIRESTARTER_USER_PRE, "a"))==NULL)
    {
      /* Show a popup */
      printf("Unable to add firestarter configuration here: %s\n", FIRESTARTER_USER_PRE);
      g_free(conf);
      return;
    }
    fputs(conf, fp);
    fclose(fp);
    g_free(conf);
}


void apply_client_settings(struct w *widgets)
{
    /* Change the client configuration and sysinit script. */
    FILE *fp;
    int i = 0;
    gint active_index;
    gchar *info, *cmd, *new_name;
    gchar *sysinit_script_path, *sysinit_start_script;
    gchar *conf_data=NULL, *openvpn_client_conf=NULL;
    gchar *pass_file, *pass_lines;
    // Use later if the OpenVPN server begins using encrypted passwords: const char *encrypted_pass;

    gchar *firestarter_start, *firestarter_stop;
    gchar *non_firestarter_start, *non_firestarter_stop;
    gchar *share_tunnel_with_lan, *start_at_boot_label;

    /* Entries */
    G_CONST_RETURN gchar *connection_name;
    G_CONST_RETURN gchar *server_address;
    G_CONST_RETURN gchar *user;
    G_CONST_RETURN gchar *pass;
    G_CONST_RETURN gchar *proxy_address;

    /* Spin buttons */
    G_CONST_RETURN gchar *server_port;
    G_CONST_RETURN gchar *log_level;
    G_CONST_RETURN gchar *proxy_port;

    /* Combos */
    gchar *proto=NULL, *tap_dev=NULL, *auth_line=NULL;
    gchar *cipher=NULL, *compression=NULL, *proxy_line=NULL;

    /* Entries */
    connection_name = gtk_entry_get_text(GTK_ENTRY(widgets->client_set_entry[0]));
    server_address  = gtk_entry_get_text(GTK_ENTRY(widgets->client_set_entry[1]));
    user  = gtk_entry_get_text(GTK_ENTRY(widgets->client_set_entry[2]));
    pass  = gtk_entry_get_text(GTK_ENTRY(widgets->client_set_entry[3]));
    proxy_address = gtk_entry_get_text(GTK_ENTRY(widgets->client_set_entry[4]));

    /* Strip newline chars at the end of the connection name */
    if( selected_connection == NULL || strlen(selected_connection) < 3
    ||  connection_name     == NULL || strlen(connection_name)     < 3 )
    {
      printf("The connection name is too short.\n");
      return;
    }

    new_name = g_strdup_printf("%s", connection_name);

    /* Check that the specified connection name is valid. */
    for(i=0; new_name[i]!='\0'; i++)
    {
      /* Change spaces to "-" chars */
      if( new_name[i]==' ' )
          new_name[i]='-';

      if( new_name[i]=='\n'
      ||  new_name[i]=='\r'
      ||  new_name[i]=='\t' )
      {
          printf("The specified connection name contains invalid chars.\n");
          g_free(new_name);
          return;
      }
    }
    if( i < 3 )
    {
      printf("You must select a longer name for this connection.\n");
      g_free(new_name);
      return;
    }
    /* Check that the selected connection name is valid. */
    for(i=0; selected_connection[i]!='\0'; i++)
    {
      /* Change spaces to "-" chars */
      if( selected_connection[i]==' ' )
          selected_connection[i]='-';

      if( selected_connection[i]=='\n'
      ||  selected_connection[i]=='\r'
      ||  selected_connection[i]=='\t' )
      {
          printf("The connection name contains invalid chars.\n");
          return;
      }
    }
    if( i < 3 )
    {
      printf("You must select a longer name for this connection.\n");
      return;
    }

    /* Check if the connection name has changed. If so, move it to the new directory. */
    if( strcmp((char *)selected_connection, (char *)new_name) !=0 )
    {
      cmd = g_strdup_printf("mv '%s/client/%s' '%s/client/%s'", OPENVPN_SYSCONF_DIR, selected_connection, OPENVPN_SYSCONF_DIR, new_name);
      if( ! run_command(cmd) )
      {
          printf("Error: could not run command:\n%s\n", cmd);
          g_free(cmd);
          g_free(new_name);
          return;
      }
      g_free(cmd);
    }

    /* Set this connection as the globally selected one */
    if( selected_connection!=NULL )
      g_free(selected_connection);
    selected_connection = g_strdup_printf("%s", new_name);

    g_free(new_name);

    /* Create this clients directory. */
    cmd = g_strdup_printf("mkdir -p '%s/client/%s'", OPENVPN_SYSCONF_DIR, selected_connection);
    if( ! run_command(cmd) )
    {
      printf("Error: could not run command:\n%s\n", cmd);
      g_free(cmd);
      return;
    }
    g_free(cmd);


    /* Remove all "Connection_selected" lines from all confs */
    remove_all_selected_lines();


    /* Spin buttons */
    server_port = gtk_entry_get_text(GTK_ENTRY(widgets->client_set_spinbutton[0]));
    log_level   = gtk_entry_get_text(GTK_ENTRY(widgets->client_set_spinbutton[1]));
    proxy_port  = gtk_entry_get_text(GTK_ENTRY(widgets->client_set_spinbutton[2]));


    /* Combos */

    /* Protocol */
    active_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widgets->client_set_combo[0]));
    if( active_index == 0 )
      proto = g_strdup_printf("proto tcp");
    else
      proto = g_strdup_printf("proto udp");

    /* Tap device */
    active_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widgets->client_set_combo[1]));
    if( active_index == 0 )
      tap_dev = g_strdup_printf("tap0");
    if( active_index == 1 )
      tap_dev = g_strdup_printf("tap1");
    if( active_index == 2 )
      tap_dev = g_strdup_printf("tap2");
    if( active_index == 3 )
      tap_dev = g_strdup_printf("tap3");

    /* Cipher */
    active_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widgets->client_set_combo[2]));
    if( active_index == 0 )
      cipher = g_strdup_printf("cipher BF-CBC\n");       /* BlowFish */
    if( active_index == 1 )
      cipher = g_strdup_printf("cipher AES-128-CBC\n");  /* AES 128 */
    if( active_index == 2 )
      cipher = g_strdup_printf("cipher AES-256-CBC\n");  /* AES 256 */
    if( active_index == 3 )
      cipher = g_strdup_printf("cipher DES-EDE3-CBC\n"); /* Triple-DES */



    /* Setup user authentication if the username entry contains a username. */
    if( user!=NULL && strlen(user) > 0 )
    {
        auth_line = g_strdup_printf("auth-user-pass %s/client/%s/passfile\n", OPENVPN_SYSCONF_DIR, selected_connection);

      /* Write the username and password to the passfile if the password entry contains a password */
      if( pass!=NULL && strlen(pass) > 5 )
      {
          /* Encrypt the password and write "UserName\nPassword\n" to the passfile */
          // OpenVPN server wants a non-encrypted password.
          // encrypted_pass = encrypt_password(pass);

          pass_file = g_strdup_printf("%s/client/%s/passfile", OPENVPN_SYSCONF_DIR, selected_connection);
          if((fp=fopen(pass_file, "w+"))==NULL)
          {
            info = g_strdup_printf(_("Can not write the password file: \n%s\n"), pass_file);
            show_info(info);
            g_free(info);
            g_free(pass_file);
            // Fixme... free stuff
            return;
          }
          pass_lines = g_strdup_printf("%s\n%s\n\n", user, pass);
          fputs(pass_lines, fp);
          fclose(fp);

          info = g_strdup_printf(_("A new username and password has been added.\n"));
          show_info(info);
          g_free(info);

          g_free(pass_file);
          g_free(pass_lines);
      }
    }
    else
      auth_line = g_strdup_printf("\n");


    /* Compression */
    active_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widgets->client_set_combo[3]));
    if( active_index == 0 )
      compression = g_strdup_printf("\n");
    else
      compression = g_strdup_printf("comp-lzo\n");


    /* Chroot is standard */


    /* Make Firestarter accept traffic on Tap interfaces if the user-pre firestarter file exists. */
    add_firestarter_user_pre();



    /* Share connection with LAN */
    active_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widgets->client_set_combo[4]));
    if( active_index == 0 )
    {
        share_tunnel_with_lan = g_strdup_printf("\n");
    }
    else
    {
      share_tunnel_with_lan = g_strconcat(
      IP_FORWARD_CMD_START, "\n",
      "# Needs fixing. Requires LAN addr and subnet mask. Not interfaced yet.\n",
      "echo \"iptables -t nat -A POSTROUTING -s LAN_ADDR/LAN_SUBN_MASK -o eth0 or tap0\"\n",
      NULL);
//    g_free(share_tunnel_with_lan);
    }

    /* Firestarter start and stop script parts if used. */
    active_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widgets->client_set_combo[5]));
    if( active_index == 1 )
    {
      firestarter_start = g_strconcat(
      "# Start Firestarter if its not running.\n",
      "if [ ! -e /var/lock/subsys/firestarter -o -e /var/lock/firestarter ]; then\n",
      "    ", FIRESTARTER_BINARY, " -s\n",
      "fi\n",
      NULL);

      firestarter_stop = g_strconcat(
      "# Stop Firestarter if its running.\n",
      "if [ -e /var/lock/subsys/firestarter -o -e /var/lock/firestarter ]; then\n",
      "    ", FIRESTARTER_BINARY, " -p\n",
      "fi\n",
      NULL);
      
      non_firestarter_start = g_strdup_printf("\n");
      non_firestarter_stop  = g_strdup_printf("\n");
    }
    else
    {
      /* Instead of firestarter configuring iptables, we do it. */

      /* Get the LAN network address. Snip at the last dot. */
/*
      lan_net_addr = g_strdup_printf("%s", lan_iface_address);
      for(i=strlen(lan_net_addr)-1; lan_net_addr[i]!='\0'; i--)
      if( lan_net_addr[i]=='.')
      {
          lan_net_addr[i+1]='0';
          lan_net_addr[i+2]='\0';
          break;
      }
*/

      non_firestarter_start = g_strconcat("",
      "# Run some iptable rules for the VPN-client.\n",
      "iptables -A INPUT  -i tap+ -j ACCEPT\n",
      "iptables -A OUTPUT -o tap+ -j ACCEPT\n",
      "iptables -A FORWARD -i tap+ -j ACCEPT\n",
      NULL);
//    share_tunnel_with_lan, Fixit, add above...
//    g_free(lan_net_addr);

      /* Disallow input and output on tap interface 
         Restart the network interface */
/*
      non_firestarter_stop = g_strconcat(
      "iptables -D INPUT  -i tap+ -j ACCEPT\n",
      "iptables -D OUTPUT -o tap+ -j ACCEPT\n",
// Not required   "ifdown ", lan_iface_name, "\n",
//    "ifup ", lan_iface_name, "\n",
      NULL);
*/
      /* Dont remove internet sharing and other, possibly vital stuff */
      firestarter_start = g_strdup_printf("\n");
      firestarter_stop  = g_strdup_printf("\n");
    }


    /* Start at boot */
    active_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widgets->client_set_combo[6]));
    if( active_index == 0 )
      start_at_boot_label = g_strdup_printf("\n");
    else
      start_at_boot_label = g_strdup_printf("# Client starts at boot\n");

    /* See if we should use a proxy. */
    if( proxy_address!=NULL && strlen(proxy_address) > 0 )
      proxy_line = g_strdup_printf("http-proxy-retry\nhttp-proxy %s %s\n", proxy_address, proxy_port);
    else
      proxy_line = g_strdup_printf("\n");



    /* Write the openvpn client configuration file:
       /etc/gadmin-openvpn/client/SITE/gadmin-openvpn-client.conf */
    openvpn_client_conf = g_strdup_printf("%s/client/%s/gadmin-openvpn-client.conf", OPENVPN_SYSCONF_DIR, selected_connection);
    if((fp=fopen(openvpn_client_conf, "w+"))==NULL)
    {
      info = g_strdup_printf(_("Can not write openvpn client configuration here: \n%s\n"), openvpn_client_conf);
      show_info(info);
      g_free(info);
      g_free(openvpn_client_conf);
      g_free(proto);
      g_free(tap_dev);
      g_free(auth_line);
      g_free(cipher);
      g_free(compression);
      g_free(proxy_line);
      g_free(firestarter_start);
      g_free(firestarter_stop);
      g_free(non_firestarter_start);
      g_free(start_at_boot_label);
//    g_free(non_firestarter_stop);
      g_free(share_tunnel_with_lan);
        return;
    }

    conf_data = g_strconcat("\n",
    "# Connection_name: ", selected_connection, "\n",
    "# Connection_selected\n",
    "client\n",
    "tls-client\n",
    "remote ", server_address, " ", server_port, "\n",
    proto, "\n",
    "dev ", tap_dev, "\n",
    "ca   certs/cacert.pem\n",
    "cert certs/cert.pem\n",
    "key  certs/key.pem\n",
    "dh   certs/dh.pem\n",
    "tls-auth certs/ta.key 1\n",
    auth_line,
    proxy_line,
    cipher,
    compression,
    "chroot ", OPENVPN_SYSCONF_DIR, "/client/", selected_connection, "\n",
    "user ", CLIENT_USER, "\n",
    "group ", CLIENT_GROUP, "\n",
    "persist-key\n",
    "persist-tun\n",
    "log    ", OPENVPN_SYSCONF_DIR, "/client/", selected_connection, "/openvpn-client.log\n",
    "status ", OPENVPN_SYSCONF_DIR, "/client/", selected_connection, "/openvpn-client-status.log\n",
    "verb ", log_level, "\n",
    "mute 20\n",
    NULL);

    fputs(conf_data, fp);
    fclose(fp);
    g_free(conf_data);
    g_free(openvpn_client_conf);


    g_free(proto);
    g_free(tap_dev);
    g_free(auth_line);
    g_free(proxy_line);
    g_free(cipher);
    g_free(compression);


    /* Write the sysinit script according to the settings */
    sysinit_start_script = g_strconcat(
    "#!/bin/bash\n",
    "#\n",
    "#\n",
    "# chkconfig: 2345 10 30\n",
    "#\n",
    "# processname: gadmin-openvpn-client\n",
    "# description: This shell script takes care of starting and stopping \\n",
    "# gadmin-openvpn-client on chkconfig-based systems.\n",
    "#\n",
    "### BEGIN INIT INFO\n",
    "# Provides: gadmin-openvpn-client\n",
    "# Required-Start: network NetworkManager\n",
    "# Required-Stop: NetworkManager\n",
    "# Default-Start: 2 3 4 5\n",
    "# Default-Stop: 0 1 6\n",
    "# Short-Description: start and stop gadmin-openvpn-client\n",
    "# Description: GAdmin-OpenVPN-Client starts and stops an OpenVPN client in Tap mode.\n",
    "### END INIT INFO\n",
    "\n",
    start_at_boot_label,
    "\n",
    "\n",
//    "lan_eth=\"", lan_iface_name, "\"\n",
//    "lan_eth_ip=\"", lan_iface_address, "\"\n",
//    "lan_eth_netmask=\"", lan_subnet_mask, "\"\n",
//    "lan_eth_broadcast=\"", lan_broadcast_address, "\"\n",
//    "\n",
    "\n",
    "case \"$1\" in\n",
    "       start)\n",
    "\n",
    firestarter_stop,
    "\n",
    "modprobe tun\n",
    "\n",
    "openvpn --daemon --writepid /var/run/openvpn/openvpn-client.pid \\\n",
    "--config ", OPENVPN_SYSCONF_DIR, "/client/", selected_connection, "/gadmin-openvpn-client.conf \\\n",
    "--cd ", OPENVPN_SYSCONF_DIR, "/client/", selected_connection, "\n",
    "\n",
    firestarter_start,
    non_firestarter_start,
    share_tunnel_with_lan,
    ";;\n",
    "\n",
    "       stop)\n",
    "\n",
// Use: kill cat pid here 
    "killall -9 openvpn\n",
    "\n",
//    non_firestarter_stop,
    "\n",
    ";;\n",
    "       *)\n",
    "echo \"usage gadmin-openvpn-client {start|stop}\"\n",
    "exit 1\n",
    ";;\n",
    "esac\n",
    "\n",
    "exit 0\n",
    "\n",
    NULL);

    g_free(firestarter_start);
    g_free(firestarter_stop);
    g_free(non_firestarter_start);
//    g_free(non_firestarter_stop);
    g_free(start_at_boot_label);
    g_free(share_tunnel_with_lan);


    /* Put the script with the others as: /etc/rc.d/init.d/gadmin-openvpn-client  */
    sysinit_script_path = g_strdup_printf("%s/gadmin-openvpn-client", SYSINIT_SCRIPTS_DIR);
    if((fp=fopen(sysinit_script_path, "w+"))==NULL)
    {
      info = g_strdup_printf(_("Can not write openvpn client sysinit script here: \n%s\n"), sysinit_script_path);
      show_info(info);
      g_free(info);
      g_free(sysinit_start_script);
      g_free(sysinit_script_path);
        return;
    }
    fputs(sysinit_start_script, fp);
    fclose(fp);

    g_free(sysinit_start_script);

    /* Chmod the script to 755 */
    cmd = g_strdup_printf("chmod 755 %s", sysinit_script_path);
    if( ! run_command(cmd) )
    {
      printf("Show popup, error chmodding sysinit script.\n");
    }
    g_free(cmd);

    g_free(sysinit_script_path);


    /* Populate the client settings */
    populate_connections(widgets);

    populate_client_settings(widgets);

    /* Populate the configuration tab */
    populate_conf_tab(widgets);
}

Generated by  Doxygen 1.6.0   Back to index