@@ -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 || ''; |