Passed
Push — master ( 542ccc...11646b )
by Tomasz
06:50
created

DeviceLinuxSh   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 711
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 48
eloc 195
c 1
b 0
f 0
dl 0
loc 711
rs 8.5599

15 Methods

Rating   Name   Duplication   Size   Complexity  
A printP12Dialog() 0 73 3
A __construct() 0 5 1
A printPasswordDialog() 0 5 1
A printStart() 0 6 1
A writeWpaConf() 0 38 5
A writeInstaller() 0 37 3
A checkNMResultAndCont() 0 16 1
A printUserConsent() 0 14 4
A glueServerNames() 0 11 3
B printNMScript() 0 194 7
A printProfileConfirmation() 0 8 2
B writeDeviceInfo() 0 32 7
A mkSubjectAltNameList() 0 10 4
A printCheckDirectory() 0 8 1
A printFunctions() 0 206 5

How to fix   Complexity   

Complex Class

Complex classes like DeviceLinuxSh often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DeviceLinuxSh, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * *****************************************************************************
4
 * Contributions to this work were made on behalf of the GÉANT project, a 
5
 * project that has received funding from the European Union’s Framework 
6
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
7
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
8
 * 691567 (GN4-1) and No. 731122 (GN4-2).
9
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
10
 * of the copyright in all material which was developed by a member of the GÉANT
11
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
12
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
13
 * UK as a branch of GÉANT Vereniging.
14
 * 
15
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
16
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
17
 *
18
 * License: see the web/copyright.inc.php file in the file structure or
19
 *          <base_url>/copyright.php after deploying the software
20
 */
21
22
/**
23
 * This file creates Linux installers
24
 *
25
 * @author Tomasz Wolniewicz <[email protected]>
26
 * @author .....
27
 *
28
 * @package ModuleWriting
29
 */
30
namespace devices\linux;
31
use Exception;
32
class DeviceLinuxSh extends \core\DeviceConfig {
33
34
      final public function __construct() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
35
  parent::__construct();
36
      $this->setSupportedEapMethods([\core\common\EAP::EAPTYPE_PEAP_MSCHAP2, \core\common\EAP::EAPTYPE_TTLS_PAP, \core\common\EAP::EAPTYPE_TTLS_MSCHAP2, \core\common\EAP::EAPTYPE_TLS, \core\common\EAP::EAPTYPE_SILVERBULLET]);
37
      $this->local_dir = '.cat_installer';
38
      $this->conf_file = '$HOME/'.$this->local_dir.'/cat_installer.conf';
39
    }
40
41
   public function writeInstaller() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
42
      $out_string = '#!/usr/bin/env bash
43
if [ -z "$BASH" ] ; then
44
   bash  $0
45
   exit
46
fi
47
48
49
';
50
      $out_string .= $this->printFunctions();
51
      $out_string .= $this->printStart();
52
      $out_string .= $this->printProfileConfirmation();
53
      $out_string .= $this->printUserConsent();
54
      $out_string .= $this->printCheckDirectory();
55
      $CAs = $this->attributes['internal:CAs'][0];
56
      $this->server_name = $this->glueServerNames($this->attributes['eap:server_name']);
57
      $this->server_alt_subject_name_list = $this->mkSubjectAltNameList($this->attributes['eap:server_name']);
58
      $out_string .= "# save certificates\n";
59
      $out_string .= 'echo "';
60
      foreach ($CAs as $ca) {
61
        $out_string .= $ca['pem']."\n";
62
      }
63
      $out_string .= '"'." > \$HOME/$this->local_dir/ca.pem\n";
64
65
     $SSIDs = $this->attributes['internal:SSID'];
66
     $delSSIDs = $this->attributes['internal:remove_SSID'];
67
68
     $out_string .= $this->printNMScript($SSIDs,$delSSIDs);
69
     $out_string .= $this->writeWpaConf($SSIDs);
70
     if($this->selected_eap == \core\common\EAP::EAPTYPE_TLS) 
0 ignored issues
show
Bug introduced by
The property selected_eap does not exist on devices\linux\DeviceLinuxSh. Did you mean selectedEap?
Loading history...
71
       $out_string .= $this->printP12Dialog();
72
     else
73
       $out_string .= $this->printPasswordDialog();
74
     $out_string .= $this->checkNMResultAndCont();
75
     $installer_path = $this->installerBasename.'.sh';
76
      file_put_contents($installer_path, $out_string);
77
      return($installer_path);
78
   }
79
80
    public function writeDeviceInfo() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
81
    $ssid_ct=count($this->attributes['internal:SSID']);
82
    $out = '';
83
84
   $out .= _("The installer is in the form of a bash script. It will try to configure eduroam under Network Manager and if this is either not appropriate for your system or your version of Network Manager is too old, a wpa_supplicant config file will be created instead.");
85
   $out .= "<p>";
86
    if($ssid_ct > 1) {
87
        if($ssid_ct > 2) {
88
            $out .= sprintf(_("In addition to <strong>%s</strong> the installer will also configure access to the following networks:"),implode(', ',\config\ConfAssistant::CONSORTIUM['ssid']))." ";
89
        } else
90
            $out .= sprintf(_("In addition to <strong>%s</strong> the installer will also configure access to:"),implode(', ',\config\ConfAssistant::CONSORTIUM['ssid']))." ";
91
        $i = 0;
92
        foreach ($this->attributes['internal:SSID'] as $ssid=>$v) {
93
           if(! in_array($ssid, \config\ConfAssistant::CONSORTIUM['ssid'])) {
94
             if($i > 0)
95
           $out .= ", ";
96
         $i++;
97
         $out .= "<strong>$ssid</strong>";
98
       }
99
    }
100
    $out .= "<p>";
101
    }
102
   $out .= _("The installer will create .cat_installer sub-directory in your home directory and will copy your server certificates there.");
103
if($this->eap == \core\common\EAP::EAPTYPE_TLS)
0 ignored issues
show
Bug Best Practice introduced by
The property eap does not exist on devices\linux\DeviceLinuxSh. Did you maybe forget to declare it?
Loading history...
104
   $out .= _("In order to connect to the network you will need a personal certificate in the form of a p12 file. You should obtain this certificate from your home institution. Consult the support page to find out how this certificate can be obtained. Such certificate files are password protected. You should have both the file and the password available during the installation process. Your p12 file will also be copied to the .cat_installer directory.");
105
else {
106
   $out .= _("In order to connect to the network you will need an account from your home institution. You should consult the support page to find out how this account can be obtained. It is very likely that your account is already activated.");
107
   $out .= "<p>";
108
   $out .= _("You will be requested to enter your account credentials during the installation. This information will be saved so that you will reconnect to the network automatically each time you are in the range.");
109
}
110
    $out .= "<p>";
111
    return $out;
112
  }
113
114
115
  private function printCheckDirectory() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
116
$out = 'if [ -d $HOME/'.$this->local_dir.' ] ; then
117
   if ! ask "'.sprintf(_("Directory %s exists; some of its files may be overwritten."),'$HOME/'.$this->local_dir).'" "'._("Continue").'" 1 ; then exit; fi
118
else
119
  mkdir $HOME/'.$this->local_dir.'
120
fi
121
';
122
 return $out;
123
  }
124
125
  private function checkNMResultAndCont() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
126
    $out = 'if run_python_script ; then
127
   show_info "'._("Installation successful").'"
128
else
129
   show_info "'._("Network Manager configuration failed, generating wpa_supplicant.conf").'"
130
   if ! ask "'.("Network Manager configuration failed, but we may generate a wpa_supplicant configuration file if you wish. Be warned that your connection password will be saved in this file as clear text.").'" "'._("Write the file").'" 1 ; then exit ; fi
131
132
if [ -f '.$this->conf_file.' ] ; then
133
  if ! ask "'.sprintf(_("File %s exists; it will be overwritten."),$this->conf_file).'" "'._("Continue").'" 1 ; then confirm_exit; fi
134
  rm '.$this->conf_file.'
135
  fi
136
   create_wpa_conf
137
   show_info "'.sprintf(_("Output written to %s"),$this->conf_file).'"
138
fi
139
';
140
  return $out;
141
  }
142
143
private function printStart() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
144
     $out = "setup_environment\n";
145
     $out .= 'show_info "'._("This installer has been prepared for \${ORGANISATION}").'\n\n'._("More information and comments:").'\n\nEMAIL: ${SUPPORT}\nWWW: ${URL}\n\n'.
146
_("Installer created with software from the GEANT project.").'"
147
';
148
  return $out;
149
}
150
151
152
private function printProfileConfirmation() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
153
 if($this->attributes['internal:profile_count'][0] > 1)
154
       $out = 'if ! ask "'.sprintf(_("This installer will only work properly if you are a member of %s and the user group: %s."),'${bf}'.$this->attributes['general:instname'][0].'${n}','${bf}'.$this->attributes['profile:name'][0]).'${n}"';
155
    else
156
       $out = 'if ! ask "'.sprintf(_("This installer will only work properly if you are a member of %s."),'${bf}'.$this->attributes['general:instname'][0]).'${n}"';
157
    $out .= ' "'._("Continue").'" 1 ; then exit; fi
158
';
159
  return $out;
160
161
}
162
163
164
  private function printUserConsent() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
165
    $out = '';
166
    if(isset($this->attributes['support:info_file'])) {
167
      if( $this->attributes['internal:info_file'][0]['mime'] == 'txt') {
168
         $handle = fopen($this->attributes['internal:info_file'][0]['name'],"r");
169
         $consent = '';
170
         while (($buffer = fgets($handle, 4096)) !== false) {
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $handle of fgets() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

170
         while (($buffer = fgets(/** @scrutinizer ignore-type */ $handle, 4096)) !== false) {
Loading history...
171
           $consent .= rtrim($buffer) . '\n';
172
         }
173
         $out = 'if ! ask "'.$consent.'${n}" "'._("Continue").'" 1 ; then exit; fi
174
';
175
      }
176
    }
177
    return $out;
178
  }
179
# ask user for confirmation
180
# the first argument is the user prompt
181
# if the second argument is 0 then the first element of yes_no array
182
# will be the default value prompted to the user
183
  private function printFunctions() {
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a function comment
Loading history...
184
$url = (isset($this->attributes['support:url'][0]) && $this->attributes['support:url'][0] ) ? $this->attributes['support:url'][0] : $this->support_url_substitute;
185
$support=(isset($this->attributes['support:email'][0]) && $this->attributes['support:email'][0] ) ? $this->attributes['support:email'][0] : $this->support_email_substitute;
186
$out ='
187
my_name=$0
188
189
190
function setup_environment {
191
  bf=""
192
  n=""
193
  ORGANISATION="'.$this->attributes['general:instname'][0].'"
194
  URL="'.$url.'"
195
  SUPPORT="'.$support.'"
196
if [ ! -z "$DISPLAY" ] ; then
197
  if which zenity 1>/dev/null 2>&1 ; then
198
    ZENITY=`which zenity`
199
  elif which kdialog 1>/dev/null 2>&1 ; then
200
    KDIALOG=`which kdialog`
201
  else
202
    if tty > /dev/null 2>&1 ; then
203
      if  echo $TERM | grep -E -q "xterm|gnome-terminal|lxterminal"  ; then
204
        bf="";
205
        n="";
206
      fi
207
    else
208
      find_xterm
209
      if [ -n "$XT" ] ; then
210
        $XT -e $my_name
211
      fi
212
    fi
213
  fi
214
fi
215
}
216
217
function split_line {
218
echo $1 | awk  -F \'\\\\\\\\n\' \'END {  for(i=1; i <= NF; i++) print $i }\'
219
}
220
221
function find_xterm {
222
terms="xterm aterm wterm lxterminal rxvt gnome-terminal konsole"
223
for t in $terms
224
do
225
  if which $t > /dev/null 2>&1 ; then
226
  XT=$t
227
  break
228
  fi
229
done
230
}
231
232
233
function ask {
234
     T=""
235
#  if ! [ -z "$3" ] ; then
236
#     T="$T: $3"
237
#  fi
238
  if [ ! -z $KDIALOG ] ; then
239
     if $KDIALOG --yesno "${1}\n${2}?" --title "$T" ; then
240
       return 0
241
     else
242
       return 1
243
     fi
244
  fi
245
  if [ ! -z $ZENITY ] ; then
246
     text=`echo "${1}" | fmt -w60`
247
     if $ZENITY --no-wrap --question --text="${text}\n${2}?" --title="$T" 2>/dev/null ; then
248
       return 0
249
     else
250
       return 1
251
     fi
252
  fi
253
254
  yes='._("Y").'
255
  no='._("N").'
256
  yes1=`echo $yes | awk \'{ print toupper($0) }\'`
257
  no1=`echo $no | awk \'{ print toupper($0) }\'`
258
259
  if [ $3 == "0" ]; then
260
    def=$yes
261
  else
262
    def=$no
263
  fi
264
265
  echo "";
266
  while true
267
  do
268
  split_line "$1"
269
  read -p "${bf}$2 ${yes}/${no}? [${def}]:$n " answer
270
  if [ -z "$answer" ] ; then
271
    answer=${def}
272
  fi
273
  answer=`echo $answer | awk \'{ print toupper($0) }\'`
274
  case "$answer" in
275
    ${yes1})
276
       return 0
277
       ;;
278
    ${no1})
279
       return 1
280
       ;;
281
  esac
282
  done
283
}
284
285
function alert {
286
  if [ ! -z $KDIALOG ] ; then
287
     $KDIALOG --sorry "${1}"
288
     return
289
  fi
290
  if [ ! -z $ZENITY ] ; then
291
     $ZENITY --warning --text="$1" 2>/dev/null
292
     return
293
  fi
294
  echo "$1"
295
296
}
297
298
function show_info {
299
  if [ ! -z $KDIALOG ] ; then
300
     $KDIALOG --msgbox "${1}"
301
     return
302
  fi
303
  if [ ! -z $ZENITY ] ; then
304
     $ZENITY --info --width=500 --text="$1" 2>/dev/null
305
     return
306
  fi
307
  split_line "$1"
308
}
309
310
function confirm_exit {
311
  if [ ! -z $KDIALOG ] ; then
312
     if $KDIALOG --yesno "'._("Really quit?").'"  ; then
313
     exit 1
314
     fi
315
  fi
316
  if [ ! -z $ZENITY ] ; then
317
     if $ZENITY --question --text="'._("Really quit?").'" 2>/dev/null ; then
318
        exit 1
319
     fi
320
  fi
321
}
322
323
324
325
function prompt_nonempty_string {
326
  prompt=$2
327
  if [ ! -z $ZENITY ] ; then
328
    if [ $1 -eq 0 ] ; then
329
     H="--hide-text "
330
    fi
331
    if ! [ -z "$3" ] ; then
332
     D="--entry-text=$3"
333
    fi
334
  elif [ ! -z $KDIALOG ] ; then
335
    if [ $1 -eq 0 ] ; then
336
     H="--password"
337
    else
338
     H="--inputbox"
339
    fi
340
  fi
341
342
343
  out_s="";
344
  if [ ! -z $ZENITY ] ; then
345
    while [ ! "$out_s" ] ; do
346
      out_s=`$ZENITY --entry --width=300 $H $D --text "$prompt" 2>/dev/null`
347
      if [ $? -ne 0 ] ; then
348
        confirm_exit
349
      fi
350
    done
351
  elif [ ! -z $KDIALOG ] ; then
352
    while [ ! "$out_s" ] ; do
353
      out_s=`$KDIALOG $H "$prompt" "$3"`
354
      if [ $? -ne 0 ] ; then
355
        confirm_exit
356
      fi
357
    done  
358
  else
359
    while [ ! "$out_s" ] ; do
360
      read -p "${prompt}: " out_s
361
    done
362
  fi
363
  echo "$out_s";
364
}
365
366
function user_cred {
367
  PASSWORD="a"
368
  PASSWORD1="b"
369
370
  if ! USER_NAME=`prompt_nonempty_string 1 "'._("enter your userid").'"` ; then
371
    exit 1
372
  fi
373
374
  while [ "$PASSWORD" != "$PASSWORD1" ]
375
  do
376
    if ! PASSWORD=`prompt_nonempty_string 0 "'._("enter your password").'"` ; then
377
      exit 1
378
    fi
379
    if ! PASSWORD1=`prompt_nonempty_string 0 "'._("repeat your password").'"` ; then
380
      exit 1
381
    fi
382
    if [ "$PASSWORD" != "$PASSWORD1" ] ; then
383
      alert "'._("passwords do not match").'"
384
    fi
385
  done
386
}
387
';
388
return $out;
389
390
}
391
392
393
  private function writeWpaConf($SSIDs) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
394
     $e = \core\common\EAP::eapDisplayName($this->selected_eap);
0 ignored issues
show
Bug introduced by
The property selected_eap does not exist on devices\linux\DeviceLinuxSh. Did you mean selectedEap?
Loading history...
395
$out = 'function create_wpa_conf {
396
cat << EOFW >> '.$this->conf_file."\n";
397
     foreach (array_keys($SSIDs) as $ssid) {
398
    $out .= '
399
network={
400
  ssid="'.$ssid.'"
401
  key_mgmt=WPA-EAP
402
  pairwise=CCMP
403
  group=CCMP TKIP
404
  eap='.$e['OUTER'].'
405
  ca_cert="${HOME}/'.$this->local_dir.'/ca.pem"
406
  identity="${USER_NAME}"';
407
  if($this->server_name)
408
    $out .= '
409
  domain_suffix_match="'.$this->server_name.'"';
410
  if($this->selected_eap == \core\common\EAP::EAPTYPE_TLS) {
411
    $out .= '
412
  private_key="${HOME}/'.$this->local_dir.'/user.p12"
413
  private_key_passwd="${PASSWORD}"';
414
  } else {
415
    $out .= '
416
  phase2="auth='.$e['INNER'].'"
417
  password="${PASSWORD}"';
418
  if($this->attributes['internal:use_anon_outer'][0] == 1) 
419
    $out .= '
420
  anonymous_identity="'.$this->attributes['internal:anon_local_value'][0].'@'.$this->attributes['internal:realm'][0].'"';
421
  }
422
    $out .= '
423
}';
424
}
425
  $out .= '
426
EOFW
427
chmod 600 '.$this->conf_file.'
428
}
429
';
430
  return $out;
431
}
432
433
434
435
  private function printPasswordDialog() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
436
  $out = '#prompt user for credentials
437
  user_cred
438
  ';
439
  return $out;
440
}
441
  private function printP12Dialog() {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
442
  $out ='function p12dialog {
443
  if [ ! -z $ZENITY ] ; then
444
    if ! cert=`$ZENITY --file-selection --file-filter="'._("personal certificate file (p12 or pfx)").' | *.p12 *.P12 *.pfx *.PFX" --file-filter="All files | *" --title="'._("personal certificate file (p12 or pfx)").'" 2>/dev/null` ; then
445
       exit
446
    fi
447
  elif [ ! -z $KDIALOG ] ; then
448
    if ! cert=`$KDIALOG --getopenfilename . "*.p12 *.P12 *.pfx *.PFX | '._("personal certificate file (p12 or pfx)").'" --title "'._("personal certificate file (p12 or pfx)").'"` ; then
449
       exit
450
    fi
451
  
452
  else
453
    cert=""
454
    fl_ct=`ls *.p12 *.P12 *.pfx *.PFX  2>/dev/null | wc -l`
455
    if [ "$fl_ct" = "1" ]; then
456
      cert=`ls *.p12 *.P12 *.pfx *.PFX 2>/dev/null `
457
    fi
458
459
    while true ; do
460
      prompt="'._("personal certificate file (p12 or pfx)").'"
461
      read -p "${prompt} [$bf$cert${n}]" cert_f
462
      if [ "$cert" -a -z "$cert_f" ] ; then
463
         break
464
      else
465
        if [ -f "$cert_f" ] ; then
466
          cert=$cert_f
467
          break
468
        else
469
          echo "'._("file not found").'"
470
          cert=""
471
        fi
472
      fi
473
    done
474
fi
475
    cp "$cert" $HOME/'.$this->local_dir.'/user.p12
476
    cert=$HOME/'.$this->local_dir.'/user.p12
477
478
    PASSWORD=""
479
    prompt="'._("enter the password for the certificate file").'"
480
    while [ ! "$PASSWORD" ]
481
    do
482
      if ! PASSWORD=`prompt_nonempty_string 0 "'._("enter the password for the certificate file").'"` ; then
483
        exit 1
484
      fi
485
      if openssl pkcs12 -in $cert -passin pass:"$PASSWORD" -noout 2>/dev/null; then
486
        USER_NAME=`openssl pkcs12 -in $cert -passin pass:"$PASSWORD" -nokeys -clcerts 2>/dev/null | awk -F/ \'/subject=/ {for(i=1 ; i <= NF; i++) { if(match($i,\'/[cC][nN]=/\')) { print substr($i,RSTART+RLENGTH)}}}\' | grep \'@\'`
487
        if [ -z "$USER_NAME" ] ; then
488
        USER_NAME=`openssl pkcs12 -in $cert -passin pass:"$PASSWORD" -nokeys -clcerts 2>/dev/null | awk -F/ \'/subject=/ {for(i=1 ; i <= NF; i++) { if(match($i,\'/email[^=]*=/\')) { print substr($i,RSTART+RLENGTH)}}}\' | grep  \'@\'`
489
        fi
490
      else
491
        alert "incorrect password"
492
        PASSWORD=""
493
      fi
494
    done
495
';
496
        if (isset($this->attributes['eap-specific:tls_use_other_id']) && $this->attributes['eap-specific:tls_use_other_id'][0] == 'on') {
497
           $out .= '      if ! USERNAME=`prompt_nonempty_string 1 "'._("enter your userid").'" "$USER_NAME"` ; then
498
       exit 1
499
    fi
500
';
501
        } else {
502
            $out .= '      if [ -z "$USER_NAME" ] ; then
503
             if ! USER_NAME=`prompt_nonempty_string 1 "' . _("enter your userid") . '" ""` ; then
504
                 exit 1
505
             fi
506
      fi
507
';
508
        }
509
$out .= '
510
}  
511
p12dialog
512
';
513
 return $out;
514
}
515
516
517
private function glueServerNames($server_list) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
518
  if(! $server_list)
519
    return '';
520
  $A0 =  array_reverse(explode('.',array_shift($server_list)));
521
  $B = $A0;
522
  foreach($server_list as $a) {
523
     $A= array_reverse(explode('.',$a));
524
     $B = array_intersect_assoc($A0,$A);
525
     $A0 = $B;
526
   }
527
  return(implode('.',array_reverse($B)));
528
}
529
530
private function mkSubjectAltNameList($server_list) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
531
  if(! $server_list)
532
    return '';
533
  $out = '';
534
  foreach($server_list as $a) {
535
     if($out)
536
       $out .= ','; 
537
     $out .= "'DNS:$a'";
538
  }
539
  return $out;
540
}
541
542
private function printNMScript($SSIDs,$delSSIDs) {
0 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
543
   $e = \core\common\EAP::eapDisplayName($this->selectedEap);
544
$out = 'function run_python_script {
545
PASSWORD=$( echo "$PASSWORD" | sed "s/\'/\\\\\\\'/g" )
546
if python << EEE1 > /dev/null 2>&1
547
import dbus
548
EEE1
549
then
550
    PYTHON=python
551
elif python3 << EEE2 > /dev/null 2>&1
552
import dbus
553
EEE2
554
then
555
    PYTHON=python3
556
else
557
    PYTHON=none
558
    return 1
559
fi
560
561
$PYTHON << EOF > /dev/null 2>&1
562
#-*- coding: utf-8 -*-
563
import dbus
564
import re
565
import sys
566
import uuid
567
import os
568
569
class EduroamNMConfigTool:
570
571
    def connect_to_NM(self):
572
        #connect to DBus
573
        try:
574
            self.bus = dbus.SystemBus()
575
        except dbus.exceptions.DBusException:
576
            print("Can\'t connect to DBus")
577
            sys.exit(2)
578
        #main service name
579
        self.system_service_name = "org.freedesktop.NetworkManager"
580
        #check NM version
581
        self.check_nm_version()
582
        if self.nm_version == "0.9" or self.nm_version == "1.0":
583
            self.settings_service_name = self.system_service_name
584
            self.connection_interface_name = "org.freedesktop.NetworkManager.Settings.Connection"
585
            #settings proxy
586
            sysproxy = self.bus.get_object(self.settings_service_name, "/org/freedesktop/NetworkManager/Settings")
587
            #settings intrface
588
            self.settings = dbus.Interface(sysproxy, "org.freedesktop.NetworkManager.Settings")
589
        elif self.nm_version == "0.8":
590
            #self.settings_service_name = "org.freedesktop.NetworkManagerUserSettings"
591
            self.settings_service_name = "org.freedesktop.NetworkManager"
592
            self.connection_interface_name = "org.freedesktop.NetworkManagerSettings.Connection"
593
            #settings proxy
594
            sysproxy = self.bus.get_object(self.settings_service_name, "/org/freedesktop/NetworkManagerSettings")
595
            #settings intrface
596
            self.settings = dbus.Interface(sysproxy, "org.freedesktop.NetworkManagerSettings")
597
        else:
598
            print("This Network Manager version is not supported")
599
            sys.exit(2)
600
601
    def check_opts(self):
602
        self.cacert_file = \'${HOME}/'.$this->local_dir.'/ca.pem\'
603
        self.pfx_file = \'${HOME}/'.$this->local_dir.'/user.p12\'
604
        if not os.path.isfile(self.cacert_file):
605
            print("Certificate file not found, looks like a CAT error")
606
            sys.exit(2)
607
608
    def check_nm_version(self):
609
        try:
610
            proxy = self.bus.get_object(self.system_service_name, "/org/freedesktop/NetworkManager")
611
            props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties")
612
            version = props.Get("org.freedesktop.NetworkManager", "Version")
613
        except dbus.exceptions.DBusException:
614
            version = "0.8"
615
        if re.match(r\'^1\.\', version):
616
            self.nm_version = "1.0"
617
            return
618
        if re.match(r\'^0\.9\', version):
619
            self.nm_version = "0.9"
620
            return
621
        if re.match(r\'^0\.8\', version):
622
            self.nm_version = "0.8"
623
            return
624
        else:
625
            self.nm_version = "Unknown version"
626
            return
627
628
    def byte_to_string(self, barray):
629
        return "".join([chr(x) for x in barray])
630
631
632
    def delete_existing_connections(self, ssid):
633
        "checks and deletes earlier connections"
634
        try:
635
            conns = self.settings.ListConnections()
636
        except dbus.exceptions.DBusException:
637
            print("DBus connection problem, a sudo might help")
638
            exit(3)
639
        for each in conns:
640
            con_proxy = self.bus.get_object(self.system_service_name, each)
641
            connection = dbus.Interface(con_proxy, "org.freedesktop.NetworkManager.Settings.Connection")
642
            try:
643
               connection_settings = connection.GetSettings()
644
               if connection_settings[\'connection\'][\'type\'] == \'802-11-wireless\':
645
                   conn_ssid = self.byte_to_string(connection_settings[\'802-11-wireless\'][\'ssid\'])
646
                   if conn_ssid == ssid:
647
                       connection.Delete()
648
            except dbus.exceptions.DBusException:
649
               pass
650
651
    def add_connection(self,ssid):
652
        server_alt_subject_name_list = dbus.Array({'.$this->server_alt_subject_name_list.'})
653
        server_name = \''.$this->server_name.'\'
654
        if self.nm_version == "0.9" or self.nm_version == "1.0":
655
             match_key = \'altsubject-matches\'
656
             match_value = server_alt_subject_name_list
657
        else:
658
             match_key = \'subject-match\'
659
             match_value = server_name
660
            
661
        s_con = dbus.Dictionary({
662
            \'type\': \'802-11-wireless\',
663
            \'uuid\': str(uuid.uuid4()),
664
            \'permissions\': [\'user:$USER\'],
665
            \'id\': ssid 
666
        })
667
        s_wifi = dbus.Dictionary({
668
            \'ssid\': dbus.ByteArray(ssid.encode(\'utf8\')),
669
            \'security\': \'802-11-wireless-security\'
670
        })
671
        s_wsec = dbus.Dictionary({
672
            \'key-mgmt\': \'wpa-eap\',
673
            \'proto\': [\'rsn\',],
674
            \'pairwise\': [\'ccmp\',],
675
            \'group\': [\'ccmp\', \'tkip\']
676
        })
677
        s_8021x = dbus.Dictionary({
678
            \'eap\': [\''.strtolower($e['OUTER']).'\'],
679
            \'identity\': \'$USER_NAME\',
680
            \'ca-cert\': dbus.ByteArray("file://{0}\0".format(self.cacert_file).encode(\'utf8\')),';
681
    if($this->server_name) {
682
             $out .= '
683
             match_key: match_value,';
684
    }
685
    if($this->selected_eap == \core\common\EAP::EAPTYPE_TLS) {
0 ignored issues
show
Bug introduced by
The property selected_eap does not exist on devices\linux\DeviceLinuxSh. Did you mean selectedEap?
Loading history...
686
       $out .= '
687
            \'client-cert\':  dbus.ByteArray("file://{0}\0".format(self.pfx_file).encode(\'utf8\')),
688
            \'private-key\':  dbus.ByteArray("file://{0}\0".format(self.pfx_file).encode(\'utf8\')),
689
            \'private-key-password\':  \'$PASSWORD\',';
690
    } else {
691
       $out .= '
692
            \'password\': \'$PASSWORD\',
693
            \'phase2-auth\': \''.strtolower($e['INNER']).'\',';
694
         if($this->attributes['internal:use_anon_outer'][0] == 1) 
695
              $out .= '
696
            \'anonymous-identity\': \''.$this->attributes['internal:anon_local_value'][0].'@'.$this->attributes['internal:realm'][0].'\',';
697
    }
698
    $out .= '
699
        })
700
        s_ip4 = dbus.Dictionary({\'method\': \'auto\'})
701
        s_ip6 = dbus.Dictionary({\'method\': \'auto\'})
702
        con = dbus.Dictionary({
703
            \'connection\': s_con,
704
            \'802-11-wireless\': s_wifi,
705
            \'802-11-wireless-security\': s_wsec,
706
            \'802-1x\': s_8021x,
707
            \'ipv4\': s_ip4,
708
            \'ipv6\': s_ip6
709
        })
710
        self.settings.AddConnection(con)
711
712
    def main(self):
713
        self.check_opts()
714
        ver = self.connect_to_NM()';
715
     foreach (array_keys($SSIDs) as $ssid) {
716
           $out .='
717
        self.delete_existing_connections(\''.$ssid.'\')
718
        self.add_connection(\''.$ssid.'\')';
719
     }
720
//   create a list of profiles to be deleted after installation
721
     foreach ($delSSIDs as $ssid => $cipher) {
722
         if($cipher == 'DEL')
723
            $out .='
724
        self.delete_existing_connections(\''.$ssid.'\')';
725
     }
726
727
$out .='
728
729
if __name__ == "__main__":
730
    ENMCT = EduroamNMConfigTool()
731
    ENMCT.main()
732
EOF
733
}
734
';
735
return $out;
736
}
737
738
739
private $local_dir;
0 ignored issues
show
Coding Style Documentation introduced by
Missing member variable doc comment
Loading history...
740
private $conf_file;
0 ignored issues
show
Coding Style Documentation introduced by
Missing member variable doc comment
Loading history...
741
private $server_name;
0 ignored issues
show
Coding Style Documentation introduced by
Missing member variable doc comment
Loading history...
742
private $server_alt_subject_name_list;
0 ignored issues
show
Coding Style Documentation introduced by
Missing member variable doc comment
Loading history...
743
}
744
745
?>
0 ignored issues
show
Coding Style introduced by
The closing tag should be omitted for pure PHP files.
Loading history...
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
746