mirror of
				https://github.com/billz/raspap-webgui.git
				synced 2025-03-01 10:31:47 +00:00 
			
		
		
		
	Merge pull request #45 from RaspAP/feature/wg-extended
Extend WG functionality
This commit is contained in:
		| @@ -307,7 +307,6 @@ $('#ovpn-confirm-activate').on('shown.bs.modal', function (e) { | ||||
| }); | ||||
|  | ||||
| $('#ovpn-userpw,#ovpn-certs').on('click', function (e) { | ||||
| //    e.stopPropagation(); | ||||
|     if (this.id == 'ovpn-userpw') { | ||||
|         $('#PanelCerts').hide(); | ||||
|         $('#PanelUserPW').show(); | ||||
| @@ -317,6 +316,20 @@ $('#ovpn-userpw,#ovpn-certs').on('click', function (e) { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| $(document).ready(function(){ | ||||
|   $("#PanelManual").hide(); | ||||
| }); | ||||
|  | ||||
| $('#wg-upload,#wg-manual').on('click', function (e) { | ||||
|     if (this.id == 'wg-upload') { | ||||
|         $('#PanelManual').hide(); | ||||
|         $('#PanelUpload').show(); | ||||
|     } else if (this.id == 'wg-manual') { | ||||
|         $('#PanelUpload').hide(); | ||||
|         $('#PanelManual').show(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| // Add the following code if you want the name of the file appear on select | ||||
| $(".custom-file-input").on("change", function() { | ||||
|   var fileName = $(this).val().split("\\").pop(); | ||||
|   | ||||
							
								
								
									
										505
									
								
								app/lib/uploader.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										505
									
								
								app/lib/uploader.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,505 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Simple PHP upload class | ||||
|  * | ||||
|  * Adapted from aivis/PHP-file-upload-class | ||||
|  * | ||||
|  * @description File upload class for RaspAP | ||||
|  * @author      Bill Zimmerman <billzimmerman@gmail.com> | ||||
|  * @author      Aivis Silins | ||||
|  * @link        https://github.com/aivis/PHP-file-upload-class | ||||
|  * @license     https://github.com/raspap/raspap-webgui/blob/master/LICENSE | ||||
|  */ | ||||
|  | ||||
| namespace RaspAP\Uploader; | ||||
|  | ||||
| class Upload | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Default directory persmissions (destination) | ||||
|      */ | ||||
|     protected $default_permissions = 0750; | ||||
|  | ||||
|     /** | ||||
|      * File post array | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $file_post = array(); | ||||
|  | ||||
|     /** | ||||
|      * Destination directory | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $destination; | ||||
|  | ||||
|     /** | ||||
|      * Fileinfo | ||||
|      * | ||||
|      * @var object | ||||
|      */ | ||||
|     protected $finfo; | ||||
|  | ||||
|     /** | ||||
|      * Data about file | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     public $file = array(); | ||||
|  | ||||
|     /** | ||||
|      * Max. file size | ||||
|      * | ||||
|      * @var int | ||||
|      */ | ||||
|     protected $max_file_size; | ||||
|  | ||||
|     /** | ||||
|      * Allowed mime types | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $mimes = array(); | ||||
|  | ||||
|     /** | ||||
|      * Temp path | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $tmp_name; | ||||
|  | ||||
|     /** | ||||
|      * Validation errors | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $validation_errors = array(); | ||||
|  | ||||
|     /** | ||||
|      * Filename (new) | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $filename; | ||||
|  | ||||
|     /** | ||||
|      * Internal callbacks (filesize check, mime, etc) | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     private $callbacks = array(); | ||||
|  | ||||
|     /** | ||||
|      * Root dir | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $root; | ||||
|  | ||||
|     /** | ||||
|      * Return upload object | ||||
|      * | ||||
|      * $destination    = 'path/to/file/destination/'; | ||||
|      * | ||||
|      * @param  string $destination | ||||
|      * @param  string $root | ||||
|      * @return Upload | ||||
|      */ | ||||
|     public static function factory($destination, $root = false) | ||||
|     { | ||||
|         return new Upload($destination, $root); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      *  Define root constant and set & create destination path | ||||
|      * | ||||
|      * @param string $destination | ||||
|      * @param string $root | ||||
|      */ | ||||
|     public function __construct($destination, $root = false) | ||||
|     { | ||||
|         if ($root) { | ||||
|             $this->root = $root; | ||||
|         } else { | ||||
|             $this->root = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR; | ||||
|         } | ||||
|  | ||||
|         // set & create destination path | ||||
|         if (!$this->set_destination($destination)) { | ||||
|             throw new Exception('Upload: Unable to create destination. '.$this->root . $this->destination); | ||||
|         } | ||||
|         //create finfo object | ||||
|         $this->finfo = new \finfo(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set target filename | ||||
|      * | ||||
|      * @param string $filename | ||||
|      */ | ||||
|     public function set_filename($filename) | ||||
|     { | ||||
|         $this->filename = $filename; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check & Save file | ||||
|      * | ||||
|      * Return data about current upload | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function upload($filename = false) | ||||
|     { | ||||
|         if($filename ) { | ||||
|             $this->set_filename($filename); | ||||
|         } | ||||
|  | ||||
|         $this->set_filename($filename); | ||||
|          | ||||
|         if ($this->check()) { | ||||
|             $this->save(); | ||||
|         } | ||||
|  | ||||
|         // return state data | ||||
|         return $this->get_state(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Save file on server | ||||
|      * Return state data | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function save() | ||||
|     { | ||||
|         $this->save_file(); | ||||
|         return $this->get_state(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Validate file (execute callbacks) | ||||
|      * Returns TRUE if validation successful | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function check() | ||||
|     { | ||||
|         //execute callbacks (check filesize, mime, also external callbacks | ||||
|         $this->validate(); | ||||
|  | ||||
|         //add error messages | ||||
|         $this->file['errors'] = $this->get_errors(); | ||||
|  | ||||
|         //change file validation status | ||||
|         $this->file['status'] = empty($this->validation_errors); | ||||
|  | ||||
|         return $this->file['status']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get current state data | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function get_state() | ||||
|     { | ||||
|         return $this->file; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Save file on server | ||||
|      */ | ||||
|     protected function save_file() | ||||
|     { | ||||
|         //create & set new filename | ||||
|         if(empty($this->filename)) { | ||||
|             $this->create_new_filename(); | ||||
|         } | ||||
|  | ||||
|         //set filename | ||||
|         $this->file['filename'] = $this->filename; | ||||
|  | ||||
|         //set full path | ||||
|         $this->file['full_path'] = $this->root . $this->destination . $this->filename; | ||||
|             $this->file['path'] = $this->destination . $this->filename; | ||||
|  | ||||
|         $status = move_uploaded_file($this->tmp_name, $this->file['full_path']); | ||||
|  | ||||
|         //checks whether upload successful | ||||
|         if (!$status) { | ||||
|             throw new Exception('Upload: Failed to upload file.'); | ||||
|         } | ||||
|  | ||||
|         //done | ||||
|         $this->file['status'] = true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set data about file | ||||
|      */ | ||||
|     protected function set_file_data() | ||||
|     { | ||||
|         $file_size = $this->get_file_size(); | ||||
|         $this->file = array( | ||||
|         'status'            => false, | ||||
|         'destination'       => $this->destination, | ||||
|         'size_in_bytes'     => $file_size, | ||||
|         'size_in_mb'        => $this->bytes_to_mb($file_size), | ||||
|         'mime'              => $this->get_file_mime(), | ||||
|         'filename'          => $this->file_post['name'], | ||||
|         'tmp_name'          => $this->file_post['tmp_name'], | ||||
|         'post_data'         => $this->file_post, | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set validation error | ||||
|      * | ||||
|      * @param string $message | ||||
|      */ | ||||
|     public function set_error($message) | ||||
|     { | ||||
|         $this->validation_errors[] = $message; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Return validation errors | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function get_errors() | ||||
|     { | ||||
|         return $this->validation_errors; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set external callback methods | ||||
|      * | ||||
|      * @param object $instance_of_callback_object | ||||
|      * @param array  $callback_methods | ||||
|      */ | ||||
|     public function callbacks($instance_of_callback_object, $callback_methods) | ||||
|     { | ||||
|         if (empty($instance_of_callback_object)) { | ||||
|             throw new Exception('Upload: $instance_of_callback_object cannot be empty.'); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         if (!is_array($callback_methods)) { | ||||
|             throw new Exception('Upload: $callback_methods data type need to be array.'); | ||||
|         } | ||||
|  | ||||
|         $this->external_callback_object = $instance_of_callback_object; | ||||
|         $this->external_callback_methods = $callback_methods; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute callbacks | ||||
|      */ | ||||
|     protected function validate() | ||||
|     { | ||||
|         //get curent errors | ||||
|         $errors = $this->get_errors(); | ||||
|  | ||||
|         if (empty($errors)) { | ||||
|  | ||||
|             //set data about current file | ||||
|             $this->set_file_data(); | ||||
|  | ||||
|             //execute internal callbacks | ||||
|             $this->execute_callbacks($this->callbacks, $this); | ||||
|  | ||||
|             //execute external callbacks | ||||
|             $this->execute_callbacks($this->external_callback_methods, $this->external_callback_object); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute callbacks | ||||
|      */ | ||||
|     protected function execute_callbacks($callbacks, $object) | ||||
|     { | ||||
|         foreach($callbacks as $method) { | ||||
|             $object->$method($this); | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * File mime type validation callback | ||||
|      * | ||||
|      * @param object $object | ||||
|      */ | ||||
|     protected function check_mime_type($object) | ||||
|     { | ||||
|         if (!empty($object->mimes)) { | ||||
|             if (!in_array($object->file['mime'], $object->mimes)) { | ||||
|                 $object->set_error('Mime type not allowed.'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set allowed mime types | ||||
|      * | ||||
|      * @param array $mimes | ||||
|      */ | ||||
|     public function set_allowed_mime_types($mimes) | ||||
|     { | ||||
|         $this->mimes        = $mimes; | ||||
|         //if mime types is set -> set callback | ||||
|         $this->callbacks[]    = 'check_mime_type'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * File size validation callback | ||||
|      * | ||||
|      * @param object $object | ||||
|      */ | ||||
|     protected function check_file_size($object) | ||||
|     { | ||||
|         if (!empty($object->max_file_size)) { | ||||
|             $file_size_in_mb = $this->bytes_to_mb($object->file['size_in_bytes']); | ||||
|             if ($object->max_file_size <= $file_size_in_mb) { | ||||
|                 $object->set_error('File exceeds maximum allowed size.'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set max file size | ||||
|      * | ||||
|      * @param int $size | ||||
|      */ | ||||
|     public function set_max_file_size($size) | ||||
|     { | ||||
|         $this->max_file_size = $size; | ||||
|          | ||||
|         //if max file size is set -> set callback | ||||
|         $this->callbacks[] = 'check_file_size'; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set File array to object | ||||
|      * | ||||
|      * @param array $file | ||||
|      */ | ||||
|     public function file($file) | ||||
|     { | ||||
|         $this->set_file_array($file); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set file array | ||||
|      * | ||||
|      * @param array $file | ||||
|      */ | ||||
|     protected function set_file_array($file) | ||||
|     { | ||||
|         //checks whether file array is valid | ||||
|         if (!$this->check_file_array($file)) { | ||||
|             //file not selected or some bigger problems (broken files array) | ||||
|             $this->set_error('Please select file.'); | ||||
|         } | ||||
|  | ||||
|         //set file data | ||||
|         $this->file_post = $file; | ||||
|  | ||||
|         //set tmp path | ||||
|         $this->tmp_name  = $file['tmp_name']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Checks whether Files post array is valid | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function check_file_array($file) | ||||
|     { | ||||
|         return isset($file['error']) | ||||
|         && !empty($file['name']) | ||||
|         && !empty($file['type']) | ||||
|         && !empty($file['tmp_name']) | ||||
|         && !empty($file['size']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get file mime type | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function get_file_mime() | ||||
|     { | ||||
|         return $this->finfo->file($this->tmp_name, FILEINFO_MIME_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get file size | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     protected function get_file_size() | ||||
|     { | ||||
|         return filesize($this->tmp_name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set destination path (return TRUE on success) | ||||
|      * | ||||
|      * @param  string $destination | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function set_destination($destination) | ||||
|     { | ||||
|         $this->destination = $destination . DIRECTORY_SEPARATOR; | ||||
|         return $this->destination_exist() ? true : $this->create_destination(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Checks whether destination folder exists | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function destination_exist() | ||||
|     { | ||||
|         return is_writable($this->root . $this->destination); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create path to destination | ||||
|      * | ||||
|      * @param  string $dir | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function create_destination() | ||||
|     { | ||||
|         return mkdir($this->root . $this->destination, $this->default_permissions, true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set unique filename | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function create_new_filename() | ||||
|     { | ||||
|         $filename = sha1(mt_rand(1, 9999) . $this->destination . uniqid()) . time(); | ||||
|         $this->set_filename($filename); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Convert bytes to MB | ||||
|      * | ||||
|      * @param  int $bytes | ||||
|      * @return int | ||||
|      */ | ||||
|     protected function bytes_to_mb($bytes) | ||||
|     { | ||||
|         return round(($bytes / 1048576), 2); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -721,13 +721,15 @@ function validateCidr($cidr) | ||||
| }     | ||||
|  | ||||
| // Validates a host or FQDN | ||||
| function validate_host($host) { | ||||
| function validate_host($host) | ||||
| { | ||||
|   return preg_match('/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i', $host); | ||||
| } | ||||
|  | ||||
| // Gets night mode toggle value | ||||
| // @return boolean | ||||
| function getNightmode(){ | ||||
| function getNightmode() | ||||
| { | ||||
|     if ($_COOKIE['theme'] == 'lightsout.css') { | ||||
|         return true; | ||||
|     } else { | ||||
| @@ -736,7 +738,8 @@ function getNightmode(){ | ||||
| }	 | ||||
| 	 | ||||
| // search array for matching string and return only first matching group | ||||
| function preg_only_match($pat,$haystack) { | ||||
| function preg_only_match($pat,$haystack) | ||||
| { | ||||
|   $match = ""; | ||||
|   if(!empty($haystack) && !empty($pat)) { | ||||
|     if(!is_array($haystack)) $haystack = array($haystack); | ||||
| @@ -754,10 +757,34 @@ function qr_encode($str) | ||||
|     return preg_replace('/(?<!\\\)([\":;,])/', '\\\\\1', $str); | ||||
| } | ||||
|  | ||||
| function evalHexSequence($string) { | ||||
| function evalHexSequence($string) | ||||
| { | ||||
|     $evaluator = function ($input) { | ||||
| 	return hex2bin($input[1]); | ||||
|     }; | ||||
|     return preg_replace_callback('/\\\x(..)/', $evaluator, $string); | ||||
| } | ||||
|  | ||||
| /* File upload callback object | ||||
|  * | ||||
|  */ | ||||
| class validation | ||||
| { | ||||
|     public function check_name_length($object) | ||||
|     { | ||||
|         if (strlen($object->file['filename']) > 255) { | ||||
|             $object->set_error('File name is too long.'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Resolves public IP address | ||||
|  * | ||||
|  * @return string $public_ip | ||||
|  */ | ||||
| function get_public_ip() | ||||
| { | ||||
|     exec('wget https://ipinfo.io/ip -qO -', $public_ip); | ||||
|     return $public_ip[0]; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| require_once 'includes/status_messages.php'; | ||||
| require_once 'includes/config.php'; | ||||
| require_once 'includes/wifi_functions.php'; | ||||
| require_once 'app/lib/uploader.php'; | ||||
|  | ||||
| getWifiInterface(); | ||||
|  | ||||
| @@ -41,11 +42,9 @@ function DisplayOpenVPNConfig() | ||||
|     } | ||||
|  | ||||
|     exec('pidof openvpn | wc -l', $openvpnstatus); | ||||
|     exec('wget https://ipinfo.io/ip -qO -', $return); | ||||
|  | ||||
|     $serviceStatus = $openvpnstatus[0] == 0 ? "down" : "up"; | ||||
|     $auth = file(RASPI_OPENVPN_CLIENT_LOGIN, FILE_IGNORE_NEW_LINES); | ||||
|     $public_ip = $return[0]; | ||||
|     $public_ip = get_public_ip(); | ||||
|  | ||||
|     // parse client auth credentials | ||||
|     if (!empty($auth)) { | ||||
| @@ -100,8 +99,8 @@ function DisplayOpenVPNConfig() | ||||
|  */ | ||||
| function SaveOpenVPNConfig($status, $file, $authUser, $authPassword) | ||||
| { | ||||
|     $tmp_ovpnclient = '/tmp/ovpnclient.ovpn'; | ||||
|     $tmp_authdata = '/tmp/authdata'; | ||||
|     define('KB', 1024); | ||||
|     $tmp_destdir = '/tmp/'; | ||||
|     $auth_flag = 0; | ||||
|  | ||||
|     try { | ||||
| @@ -110,66 +109,28 @@ function SaveOpenVPNConfig($status, $file, $authUser, $authPassword) | ||||
|             throw new RuntimeException('Invalid parameters'); | ||||
|         } | ||||
|  | ||||
|         // Parse returned errors | ||||
|         switch ($file['error']) { | ||||
|         case UPLOAD_ERR_OK: | ||||
|             break; | ||||
|         case UPLOAD_ERR_NO_FILE: | ||||
|             throw new RuntimeException('OpenVPN configuration file not sent'); | ||||
|         case UPLOAD_ERR_INI_SIZE: | ||||
|         case UPLOAD_ERR_FORM_SIZE: | ||||
|             throw new RuntimeException('Exceeded filesize limit'); | ||||
|         default: | ||||
|             throw new RuntimeException('Unknown errors'); | ||||
|         } | ||||
|         $upload = \RaspAP\Uploader\Upload::factory('ovpn',$tmp_destdir); | ||||
|         $upload->set_max_file_size(64*KB); | ||||
|         $upload->set_allowed_mime_types(array('ovpn' => 'text/plain')); | ||||
|         $upload->file($file); | ||||
|  | ||||
|         // Validate extension | ||||
|         $ext = pathinfo($file['name'], PATHINFO_EXTENSION); | ||||
|         if ($ext != 'ovpn') { | ||||
|             throw new RuntimeException('Invalid file extension'); | ||||
|         } | ||||
|         $validation = new validation; | ||||
|         $upload->callbacks($validation, array('check_name_length')); | ||||
|         $results = $upload->upload(); | ||||
|  | ||||
|         // Validate MIME type | ||||
|         $finfo = new finfo(FILEINFO_MIME_TYPE); | ||||
|         if (false === $ext = array_search( | ||||
|             $finfo->file($file['tmp_name']), | ||||
|             array( | ||||
|                 'ovpn' => 'text/plain' | ||||
|             ), | ||||
|             true | ||||
|         ) | ||||
|         ) { | ||||
|             throw new RuntimeException('Invalid file format'); | ||||
|         } | ||||
|  | ||||
|         // Validate filesize | ||||
|         define('KB', 1024); | ||||
|         if ($file['size'] > 64*KB) { | ||||
|             throw new RuntimeException('File size limit exceeded'); | ||||
|         } | ||||
|  | ||||
|         // Use safe filename, save to /tmp | ||||
|         if (!move_uploaded_file( | ||||
|             $file['tmp_name'], | ||||
|             sprintf( | ||||
|                 '/tmp/%s.%s', | ||||
|                 'ovpnclient', | ||||
|                 $ext | ||||
|             ) | ||||
|         ) | ||||
|         ) { | ||||
|             throw new RuntimeException('Unable to move uploaded file'); | ||||
|         if (!empty($results['errors'])) { | ||||
|             throw new RuntimeException($results['errors'][0]); | ||||
|         } | ||||
|  | ||||
|         // Good file upload, update auth credentials if present | ||||
|         if (!empty($authUser) && !empty($authPassword)) { | ||||
|             $auth_flag = 1; | ||||
|             // Move tmp authdata to /etc/openvpn/login.conf | ||||
|             $auth.= $authUser .PHP_EOL . $authPassword .PHP_EOL; | ||||
|             $tmp_authdata = $tmp_destdir .'ovpn/authdata'; | ||||
|             $auth = $authUser .PHP_EOL . $authPassword .PHP_EOL; | ||||
|             file_put_contents($tmp_authdata, $auth); | ||||
|             chmod($tmp_authdata, 0644); | ||||
|             $client_auth = RASPI_OPENVPN_CLIENT_PATH.pathinfo($file['name'], PATHINFO_FILENAME).'_login.conf'; | ||||
|             system("sudo cp $tmp_authdata $client_auth", $return); | ||||
|             system("sudo mv $tmp_authdata $client_auth", $return); | ||||
|             system("sudo rm ".RASPI_OPENVPN_CLIENT_LOGIN, $return); | ||||
|             system("sudo ln -s $client_auth ".RASPI_OPENVPN_CLIENT_LOGIN, $return); | ||||
|             if ($return !=0) { | ||||
| @@ -178,14 +139,16 @@ function SaveOpenVPNConfig($status, $file, $authUser, $authPassword) | ||||
|         } | ||||
|  | ||||
|         // Set iptables rules and, optionally, auth-user-pass | ||||
|         exec("sudo /etc/raspap/openvpn/configauth.sh $tmp_ovpnclient $auth_flag " .$_SESSION['ap_interface'], $return); | ||||
|         $tmp_ovpn = $results['full_path']; | ||||
|         exec("sudo /etc/raspap/openvpn/configauth.sh $tmp_ovpn $auth_flag " .$_SESSION['ap_interface'], $return); | ||||
|         foreach ($return as $line) { | ||||
|             $status->addMessage($line, 'info'); | ||||
|         } | ||||
|  | ||||
|         // Move uploaded ovpn config from /tmp and create symlink | ||||
|         $client_ovpn = RASPI_OPENVPN_CLIENT_PATH.pathinfo($file['name'], PATHINFO_FILENAME).'_client.conf'; | ||||
|         chmod($tmp_ovpnclient, 0644); | ||||
|         system("sudo cp $tmp_ovpnclient $client_ovpn", $return); | ||||
|         chmod($tmp_ovpn, 0644); | ||||
|         system("sudo mv $tmp_ovpn $client_ovpn", $return); | ||||
|         system("sudo rm ".RASPI_OPENVPN_CLIENT_CONFIG, $return); | ||||
|         system("sudo ln -s $client_ovpn ".RASPI_OPENVPN_CLIENT_CONFIG, $return); | ||||
|  | ||||
| @@ -201,3 +164,4 @@ function SaveOpenVPNConfig($status, $file, $authUser, $authPassword) | ||||
|         return $status; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -10,8 +10,13 @@ function DisplayWireGuardConfig() | ||||
| { | ||||
|     $status = new StatusMessages(); | ||||
|     if (!RASPI_MONITOR_ENABLED) { | ||||
|         if (isset($_POST['savewgsettings'])) { | ||||
|         $optRules     = $_POST['wgRules']; | ||||
|         $optConf      = $_POST['wgCnfOpt']; | ||||
|         $optSrvEnable = $_POST['wgSrvEnable']; | ||||
|         if (isset($_POST['savewgsettings']) && $optConf == 'manual' && $optSrvEnable == 1 ) { | ||||
|             SaveWireGuardConfig($status); | ||||
|         } elseif (isset($_POST['savewgsettings']) && $optConf == 'upload' && is_uploaded_file($_FILES["wgFile"]["tmp_name"])) { | ||||
|             SaveWireGuardUpload($status, $_FILES['wgFile'], $optRules); | ||||
|         } elseif (isset($_POST['startwg'])) { | ||||
|             $status->addMessage('Attempting to start WireGuard', 'info'); | ||||
|             exec('sudo /bin/systemctl start wg-quick@wg0', $return); | ||||
| @@ -27,7 +32,7 @@ function DisplayWireGuardConfig() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // fetch wg config | ||||
|     // fetch server config | ||||
|     exec('sudo cat '. RASPI_WIREGUARD_CONFIG, $return); | ||||
|     $conf = ParseConfig($return); | ||||
|     $wg_srvpubkey = exec('sudo cat '. RASPI_WIREGUARD_PATH .'wg-server-public.key', $return); | ||||
| @@ -39,7 +44,7 @@ function DisplayWireGuardConfig() | ||||
|         $wg_senabled = true; | ||||
|     } | ||||
|  | ||||
|     // todo: iterate multiple peer configs | ||||
|     // fetch client config | ||||
|     exec('sudo cat '. RASPI_WIREGUARD_PATH.'client.conf', $preturn); | ||||
|     $conf = ParseConfig($preturn); | ||||
|     $wg_pipaddress = ($conf['Address'] == '') ? getDefaultNetValue('wireguard','peer','Address') : $conf['Address']; | ||||
| @@ -55,12 +60,15 @@ function DisplayWireGuardConfig() | ||||
|     exec('pidof wg-crypt-wg0 | wc -l', $wgstatus); | ||||
|     $serviceStatus = $wgstatus[0] == 0 ? "down" : "up"; | ||||
|     $wg_state = ($wgstatus[0] > 0); | ||||
|     $public_ip = get_public_ip(); | ||||
|  | ||||
|     echo renderTemplate( | ||||
|         "wireguard", compact( | ||||
|             "status", | ||||
|             "wg_state", | ||||
|             "serviceStatus", | ||||
|             "public_ip", | ||||
|             "optRules", | ||||
|             "wg_log", | ||||
|             "peer_id", | ||||
|             "wg_srvpubkey", | ||||
| @@ -79,6 +87,71 @@ function DisplayWireGuardConfig() | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates uploaded .conf file, adds iptables post-up and | ||||
|  * post-down rules. | ||||
|  * | ||||
|  * @param  object $status | ||||
|  * @param  object $file | ||||
|  * @param  boolean $optRules | ||||
|  * @return object $status | ||||
|  */ | ||||
| function SaveWireGuardUpload($status, $file, $optRules) | ||||
| { | ||||
|     define('KB', 1024); | ||||
|     $tmp_destdir = '/tmp/'; | ||||
|     $auth_flag = 0; | ||||
|  | ||||
|     try { | ||||
|         // If undefined or multiple files, treat as invalid | ||||
|         if (!isset($file['error']) || is_array($file['error'])) { | ||||
|             throw new RuntimeException('Invalid parameters'); | ||||
|         } | ||||
|  | ||||
|         $upload = \RaspAP\Uploader\Upload::factory('wg',$tmp_destdir); | ||||
|         $upload->set_max_file_size(64*KB); | ||||
|         $upload->set_allowed_mime_types(array('text/plain')); | ||||
|         $upload->file($file); | ||||
|  | ||||
|         $validation = new validation; | ||||
|         $upload->callbacks($validation, array('check_name_length')); | ||||
|         $results = $upload->upload(); | ||||
|  | ||||
|         if (!empty($results['errors'])) { | ||||
|             throw new RuntimeException($results['errors'][0]); | ||||
|         } | ||||
|  | ||||
|         // Valid upload, get file contents | ||||
|         $tmp_wgconfig = $results['full_path']; | ||||
|         $tmp_contents = file_get_contents($tmp_wgconfig); | ||||
|  | ||||
|         // Set iptables rules | ||||
|         if (isset($optRules) && !preg_match('/PostUp|PostDown/m',$tmp_contents)) { | ||||
|             $rules[] = 'PostUp = '.getDefaultNetValue('wireguard','server','PostUp'); | ||||
|             $rules[] = 'PostDown = '.getDefaultNetValue('wireguard','server','PostDown'); | ||||
|             $rules[] = ''; | ||||
|             $rules = join(PHP_EOL, $rules); | ||||
|             $rules = preg_replace('/wlan0/m', $_SESSION['ap_interface'], $rules); | ||||
|             $tmp_contents = preg_replace('/^\s*$/ms', $rules, $tmp_contents, 1); | ||||
|             file_put_contents($tmp_wgconfig, $tmp_contents); | ||||
|         } | ||||
|  | ||||
|         // Move processed file from tmp to destination | ||||
|         system("sudo mv $tmp_wgconfig ". RASPI_WIREGUARD_CONFIG, $return); | ||||
|  | ||||
|         if ($return ==0) { | ||||
|             $status->addMessage('WireGuard configuration uploaded successfully', 'info'); | ||||
|         } else { | ||||
|             $status->addMessage('Unable to save WireGuard configuration', 'danger'); | ||||
|         } | ||||
|         return $status; | ||||
|  | ||||
|     } catch (RuntimeException $e) { | ||||
|         $status->addMessage($e->getMessage(), 'danger'); | ||||
|         return $status; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validate user input, save wireguard configuration | ||||
|  * | ||||
|   | ||||
| @@ -20,8 +20,7 @@ www-data ALL=(ALL) NOPASSWD:/bin/systemctl start openvpn-client@client | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/systemctl enable openvpn-client@client | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/systemctl stop openvpn-client@client | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/systemctl disable openvpn-client@client | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/ovpnclient.ovpn /etc/openvpn/client/*.conf | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/authdata /etc/openvpn/client/*.conf | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/mv /tmp/ovpn/* /etc/openvpn/client/*.conf | ||||
| www-data ALL=(ALL) NOPASSWD:/usr/bin/ln -s /etc/openvpn/client/*.conf /etc/openvpn/client/*.conf | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/rm /etc/openvpn/client/*.conf | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dnsmasqdata /etc/dnsmasq.d/090_*.conf | ||||
| @@ -49,6 +48,7 @@ www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dnsmasqdata /etc/dnsmasq.d/090_adblock. | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/dnsmasq_custom /etc/raspap/adblock/custom.txt | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/wgdata /etc/wireguard/*.conf | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/mv /tmp/wg-*.key /etc/wireguard/wg-*.key | ||||
| www-data ALL=(ALL) NOPASSWD:/bin/mv /tmp/wg/* /etc/wireguard/*.conf | ||||
| www-data ALL=(ALL) NOPASSWD:/etc/raspap/adblock/update_blocklist.sh | ||||
| www-data ALL=(ALL) NOPASSWD:/usr/bin/socat - /dev/ttyUSB[0-9] | ||||
| www-data ALL=(ALL) NOPASSWD:/usr/local/sbin/onoff_huawei_hilink.sh * | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| @@ -1026,14 +1026,44 @@ msgstr "Invalid custom host found on line " | ||||
| msgid "Tunnel settings" | ||||
| msgstr "Tunnel settings" | ||||
|  | ||||
| msgid "Configuration Method" | ||||
| msgstr "Configuration Method" | ||||
|  | ||||
| msgid "Upload file" | ||||
| msgstr "Upload file" | ||||
|  | ||||
| msgid "Create manually" | ||||
| msgstr "Create manually" | ||||
|  | ||||
| msgid "Upload a WireGuard config" | ||||
| msgstr "Upload a WireGuard config" | ||||
|  | ||||
| msgid "This option uploads and installs an existing WireGuard <code>.conf</code> file on this device." | ||||
| msgstr "This option uploads and installs an existing WireGuard <code>.conf</code> file on this device." | ||||
|  | ||||
| msgid "Apply iptables rules for AP interface" | ||||
| msgstr "Apply iptables rules for AP interface" | ||||
|  | ||||
| msgid "Recommended if you wish to forward network traffic from the wg0 interface to clients connected on the AP interface." | ||||
| msgstr "Recommended if you wish to forward network traffic from the wg0 interface to clients connected on the AP interface." | ||||
|  | ||||
| msgid "This option adds <strong>iptables</strong> <code>Postup</code> and <code>PostDown</code> rules for the configured AP interface (%s)." | ||||
| msgstr "This option adds <strong>iptables</strong> <code>Postup</code> and <code>PostDown</code> rules for the configured AP interface (%s)." | ||||
|  | ||||
| msgid "Select WireGuard configuration file (.conf)" | ||||
| msgstr "Select WireGuard configuration file (.conf)" | ||||
|  | ||||
| msgid "Create a local WireGuard config" | ||||
| msgstr "Create a local WireGuard config" | ||||
|  | ||||
| msgid "Enable server" | ||||
| msgstr "Enable server" | ||||
|  | ||||
| msgid "Enable this option to encrypt traffic by creating a tunnel between RaspAP and configured peers." | ||||
| msgstr "Enable this option to encrypt traffic by creating a tunnel between RaspAP and configured peers." | ||||
| msgid "Enable this option to secure network traffic by creating an encrypted tunnel between RaspAP and configured peers." | ||||
| msgstr "Enable this option to secure network traffic by creating an encrypted tunnel between RaspAP and configured peers." | ||||
|  | ||||
| msgid "This option adds <code>wg0.conf</code> to the WireGuard configuration." | ||||
| msgstr "This option adds <code>wg0.conf</code> to the WireGuard configuration." | ||||
| msgid "This setting generates a new WireGuard <code>.conf</code> file on this device." | ||||
| msgstr "This setting generates a new WireGuard <code>.conf</code> file on this device." | ||||
|  | ||||
| msgid "Local public key" | ||||
| msgstr "Local public key" | ||||
|   | ||||
| @@ -3,53 +3,106 @@ | ||||
|   <div class="row"> | ||||
|     <div class="col-md-6"> | ||||
|       <h4 class="mt-3"><?php echo _("Tunnel settings"); ?></h4> | ||||
|         <div class="input-group"> | ||||
|           <div class="custom-control custom-switch"> | ||||
|             <input class="custom-control-input" id="server_enabled" type="checkbox" name="wg_senabled" value="1" <?php echo $wg_senabled ? ' checked="checked"' : "" ?> aria-describedby="server-description"> | ||||
|           <label class="custom-control-label" for="server_enabled"><?php echo _("Enable server") ?></label> | ||||
|         </div> | ||||
|         <p id="wg-description"> | ||||
|           <small><?php echo _("Enable this option to encrypt traffic by creating a tunnel between RaspAP and configured peers.") ?></small> | ||||
|           <small><?php echo _("This option adds <code>wg0.conf</code> to the WireGuard configuration.") ?></small> | ||||
|         </p> | ||||
|         </div> | ||||
|  | ||||
|         <div class="row"> | ||||
|           <div class="col-xs-3 col-sm-6"> | ||||
|             <label for="code"><?php echo _("Local public key"); ?></label> | ||||
|           </div> | ||||
|           <div class="input-group col-md-12 mb-3"> | ||||
|             <input type="text" class="form-control" name="wg-server" id="wg-srvpubkey" value="<?php echo htmlspecialchars($wg_srvpubkey, ENT_QUOTES); ?>" /> | ||||
|             <div class="input-group-append"> | ||||
|               <button class="btn btn-outline-secondary rounded-right wg-keygen" type="button"><i class="fas fa-magic"></i></button> | ||||
|               <span id="wg-server-pubkey-status" class="input-group-addon check-hidden ml-2 mt-1"><i class="fas fa-check"></i></span> | ||||
|             </div> | ||||
|         <div class="col-lg-12 mt-2"> | ||||
|           <div class="row mt-3 mb-2"> | ||||
|             <div class="info-item col-xs-3"><?php echo _("IPv4 Address"); ?></div> | ||||
|             <div class="info-value col-xs-3"><?php echo htmlspecialchars($public_ip, ENT_QUOTES); ?><a class="text-gray-500" href="https://ipapi.co/<?php echo($public_ip); ?>" target="_blank" rel="noopener noreferrer"><i class="fas fa-external-link-alt ml-2"></i></a></div> | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|         <div class="row"> | ||||
|           <div class="form-group col-xs-3 col-sm-3"> | ||||
|             <label for="code"><?php echo _("Local Port"); ?></label> | ||||
|             <input type="text" class="form-control" name="wg_srvport" value="<?php echo htmlspecialchars($wg_srvport, ENT_QUOTES); ?>" /> | ||||
|           </div> | ||||
|         <h5><?php echo _("Configuration Method"); ?></h5> | ||||
|         <div class="col-sm-12 mt-2 mb-2 form-check"> | ||||
|           <input class="form-check-input" id="wg-upload" name="wgCnfOpt" value="upload" data-toggle="" data-parent="#serversettings" data-target="#wgUpload" type="radio" checked> | ||||
|           <label class="form-check-label"><?php echo _("Upload file"); ?></label> | ||||
|         </div> | ||||
|         <div class="col-sm-12 mt-2 mb-2 form-check"> | ||||
|           <input class="form-check-input" id="wg-manual" name="wgCnfOpt" value="manual" data-toggle="" data-parent="#serversettings" data-target="#wgManual" type="radio"> | ||||
|           <label class="form-check-label"><?php echo _("Create manually"); ?></label> | ||||
|         </div> | ||||
|  | ||||
|         <div class="row"> | ||||
|           <div class="form-group col-md-6"> | ||||
|             <label for="code"><?php echo _("IP Address"); ?></label> | ||||
|             <input type="text" class="form-control" name="wg_srvipaddress" value="<?php echo htmlspecialchars($wg_srvipaddress, ENT_QUOTES); ?>" /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-sm-12 ml-2"> | ||||
|           <div class="panel-group" id="serversettings"> | ||||
|  | ||||
|         <div class="row"> | ||||
|           <div class="form-group col-md-6"> | ||||
|             <label for="code"><?php echo _("DNS"); ?></label> | ||||
|             <input type="text" class="form-control" name="wg_srvdns" value="<?php echo htmlspecialchars($wg_srvdns, ENT_QUOTES); ?>" /> | ||||
|           </div> | ||||
|         </div> | ||||
|             <div class="panel panel-default panel-collapse" id="PanelUpload"> | ||||
|               <div class="panel-heading"> | ||||
|                 <h5 class="panel-title"><?php echo _("Upload a WireGuard config"); ?></h5> | ||||
|                 <p id="wg-description"> | ||||
|                   <small><?php echo _("This option uploads and installs an existing WireGuard <code>.conf</code> file on this device.") ?></small> | ||||
|                 </p> | ||||
|               </div> | ||||
|               <div class="panel-body"> | ||||
|  | ||||
|                 <div class="form-group col-sm-12"> | ||||
|                   <div class="custom-control custom-switch"> | ||||
|                     <?php $checked = $optRules == 1 ? 'checked="checked"' : '' ?> | ||||
|                     <input class="custom-control-input" id="chxwgrules" name="wgRules" type="checkbox" value="1" <?php echo $checked ?> /> | ||||
|                     <label class="custom-control-label" for="chxwgrules"><?php echo _("Apply iptables rules for AP interface"); ?></label> | ||||
|                     <i class="fas fa-question-circle text-muted" data-toggle="tooltip" data-placement="auto" title="<?php echo _("Recommended if you wish to forward network traffic from the wg0 interface to clients connected on the AP interface."); ?>"></i> | ||||
|                     <p id="wg-description"> | ||||
|                       <small><?php printf(_("This option adds <strong>iptables</strong> <code>Postup</code> and <code>PostDown</code> rules for the configured AP interface (%s)."), $_SESSION['ap_interface']) ?></small> | ||||
|                     </p> | ||||
|                   </div> | ||||
|                 </div> | ||||
|  | ||||
|                 <div class="form-group"> | ||||
|                   <h5 class="panel-title"><?php echo _("Configuration File"); ?></h4> | ||||
|                   <div class="custom-file"> | ||||
|                     <input type="file" class="custom-file-input" name="wgFile" id="wgFile"> | ||||
|                     <label class="custom-file-label" for="wgFile"><?php echo _("Select WireGuard configuration file (.conf)"); ?></label> | ||||
|                   </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-2"></div> | ||||
|  | ||||
|               </div><!-- /.panel-body --> | ||||
|             </div><!-- /.panel --> | ||||
|  | ||||
|             <div class="panel panel-default panel-collapse" id="PanelManual"> | ||||
|               <div class="panel-heading"> | ||||
|                 <h5 class="panel-title"><?php echo _("Create a local WireGuard config"); ?></h5> | ||||
|                 <div class="input-group"> | ||||
|                   <div class="custom-control custom-switch"> | ||||
|                     <input class="custom-control-input" id="server_enabled" type="checkbox" name="wgSrvEnable" value="1" <?php echo $wg_senabled ? ' checked="checked"' : "" ?> aria-describedby="server-description"> | ||||
|                     <label class="custom-control-label" for="server_enabled"><?php echo _("Enable server") ?></label> | ||||
|                   </div> | ||||
|                   <p id="wg-description"> | ||||
|                     <small> | ||||
|                       <?php echo _("Enable this option to secure network traffic by creating an encrypted tunnel between RaspAP and configured peers.") ?> | ||||
|                       <?php echo _("This setting generates a new WireGuard <code>.conf</code> file on this device.") ?> | ||||
|                     </small> | ||||
|                   </p> | ||||
|                 </div> | ||||
|               </div> | ||||
|  | ||||
|               <div class="panel-body"> | ||||
|                 <label for="code"><?php echo _("Local public key"); ?></label> | ||||
|                 <div class="input-group col-md-12 mb-3"> | ||||
|                   <input type="text" class="form-control" name="wg-server" id="wg-srvpubkey" value="<?php echo htmlspecialchars($wg_srvpubkey, ENT_QUOTES); ?>" /> | ||||
|                   <div class="input-group-append"> | ||||
|                     <button class="btn btn-outline-secondary rounded-right wg-keygen" type="button"><i class="fas fa-magic"></i></button> | ||||
|                     <span id="wg-server-pubkey-status" class="input-group-addon check-hidden ml-2 mt-1"><i class="fas fa-check"></i></span> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </div> | ||||
|  | ||||
|               <div class="form-group col-xs-3 col-sm-3"> | ||||
|                 <label for="code"><?php echo _("Local Port"); ?></label> | ||||
|                 <input type="text" class="form-control" name="wg_srvport" value="<?php echo htmlspecialchars($wg_srvport, ENT_QUOTES); ?>" /> | ||||
|               </div> | ||||
|               <div class="form-group col-md-6"> | ||||
|                 <label for="code"><?php echo _("IP Address"); ?></label> | ||||
|                 <input type="text" class="form-control" name="wg_srvipaddress" value="<?php echo htmlspecialchars($wg_srvipaddress, ENT_QUOTES); ?>" /> | ||||
|               </div> | ||||
|               <div class="form-group col-md-6"> | ||||
|                 <label for="code"><?php echo _("DNS"); ?></label> | ||||
|                 <input type="text" class="form-control" name="wg_srvdns" value="<?php echo htmlspecialchars($wg_srvdns, ENT_QUOTES); ?>" /> | ||||
|               </div> | ||||
|               <div class="row mb-3"></div> | ||||
|  | ||||
|             </div><!-- /.panel-body --> | ||||
|           </div><!-- /.panel --> | ||||
|  | ||||
|         </div><!-- /.panel-group --> | ||||
|       </div><!-- /.col --> | ||||
|     </div><!-- /.row --> | ||||
|  | ||||
|     </div> | ||||
|   </div><!-- /.row --> | ||||
| </div><!-- /.tab-pane | settings tab --> | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user