<commit_before>#!/usr/bin/env python3
#
# Copyright (C) 2018 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# 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, see <http://www.gnu.org/licenses/>.
#
#
#### TODO:
# preshared key
####

import sys
import os
import re
import syslog as sl
import subprocess

from vyos.config import Config
from vyos import ConfigError

dir = r'/config/auth/wireguard'
pk  = dir + '/private.key'
pub = dir + '/public.key'

def check_kmod():
  if not os.path.exists('/sys/module/wireguard'):
    sl.syslog(sl.LOG_NOTICE, "loading wirguard kmod") 
    if  os.system('sudo modprobe wireguard') != 0:
      sl.syslog(sl.LOG_NOTICE, "modprobe wireguard failed")
      raise ConfigError("modprobe wireguard failed")

def get_config():
  c = Config()
  if not c.exists('interfaces wireguard'):
    return None

  c.set_level('interfaces')
  intfcs = c.list_nodes('wireguard')
  intfcs_eff = c.list_effective_nodes('wireguard')
  new_lst = list( set(intfcs) - set(intfcs_eff) )
  del_lst = list( set(intfcs_eff) - set(intfcs) )

  config_data = {
    'interfaces' : {}
  }
  ### setting defaults and determine status of the config 
  for intfc in intfcs:
    cnf = 'wireguard ' + intfc
    # default data struct
    config_data['interfaces'].update (
      {
        intfc : {
          'addr'        : '',
          'descr'       : intfc, ## snmp ifAlias
          'lport'       : '',
          'status'      : 'exists',
          'state'       : 'enabled',
          'mtu'         : '1420',
          'peer'        : {}
          }
        }
    ) 
  
  ### determine status either delete or create
  for i in new_lst:
    config_data['interfaces'][i]['status'] = 'create' 

  for i in del_lst:
    config_data['interfaces'].update (
      {
        i : {
          'status': 'delete'
        }
      }
    )

  ### based on the status, setup conf values
  for intfc in intfcs:
    cnf = 'wireguard ' + intfc
    if config_data['interfaces'][intfc]['status'] != 'delete':
      ### addresses
      if c.exists(cnf + ' address'):
        config_data['interfaces'][intfc]['addr'] = c.return_values(cnf + ' address')
      ### listen port
      if c.exists(cnf + ' listen-port'):
        config_data['interfaces'][intfc]['lport'] = c.return_value(cnf + ' listen-port')
      ### description
      if c.exists(cnf + ' description'):
        config_data['interfaces'][intfc]['descr'] = c.return_value(cnf + ' description')
      ### mtu
      if c.exists(cnf + ' mtu'):
        config_data['interfaces'][intfc]['mtu'] = c.return_value(cnf + ' mtu')
      ### peers
      if c.exists(cnf + ' peer'):
        for p in c.list_nodes(cnf + ' peer'):
          config_data['interfaces'][intfc]['peer'].update  (
            {
              p : {
                'allowed-ips' : [],
                'endpoint'  : '',
                'pubkey'  : ''
              }
            }
          )
          if c.exists(cnf + ' peer ' + p + ' pubkey'):
            config_data['interfaces'][intfc]['peer'][p]['pubkey'] = c.return_value(cnf + ' peer ' + p + ' pubkey')
          if c.exists(cnf + ' peer ' + p + ' allowed-ips'):
            config_data['interfaces'][intfc]['peer'][p]['allowed-ips'] = c.return_values(cnf + ' peer ' + p + ' allowed-ips')
          if c.exists(cnf + ' peer ' + p + ' endpoint'):
            config_data['interfaces'][intfc]['peer'][p]['endpoint'] = c.return_value(cnf + ' peer ' + p + ' endpoint')
          if c.exists(cnf + ' peer ' + p + ' persistent-keepalive'):
            config_data['interfaces'][intfc]['peer'][p]['persistent-keepalive'] = c.return_value(cnf + ' peer ' + p + ' persistent-keepalive')

  return config_data

def verify(c):
  if not c:
    return None

  for i in c['interfaces']:
    if c['interfaces'][i]['status'] != 'delete':
      if not c['interfaces'][i]['addr']:
        raise ConfigError("address required for interface " + i) 
      if not c['interfaces'][i]['peer']:
        raise ConfigError("peer required on interface " + i)
      else:
        for p in c['interfaces'][i]['peer']:
          if not c['interfaces'][i]['peer'][p]['allowed-ips']:
            raise ConfigError("allowed-ips required on interface " + i + " for peer " + p)
          if not c['interfaces'][i]['peer'][p]['pubkey']:
            raise ConfigError("pubkey from your peer is mandatory on " + i + " for peer " + p)

    ### endpoint needs to be IP:port, mabey verify it here, but consider IPv6 in the pattern

def apply(c):
  ### no wg config left, delete all wireguard devices on the os
  if not c:
    net_devs = os.listdir('/sys/class/net/')
    for dev in net_devs:
      buf = open('/sys/class/net/' + dev + '/uevent','r').read()
      if re.search("DEVTYPE=wireguard", buf, re.I|re.M):
        wg_intf = re.sub("INTERFACE=","", re.search("INTERFACE=.*", buf, re.I|re.M).group(0) ) <commit_msg>T791: endpoint pattern doesn't need to be checked, wg returns an error message if it's not IP:port<commit_after>#!/usr/bin/env python3
#
# Copyright (C) 2018 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# 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, see <http://www.gnu.org/licenses/>.
#
#
#### TODO:
# preshared key
####

import sys
import os
import re
import syslog as sl
import subprocess

from vyos.config import Config
from vyos import ConfigError

dir = r'/config/auth/wireguard'
pk  = dir + '/private.key'
pub = dir + '/public.key'

def check_kmod():
  if not os.path.exists('/sys/module/wireguard'):
    sl.syslog(sl.LOG_NOTICE, "loading wirguard kmod") 
    if  os.system('sudo modprobe wireguard') != 0:
      sl.syslog(sl.LOG_NOTICE, "modprobe wireguard failed")
      raise ConfigError("modprobe wireguard failed")

def get_config():
  c = Config()
  if not c.exists('interfaces wireguard'):
    return None

  c.set_level('interfaces')
  intfcs = c.list_nodes('wireguard')
  intfcs_eff = c.list_effective_nodes('wireguard')
  new_lst = list( set(intfcs) - set(intfcs_eff) )
  del_lst = list( set(intfcs_eff) - set(intfcs) )

  config_data = {
    'interfaces' : {}
  }
  ### setting defaults and determine status of the config 
  for intfc in intfcs:
    cnf = 'wireguard ' + intfc
    # default data struct
    config_data['interfaces'].update (
      {
        intfc : {
          'addr'        : '',
          'descr'       : intfc, ## snmp ifAlias
          'lport'       : '',
          'status'      : 'exists',
          'state'       : 'enabled',
          'mtu'         : '1420',
          'peer'        : {}
          }
        }
    ) 
  
  ### determine status either delete or create
  for i in new_lst:
    config_data['interfaces'][i]['status'] = 'create' 

  for i in del_lst:
    config_data['interfaces'].update (
      {
        i : {
          'status': 'delete'
        }
      }
    )

  ### based on the status, setup conf values
  for intfc in intfcs:
    cnf = 'wireguard ' + intfc
    if config_data['interfaces'][intfc]['status'] != 'delete':
      ### addresses
      if c.exists(cnf + ' address'):
        config_data['interfaces'][intfc]['addr'] = c.return_values(cnf + ' address')
      ### listen port
      if c.exists(cnf + ' listen-port'):
        config_data['interfaces'][intfc]['lport'] = c.return_value(cnf + ' listen-port')
      ### description
      if c.exists(cnf + ' description'):
        config_data['interfaces'][intfc]['descr'] = c.return_value(cnf + ' description')
      ### mtu
      if c.exists(cnf + ' mtu'):
        config_data['interfaces'][intfc]['mtu'] = c.return_value(cnf + ' mtu')
      ### peers
      if c.exists(cnf + ' peer'):
        for p in c.list_nodes(cnf + ' peer'):
          config_data['interfaces'][intfc]['peer'].update  (
            {
              p : {
                'allowed-ips' : [],
                'endpoint'  : '',
                'pubkey'  : ''
              }
            }
          )
          if c.exists(cnf + ' peer ' + p + ' pubkey'):
            config_data['interfaces'][intfc]['peer'][p]['pubkey'] = c.return_value(cnf + ' peer ' + p + ' pubkey')
          if c.exists(cnf + ' peer ' + p + ' allowed-ips'):
            config_data['interfaces'][intfc]['peer'][p]['allowed-ips'] = c.return_values(cnf + ' peer ' + p + ' allowed-ips')
          if c.exists(cnf + ' peer ' + p + ' endpoint'):
            config_data['interfaces'][intfc]['peer'][p]['endpoint'] = c.return_value(cnf + ' peer ' + p + ' endpoint')
          if c.exists(cnf + ' peer ' + p + ' persistent-keepalive'):
            config_data['interfaces'][intfc]['peer'][p]['persistent-keepalive'] = c.return_value(cnf + ' peer ' + p + ' persistent-keepalive')

  return config_data

def verify(c):
  if not c:
    return None

  for i in c['interfaces']:
    if c['interfaces'][i]['status'] != 'delete':
      if not c['interfaces'][i]['addr']:
        raise ConfigError("address required for interface " + i) 
      if not c['interfaces'][i]['peer']:
        raise ConfigError("peer required on interface " + i)

      for p in c['interfaces'][i]['peer']:
        if not c['interfaces'][i]['peer'][p]['allowed-ips']:
          raise ConfigError("allowed-ips required on interface " + i + " for peer " + p)
        if not c['interfaces'][i]['peer'][p]['pubkey']:
          raise ConfigError("pubkey from your peer is mandatory on " + i + " for peer " + p)


def apply(c):
  ### no wg config left, delete all wireguard devices on the os
  if not c:
    net_devs = os.listdir('/sys/class/net/')
    for dev in net_devs:
      buf = open('/sys/class/net/' + dev + '/uevent','r').read()
      if re.search("DEVTYPE=wireguard", buf, re.I|re.M):
        wg_intf = re.sub("INTERFACE=","", re.search("INTERFACE=.*", buf, re.I|re.M).group(0) ) 
{'fraction_non_alphanumeric': 0.15315060751624754, 'fraction_numerical': 0.0026372798342281247, 'mean_word_length': 2.593231810490694, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6857192', 'n_tokens_mistral': 3409, 'n_tokens_neox': 3382, 'n_words': 892}