Showing 1 changed files with 54 additions and 7 deletions
+54 -7
scripts/host_manager.pl
@@ -645,7 +645,7 @@ sub reassign_vhost {
645 645
     my ($client, $payload) = @_;
646 646
     my $vhost = normalize_dns_name($payload->{vhost_fqdn} || '');
647 647
     my $target_fqdn = normalize_dns_name($payload->{host_fqdn} || $payload->{fqdn} || '');
648
-    return send_json($client, 400, { error => 'invalid_vhost' }) unless name_is_vhost($vhost);
648
+    return send_json($client, 400, { error => 'invalid_vhost' }) unless vhost_name_is_valid($vhost);
649 649
     return send_json($client, 400, { error => 'missing_target_host' }) unless $target_fqdn;
650 650
 
651 651
     my $dbh = dbh();
@@ -688,11 +688,12 @@ sub upsert_vhost {
688 688
     my ($client, $payload) = @_;
689 689
     my $vhost = normalize_dns_name($payload->{vhost_fqdn} || '');
690 690
     my $target_fqdn = normalize_dns_name($payload->{host_fqdn} || $payload->{fqdn} || '');
691
-    return send_json($client, 400, { error => 'invalid_vhost' }) unless name_is_vhost($vhost);
691
+    return send_json($client, 400, { error => 'invalid_vhost' }) unless vhost_name_is_valid($vhost);
692 692
     return send_json($client, 400, { error => 'missing_target_host' }) unless $target_fqdn;
693 693
 
694 694
     my $dbh = dbh();
695 695
     return send_json($client, 400, { error => 'invalid_target_host' }) unless db_scalar($dbh, 'SELECT COUNT(*) FROM hosts WHERE fqdn = ? AND status <> ?', $target_fqdn, 'retired');
696
+    return send_json($client, 400, { error => 'vhost_matches_host' }) if db_scalar($dbh, 'SELECT COUNT(*) FROM hosts WHERE fqdn = ? AND status <> ?', $vhost, 'retired');
696 697
     my ($current_fqdn) = $dbh->selectrow_array(
697 698
         "SELECT host_fqdn FROM vhosts WHERE vhost_fqdn = ? AND status = 'active'",
698 699
         undef,
@@ -725,7 +726,7 @@ sub delete_vhost {
725 726
     my ($client, $payload) = @_;
726 727
     my $vhost = normalize_dns_name($payload->{vhost_fqdn} || '');
727 728
     my $confirm = normalize_dns_name($payload->{confirm} || '');
728
-    return send_json($client, 400, { error => 'invalid_vhost' }) unless name_is_vhost($vhost);
729
+    return send_json($client, 400, { error => 'invalid_vhost' }) unless vhost_name_is_valid($vhost);
729 730
     return send_json($client, 400, { error => 'confirmation_required' }) unless $confirm eq $vhost;
730 731
 
731 732
     my $dbh = dbh();
@@ -828,7 +829,7 @@ sub set_vhost_certificate {
828 829
     my $vhost = normalize_dns_name($payload->{vhost_fqdn} || '');
829 830
     my $raw_certificate_id = clean_scalar($payload->{certificate_id} || $payload->{cert_id} || '');
830 831
     my $certificate_id = clean_certificate_id($raw_certificate_id);
831
-    return send_json($client, 400, { error => 'invalid_vhost' }) unless name_is_vhost($vhost);
832
+    return send_json($client, 400, { error => 'invalid_vhost' }) unless vhost_name_is_valid($vhost);
832 833
     return send_json($client, 400, { error => 'invalid_certificate' })
833 834
         if length($raw_certificate_id) && !length($certificate_id);
834 835
 
@@ -857,7 +858,7 @@ sub set_vhost_certificate {
857 858
 sub issue_vhost_certificate {
858 859
     my ($client, $payload) = @_;
859 860
     my $vhost = normalize_dns_name($payload->{vhost_fqdn} || '');
860
-    return send_json($client, 400, { error => 'invalid_vhost' }) unless name_is_vhost($vhost);
861
+    return send_json($client, 400, { error => 'invalid_vhost' }) unless vhost_name_is_valid($vhost);
861 862
 
862 863
     my $dbh = dbh();
863 864
     my ($host_fqdn) = $dbh->selectrow_array(
@@ -2825,6 +2826,19 @@ sub name_is_vhost {
2825 2826
     return $name =~ /\A(?:pmx|pbs|hosts)\./ ? 1 : 0;
2826 2827
 }
2827 2828
 
2829
+sub vhost_name_is_valid {
2830
+    my ($name) = @_;
2831
+    $name = normalize_dns_name($name);
2832
+    return 0 unless length $name;
2833
+    return 0 unless $name eq 'madagascar.xdev.ro' || $name =~ /\.madagascar\.xdev\.ro\z/;
2834
+    return 0 unless length($name) <= 253;
2835
+    for my $label (split /\./, $name) {
2836
+        return 0 unless length($label) >= 1 && length($label) <= 63;
2837
+        return 0 unless $label =~ /\A[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\z/;
2838
+    }
2839
+    return 1;
2840
+}
2841
+
2828 2842
 sub vhost_service_name {
2829 2843
     my ($name) = @_;
2830 2844
     $name = normalize_dns_name($name);
@@ -3626,7 +3640,9 @@ sub app_html {
3626 3640
           handleAuthLost(error.message);
3627 3641
           throw error;
3628 3642
         }
3629
-        throw new Error(errorCode || res.statusText);
3643
+        const error = new Error(body.detail || errorCode || res.statusText);
3644
+        error.code = errorCode;
3645
+        throw error;
3630 3646
       }
3631 3647
       return body;
3632 3648
     }
@@ -4451,7 +4467,20 @@ sub app_html {
4451 4467
       const hostSelect = $('vhost-new-host');
4452 4468
       const vhost = (nameInput.value || '').trim().toLowerCase();
4453 4469
       const hostFqdn = hostSelect.value || '';
4454
-      if (!vhost || !hostFqdn) return;
4470
+      if (!vhost || !hostFqdn) {
4471
+        msg('completeaza vhost si host');
4472
+        return;
4473
+      }
4474
+      if (!isValidVhostName(vhost)) {
4475
+        msg('vhost invalid: foloseste un nume sub madagascar.xdev.ro');
4476
+        nameInput.focus();
4477
+        return;
4478
+      }
4479
+      if (state.hosts.some(host => (host.fqdn || '').toLowerCase() === vhost)) {
4480
+        msg('vhost invalid: numele este deja host real');
4481
+        nameInput.focus();
4482
+        return;
4483
+      }
4455 4484
       $('vhost-add').disabled = true;
4456 4485
       nameInput.disabled = true;
4457 4486
       hostSelect.disabled = true;
@@ -4464,6 +4493,8 @@ sub app_html {
4464 4493
         nameInput.value = '';
4465 4494
         msg(`vhost ${vhost} saved`);
4466 4495
         await refresh();
4496
+      } catch (e) {
4497
+        if (!isAuthLost(e)) msg(vhostErrorMessage(e));
4467 4498
       } finally {
4468 4499
         $('vhost-add').disabled = false;
4469 4500
         nameInput.disabled = false;
@@ -4471,6 +4502,22 @@ sub app_html {
4471 4502
       }
4472 4503
     }
4473 4504
 
4505
+    function isValidVhostName(name) {
4506
+      name = String(name || '').trim().toLowerCase().replace(/\.$/, '');
4507
+      if (!(name === 'madagascar.xdev.ro' || name.endsWith('.madagascar.xdev.ro'))) return false;
4508
+      if (name.length > 253) return false;
4509
+      return name.split('.').every(label => /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(label));
4510
+    }
4511
+
4512
+    function vhostErrorMessage(error) {
4513
+      const code = error && error.code ? error.code : '';
4514
+      if (code === 'invalid_vhost') return 'vhost invalid: foloseste un nume sub madagascar.xdev.ro';
4515
+      if (code === 'vhost_matches_host') return 'vhost invalid: numele este deja host real';
4516
+      if (code === 'invalid_target_host') return 'host tinta invalid';
4517
+      if (code === 'missing_target_host') return 'alege hostul tinta';
4518
+      return error && error.message ? error.message : 'vhost add failed';
4519
+    }
4520
+
4474 4521
     async function setVhostCertificateFromSelect(select) {
4475 4522
       if (!await ensureAuthenticated('Autentifica-te inainte de salvare.')) {
4476 4523
         select.value = select.dataset.currentCertificate || '';