1<?php
2
3/**
4 *
5 * bareos-webui - Bareos Web-Frontend
6 *
7 * @link      https://github.com/bareos/bareos for the canonical source repository
8 * @copyright Copyright (c) 2013-2017 Bareos GmbH & Co. KG (http://www.bareos.org/)
9 * @license   GNU Affero General Public License (http://www.gnu.org/licenses/)
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Affero General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Affero General Public License for more details.
20 *
21 * You should have received a copy of the GNU Affero General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25
26namespace Auth\Controller;
27
28use Zend\Mvc\Controller\AbstractActionController;
29use Zend\View\Model\ViewModel;
30use Auth\Model\Auth;
31use Auth\Form\LoginForm;
32use Zend\Session\Container;
33
34class AuthController extends AbstractActionController
35{
36
37   /**
38    * Variables
39    */
40   protected $directorModel = null;
41   protected $bsock = null;
42   protected $updates = null;
43
44   /**
45    * Index Action
46    *
47    * @return object
48    */
49   public function indexAction()
50   {
51      return new ViewModel();
52   }
53
54   /**
55    * Login Action
56    *
57    * @return object
58    */
59   public function loginAction()
60   {
61
62      if($this->SessionTimeoutPlugin()->isValid()) {
63         return $this->redirect()->toRoute('dashboard', array('action' => 'index'));
64      }
65
66      $this->layout('layout/login');
67
68      $config = $this->getServiceLocator()->get('Config');
69      $dird = $this->params()->fromQuery('dird') ? $this->params()->fromQuery('dird') : null;
70
71      if(count($config['directors']) > 1) {
72         $multi_dird_env = true;
73      }
74
75      $form = new LoginForm($config['directors'], $dird);
76
77      $request = $this->getRequest();
78
79      if(!$request->isPost()) {
80         return $this->createNewLoginForm($form);
81      }
82
83      $auth = new Auth();
84      $form->setInputFilter($auth->getInputFilter());
85      $form->setData($request->getPost());
86
87      if(!$form->isValid()) {
88         $err_msg = "Please provide a director, username and password.";
89         return $this->createNewLoginForm($form,$err_msg);
90      }
91
92      $director = $form->getInputFilter()->getValue('director');
93      $username = $form->getInputFilter()->getValue('consolename');
94      $password = $form->getInputFilter()->getValue('password');
95      $locale = $form->getInputFilter()->getValue('locale');
96      $bareos_updates = $form->getInputFilter()->getValue('bareos_updates');
97
98      $config = $this->getServiceLocator()->get('Config');
99      $this->bsock = $this->getServiceLocator()->get('director');
100      $this->bsock->set_config($config['directors'][$director]);
101      $this->bsock->set_user_credentials($username, $password);
102
103      if(!$this->bsock->connect_and_authenticate()) {
104         $err_msg = "Sorry, can not authenticate. Wrong username and/or password.";
105         return $this->createNewLoginForm($form,$err_msg,$this->bsock);
106      }
107
108      $session = new Container('bareos');
109      $session->offsetSet('director', $director);
110      $session->offsetSet('username', $username);
111      $session->offsetSet('password', $password);
112      $session->offsetSet('authenticated', true);
113      $session->offsetSet('locale', $locale);
114      $session->offsetSet('idletime', time());
115      $session->offsetSet('product-updates', $bareos_updates);
116      $session->offsetSet('product-updates-status', false);
117      $session->offsetSet('dird-update-available', false);
118
119      $configuration = $this->getServiceLocator()->get('configuration');
120
121      $session->offsetSet('dt_lengthmenu', $configuration['configuration']['tables']['pagination_values']);
122      $session->offsetSet('dt_pagelength', $configuration['configuration']['tables']['pagination_default_value']);
123      $session->offsetSet('dt_statesave', ($configuration['configuration']['tables']['save_previous_state']) ? 'true' : 'false');
124      $session->offsetSet('dashboard_autorefresh_interval', $configuration['configuration']['dashboard']['autorefresh_interval']);
125      $session->offsetSet('filetree_refresh_timeout', $configuration['configuration']['restore']['filetree_refresh_timeout']);
126
127      if(isset($configuration['configuration']['autochanger']['labelpooltype'])) {
128         $session->offsetSet('ac_labelpooltype', $configuration['configuration']['autochanger']['labelpooltype']);
129      }
130
131      if($bareos_updates != "false" &&
132         !preg_match('/"statusText":"timeout"/', $bareos_updates)) {
133            $session->offsetSet('product-updates-status', true);
134            $this->updates = json_decode($bareos_updates, true);
135            $session->offsetSet('dird-update-available', $this->checkUpdateStatusDIRD());
136      }
137
138      $apicheck = $this->checkAPIStatusDIRD();
139
140      if(!$apicheck) {
141         return $this->createNewLoginForm($form, $multi_dird_env, $apicheck, $this->bsock);
142      }
143
144      $aclcheck = $this->checkACLStatusDIRD();
145
146      if(!$aclcheck) {
147         return $this->createNewLoginForm($form, $multi_dird_env, $aclcheck, $this->bsock);
148      } else {
149         $session->offsetSet('commands', $aclcheck);
150      }
151
152      if($this->params()->fromQuery('req')) {
153         $redirect = $this->params()->fromQuery('req');
154         $request = $this->getRequest();
155         $request->setUri($redirect);
156         if($routeToBeMatched = $this->getServiceLocator()->get('Router')->match($request)) {
157            return $this->redirect()->toUrl($this->params()->fromQuery('req'));
158         }
159      }
160
161      return $this->redirect()->toRoute('dashboard', array('action' => 'index'));
162   }
163
164   /**
165    * Logout Action
166    *
167    * @return object
168    */
169   public function logoutAction()
170   {
171      $session = new Container('bareos');
172      $session->getManager()->destroy();
173      return $this->redirect()->toRoute('auth', array('action' => 'login'));
174   }
175
176   /**
177    * Get Director Model
178    *
179    * @return object
180    */
181   public function getDirectorModel()
182   {
183      if(!$this->directorModel) {
184         $sm = $this->getServiceLocator();
185         $this->directorModel = $sm->get('Director\Model\DirectorModel');
186      }
187      return $this->directorModel;
188   }
189
190   /**
191    * Create New Login Form
192    *
193    * @return object
194    */
195   private function createNewLoginForm($form, $err_msg = null, $bsock = null)
196   {
197      if ($bsock != null) {
198         $bsock->disconnect();
199      }
200      session_destroy();
201      return new ViewModel(
202         array(
203            'form' => $form,
204            'err_msg' => $err_msg,
205         )
206      );
207   }
208
209   /**
210    * DIRD API check
211    *
212    * @return mixed
213    */
214   private function checkAPIStatusDIRD() {
215
216      $err_msg_1 = 'Sorry, the user you are trying to login with has no permissions for the .api command. For further information, please read the <a href="https://docs.bareos.org/IntroductionAndTutorial/InstallingBareosWebui.html#configuration-of-profile-resources" target="_blank">Bareos documentation</a>.';
217      $err_msg_2 = 'Error: API 2 not available on 15.2.2 or greater and/or compile with jansson support.';
218
219      $result = $this->getDirectorModel()->sendDirectorCommand($this->bsock, ".api 2 compact=yes");
220
221      if(preg_match("/.api:/", $result)) {
222         return $err_msg_1;
223      }
224
225      if(preg_match("/result/", $result)) {
226         return $err_msg_2;
227      }
228
229      return true;
230   }
231
232   /**
233    * DIRD ACL check
234    *
235    * @return mixed
236    */
237   private function checkACLStatusDIRD() {
238
239      $err_msg = 'Sorry, your Command ACL does not fit the minimal requirements. For further information, please read the <a href="https://docs.bareos.org/IntroductionAndTutorial/InstallingBareosWebui.html#configuration-of-profile-resources" target="_blank">Bareos documentation</a>.';
240
241      try {
242         $commands = $this->getDirectorModel()->getAvailableCommands($this->bsock);
243      }
244      catch(Exception $e) {
245         echo $e->getMessage();
246      }
247
248      if($commands['.help']['permission'] == 0) {
249         return $err_msg;
250      }
251
252      return $commands;
253   }
254
255   /**
256    * DIRD update check
257    *
258    * @return boolean
259    */
260   private function checkUpdateStatusDIRD() {
261
262      $dird_version = null;
263      $dird_dist = null;
264
265      try {
266         $dird_version = $this->getDirectorModel()->getDirectorVersion($this->bsock);
267         if(array_key_exists('version', $dird_version)) {
268            $dird_vers = $dird_version['version'];
269         }
270      }
271      catch(Exception $e) {
272         echo $e->getMessage();
273      }
274
275      if(array_key_exists('obsdistribution', $dird_version)) {
276         $dird_dist = $dird_version['obsdistribution'];
277      }
278
279      if(!array_key_exists('obsarch', $dird_version)) {
280         $dird_arch = null;
281      }
282
283      if($dird_dist !== null) {
284         if(preg_match("/ubuntu/i", $dird_dist) && $dird_version['obsarch'] == "x86_64") {
285            $dird_arch = "amd64";
286         }
287         elseif(preg_match("/debian/i", $dird_dist) && $dird_version['obsarch'] == "x86_64") {
288            $dird_arch = "amd64";
289         }
290         elseif(preg_match("/univention/i", $dird_dist) && $dird_version['obsarch'] == "x86_64") {
291            $dird_arch = "amd64";
292         }
293         elseif(preg_match("/windows/i", $dird_dist) && $dird_version['obsarch'] == "Win32") {
294            $dird_arch = "32";
295         }
296         elseif(preg_match("/windows/i", $dird_dist) && $dird_version['obsarch'] == "Win64") {
297            $dird_arch = "64";
298         }
299         else {
300            $dird_arch = $dird_version['obsarch'];
301         }
302
303         if(isset($dird_arch) && isset($dird_vers)) {
304            if(array_key_exists('product', $this->updates) &&
305               array_key_exists($dird_dist, $this->updates['product']['bareos-director']['distribution']) &&
306               array_key_exists($dird_arch, $this->updates['product']['bareos-director']['distribution'][$dird_dist])) {
307               foreach($this->updates['product']['bareos-director']['distribution'][$dird_dist][$dird_arch] as $key => $value) {
308                  if( version_compare($dird_vers, $key, '>=') ) {
309                     return false;
310                  }
311                  if( version_compare($dird_vers, $key, '<') ) {
312                     return true;
313                  }
314               }
315            }
316         }
317      }
318
319      return false;
320   }
321
322}
323