2020-03-27 12:09:54 +00:00
package main
import (
2021-03-07 15:06:53 +00:00
"encoding/json"
2020-04-25 21:53:09 +00:00
"errors"
2020-03-27 12:09:54 +00:00
"fmt"
"io/ioutil"
"log"
2020-04-25 21:53:09 +00:00
"net"
2020-03-27 12:09:54 +00:00
"net/http"
2021-10-31 16:30:29 +00:00
"net/url"
2021-03-05 14:14:45 +00:00
"strings"
2020-03-27 12:09:54 +00:00
"time"
2021-10-31 15:43:43 +00:00
"github.com/go-ping/ping"
2020-03-27 12:09:54 +00:00
"github.com/miekg/dns"
2020-03-27 13:57:14 +00:00
2021-10-31 15:43:43 +00:00
"git.nemunai.re/srs/adlin/libadlin"
2020-03-27 12:09:54 +00:00
)
2021-03-05 14:13:59 +00:00
const (
DEFAULT_RESOLVER = "2a01:e0a:2b:2250::1"
2021-03-12 11:46:22 +00:00
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. Taken from miekg/dns
2021-03-05 14:13:59 +00:00
)
2021-03-16 16:12:31 +00:00
var (
verbose = false
2021-10-31 16:42:07 +00:00
verbose2 = false
2021-03-16 16:12:31 +00:00
domainsHostingMap = map [ string ] string { }
)
2020-04-02 14:05:37 +00:00
2020-03-27 12:09:54 +00:00
// ICMP
func check_ping ( ip string , cb func ( pkt * ping . Packet ) ) ( err error ) {
var pinger * ping . Pinger
pinger , err = ping . NewPinger ( ip )
if err != nil {
2021-10-31 16:42:07 +00:00
if verbose {
log . Printf ( "check_ping: %s: %s" , ip , err . Error ( ) )
}
2020-03-27 12:09:54 +00:00
return
}
2021-03-05 14:13:34 +00:00
defer pinger . Stop ( )
2020-03-27 12:09:54 +00:00
pinger . Timeout = time . Second * 5
pinger . Count = 1
pinger . OnRecv = cb
pinger . SetPrivileged ( true )
pinger . Run ( )
return
}
// PORT 53
2020-04-25 21:53:09 +00:00
func get_GLUE ( domain string ) ( aaaa net . IP , err error ) {
client := dns . Client { Net : "tcp" , Timeout : time . Second * 5 }
2021-03-16 16:12:31 +00:00
dnssrv := "[2a01:e0a:2b:2250::b]:53"
if strings . HasSuffix ( domain , adlin . DelegatedDomainSuffix ) {
dnssrv = "[2a01:e0a:2b:2250::b]:53"
} else if v , ok := domainsHostingMap [ domain ] ; ok {
dnssrv = v
} else {
// Looking for root NS
m := new ( dns . Msg )
m . SetQuestion ( "." , dns . TypeNS )
m . RecursionDesired = false
m . SetEdns0 ( 4096 , true )
var r * dns . Msg
r , _ , err = client . Exchange ( m , dnssrv )
if err != nil {
return
}
if r == nil {
return nil , errors . New ( "response is nil during initial recursion" )
}
if r . Rcode != dns . RcodeSuccess {
return nil , errors . New ( "failed to get a valid answer during initial recursion" )
}
for _ , answer := range r . Answer {
if t , ok := answer . ( * dns . NS ) ; ok {
dnssrv = t . Ns + ":53"
}
}
// Do casual recursion
i := 0
recursion :
for i = 0 ; i < 10 ; i ++ {
m := new ( dns . Msg )
m . SetQuestion ( domain , dns . TypeNS )
m . RecursionDesired = false
m . SetEdns0 ( 4096 , true )
var r * dns . Msg
r , _ , err = client . Exchange ( m , dnssrv )
if err != nil {
return
}
if r == nil {
return nil , errors . New ( "response is nil during recursion" )
}
if r . Rcode != dns . RcodeSuccess {
return nil , errors . New ( "failed to get a valid answer during recursion" )
}
for _ , answer := range r . Ns {
if t , ok := answer . ( * dns . NS ) ; ok {
dnssrv = t . Ns + ":53"
if t . Header ( ) . Name == domain {
break recursion
}
}
}
}
if i >= 10 {
return nil , fmt . Errorf ( "too much name recursions" )
} else {
domainsHostingMap [ domain ] = dnssrv
}
}
2020-04-25 21:53:09 +00:00
m := new ( dns . Msg )
m . SetQuestion ( domain , dns . TypeNS )
m . RecursionDesired = false
m . SetEdns0 ( 4096 , true )
var r * dns . Msg
2021-03-16 16:12:31 +00:00
r , _ , err = client . Exchange ( m , dnssrv )
2020-04-25 21:53:09 +00:00
if err != nil {
return
}
if r == nil {
return nil , errors . New ( "response is nil" )
}
if r . Rcode != dns . RcodeSuccess {
return nil , errors . New ( "failed to get a valid answer" )
}
for _ , extra := range r . Extra {
if t , ok := extra . ( * dns . AAAA ) ; ok {
aaaa = t . AAAA
}
}
return
}
func check_dns ( domain , ip string ) ( aaaa net . IP , err error ) {
2020-03-27 12:09:54 +00:00
client := dns . Client { Timeout : time . Second * 5 }
m := new ( dns . Msg )
2020-04-25 21:53:09 +00:00
m . SetQuestion ( domain , dns . TypeAAAA )
var r * dns . Msg
r , _ , err = client . Exchange ( m , fmt . Sprintf ( "[%s]:53" , ip ) )
if err != nil {
return
}
if r == nil {
err = errors . New ( "response is nil" )
2021-03-12 11:46:22 +00:00
return
2020-04-25 21:53:09 +00:00
}
if r . Rcode != dns . RcodeSuccess {
err = errors . New ( "failed to get a valid answer" )
2021-03-12 11:46:22 +00:00
return
2020-04-25 21:53:09 +00:00
}
2021-03-04 00:04:58 +00:00
for _ , answer := range r . Answer {
if t , ok := answer . ( * dns . AAAA ) ; ok {
aaaa = t . AAAA
}
2020-04-25 21:53:09 +00:00
}
2020-03-27 12:09:54 +00:00
return
}
2021-03-12 11:46:22 +00:00
func check_dnssec ( domain , ip string ) ( err error ) {
2021-03-14 09:58:53 +00:00
client := dns . Client { Net : "tcp" , Timeout : time . Second * 10 }
2021-03-12 11:46:22 +00:00
// Get DNSKEY
m := new ( dns . Msg )
m . SetEdns0 ( 4096 , true )
m . SetQuestion ( domain , dns . TypeDNSKEY )
var r * dns . Msg
r , _ , err = client . Exchange ( m , fmt . Sprintf ( "[%s]:53" , ip ) )
if err != nil {
return
}
if r == nil {
return errors . New ( "response is nil" )
}
if r . Rcode != dns . RcodeSuccess {
return errors . New ( "failed to get a valid answer when getting DNSKEY" )
}
var rrs [ ] dns . RR
var dnskeys [ ] * dns . DNSKEY
var dnskeysig * dns . RRSIG
for _ , answer := range r . Answer {
if t , ok := answer . ( * dns . DNSKEY ) ; ok {
dnskeys = append ( dnskeys , t )
rrs = append ( rrs , dns . RR ( t ) )
} else if t , ok := answer . ( * dns . RRSIG ) ; ok {
dnskeysig = t
}
}
2021-03-14 09:58:53 +00:00
if dnskeysig == nil {
return fmt . Errorf ( "Unable to verify DNSKEY record signature: No RRSIG found for DNSKEY record." )
}
2021-03-12 11:46:22 +00:00
found := false
for _ , dnskey := range dnskeys {
if err = dnskeysig . Verify ( dnskey , rrs ) ; err == nil {
found = true
break
}
}
if ! found {
return fmt . Errorf ( "Unable to verify DNSKEY record signature: %w" , err )
}
// Check AAAA validity
m = new ( dns . Msg )
m . SetEdns0 ( 4096 , true )
m . SetQuestion ( domain , dns . TypeAAAA )
r , _ , err = client . Exchange ( m , fmt . Sprintf ( "[%s]:53" , ip ) )
if err != nil {
return
}
if r == nil {
return errors . New ( "response is nil" )
}
if r . Rcode != dns . RcodeSuccess {
return errors . New ( "failed to get a valid answer when getting AAAA records" )
}
rrs = [ ] dns . RR { }
var aaaas [ ] * dns . AAAA
var aaaasig * dns . RRSIG
for _ , answer := range r . Answer {
if t , ok := answer . ( * dns . AAAA ) ; ok {
aaaas = append ( aaaas , t )
rrs = append ( rrs , t )
} else if t , ok := answer . ( * dns . RRSIG ) ; ok {
aaaasig = t
}
}
if len ( aaaas ) == 0 {
2021-03-14 09:58:53 +00:00
return errors . New ( "Something odd happen: no AAAA record found." )
}
if aaaasig == nil {
return fmt . Errorf ( "Unable to verify AAAA record signature: No RRSIG found for AAAA record." )
2021-03-12 11:46:22 +00:00
}
found = false
for _ , dnskey := range dnskeys {
if err = aaaasig . Verify ( dnskey , rrs ) ; err == nil {
found = true
if ! aaaasig . ValidityPeriod ( time . Now ( ) ) {
utc := time . Now ( ) . UTC ( ) . Unix ( )
modi := ( int64 ( aaaasig . Inception ) - utc ) / year68
ti := int64 ( aaaasig . Inception ) + modi * year68
mode := ( int64 ( aaaasig . Expiration ) - utc ) / year68
te := int64 ( aaaasig . Expiration ) + mode * year68
if ti > utc {
return fmt . Errorf ( "Unable to verify AAAA record signature: signature not yet valid" )
} else if utc > te {
return fmt . Errorf ( "Unable to verify AAAA record signature: signature expired" )
} else {
return fmt . Errorf ( "Unable to verify AAAA record signature: signature expired or not yet valid" )
}
}
break
}
}
if ! found {
return fmt . Errorf ( "Unable to verify AAAA record signature: %w" , err )
}
// Check DS
m = new ( dns . Msg )
m . SetQuestion ( domain , dns . TypeDS )
m . RecursionDesired = false
m . SetEdns0 ( 4096 , true )
r , _ , err = client . Exchange ( m , "[2a01:e0a:2b:2250::b]:53" )
if err != nil {
return
}
if r == nil {
return errors . New ( "response is nil" )
}
if r . Rcode != dns . RcodeSuccess {
return errors . New ( "failed to get a valid answer when getting DS records in parent server" )
}
found = false
for _ , answer := range r . Answer {
if t , ok := answer . ( * dns . DS ) ; ok {
for _ , dnskey := range dnskeys {
expectedDS := dnskey . ToDS ( dns . SHA256 )
if expectedDS . KeyTag == t . KeyTag && expectedDS . Algorithm == t . Algorithm && expectedDS . DigestType == t . DigestType && expectedDS . Digest == t . Digest {
found = true
err = nil
break
} else {
err = fmt . Errorf ( "DS record found in parent zone differs from DNSKEY %v vs. %v." , expectedDS , t )
}
}
}
}
if ! found {
if err == nil {
return fmt . Errorf ( "Unable to find a valid DS record in parent zone." )
} else {
return err
}
}
return
}
2020-03-27 12:09:54 +00:00
// PORT 80
2021-03-05 14:14:45 +00:00
func check_http ( ip , dn string ) ( err error ) {
2020-04-25 21:53:09 +00:00
client := & http . Client {
CheckRedirect : func ( req * http . Request , via [ ] * http . Request ) error {
return http . ErrUseLastResponse
} ,
}
2021-03-05 14:14:45 +00:00
req , errr := http . NewRequest ( "GET" , fmt . Sprintf ( "http://[%s]/" , ip ) , nil )
if errr != nil {
return errr
}
if dn != "" {
req . Header . Add ( "Host" , strings . TrimSuffix ( dn , "." ) )
}
2020-03-27 12:09:54 +00:00
var resp * http . Response
2021-03-05 14:14:45 +00:00
resp , err = client . Do ( req )
2020-03-27 12:09:54 +00:00
if err != nil {
return
}
defer resp . Body . Close ( )
2021-03-04 01:01:26 +00:00
2021-03-05 14:14:45 +00:00
if dn != "" && resp . StatusCode >= 400 {
2021-03-04 01:01:26 +00:00
return fmt . Errorf ( "Bad status, got: %d (%s)" , resp . StatusCode , resp . Status )
}
2020-03-27 12:09:54 +00:00
_ , err = ioutil . ReadAll ( resp . Body )
return
}
// PORT 443
func check_https ( domain , ip string ) ( err error ) {
var resp * http . Response
2021-03-05 14:14:45 +00:00
resp , err = http . Get ( fmt . Sprintf ( "https://%s/" , strings . TrimSuffix ( domain , "." ) ) )
2020-03-27 12:09:54 +00:00
if err != nil {
return
}
defer resp . Body . Close ( )
2021-03-04 01:01:26 +00:00
2021-03-05 14:14:45 +00:00
if resp . StatusCode >= 300 && resp . StatusCode < 400 {
loc := resp . Header . Get ( "Location" )
if loc != "" && strings . HasSuffix ( dns . Fqdn ( loc ) , domain ) {
if dns . Fqdn ( loc ) == domain {
return fmt . Errorf ( "Redirection loop %s redirect to %s" , domain , loc )
} else if err = check_https ( dns . Fqdn ( loc ) , ip ) ; err != nil {
return fmt . Errorf ( "Error after following redirection to %s: %w" , loc , err )
} else {
return
}
}
}
2021-03-04 01:01:26 +00:00
if resp . StatusCode >= 300 {
return fmt . Errorf ( "Bad status, got: %d (%s)" , resp . StatusCode , resp . Status )
}
2020-03-27 12:09:54 +00:00
_ , err = ioutil . ReadAll ( resp . Body )
return
}
2021-03-07 15:06:53 +00:00
// MATRIX
type matrix_result struct {
WellKnownResult struct {
2021-03-12 11:28:25 +00:00
Server string ` json:"m.server" `
2021-03-07 15:06:53 +00:00
Result string ` json:"result" `
}
DNSResult struct {
SRVError * struct {
Message string
}
}
ConnectionReports map [ string ] struct {
Errors [ ] string
}
ConnectionErrors map [ string ] struct {
Message string
}
Version struct {
Name string ` json:"name" `
Version string ` json:"version" `
}
2021-03-12 11:28:25 +00:00
FederationOK bool ` json:"FederationOK" `
2021-03-07 15:06:53 +00:00
}
2021-10-31 16:30:29 +00:00
func check_matrix_federation ( domain string ) ( version string , err error ) {
2021-03-07 15:06:53 +00:00
var resp * http . Response
resp , err = http . Get ( fmt . Sprintf ( "https://federation-tester.adlin.nemunai.re/api/report?server_name=%s" , strings . TrimSuffix ( domain , "." ) ) )
if err != nil {
return
}
defer resp . Body . Close ( )
if resp . StatusCode >= 300 {
2021-03-12 11:28:25 +00:00
return "" , fmt . Errorf ( "Sorry, the federation tester is broken. Check on https://federationtester.matrix.org/#%s" , strings . TrimSuffix ( domain , "." ) )
2021-03-07 15:06:53 +00:00
}
var federationTest matrix_result
2021-03-12 11:28:25 +00:00
if err = json . NewDecoder ( resp . Body ) . Decode ( & federationTest ) ; err != nil {
2021-10-31 16:30:29 +00:00
log . Printf ( "Error in check_matrix_federation, when decoding json: %w" , err . Error ( ) )
2021-03-12 11:28:25 +00:00
return "" , fmt . Errorf ( "Sorry, the federation tester is broken. Check on https://federationtester.matrix.org/#%s" , strings . TrimSuffix ( domain , "." ) )
} else if federationTest . FederationOK {
2021-03-08 12:44:23 +00:00
version = federationTest . Version . Name + " " + federationTest . Version . Version
return version , nil
2021-03-07 15:06:53 +00:00
} else if federationTest . DNSResult . SRVError != nil && federationTest . WellKnownResult . Result != "" {
2021-03-08 12:44:23 +00:00
return "" , fmt . Errorf ( "%s OR %s" , federationTest . DNSResult . SRVError . Message , federationTest . WellKnownResult . Result )
2021-03-07 15:06:53 +00:00
} else if len ( federationTest . ConnectionErrors ) > 0 {
var msg strings . Builder
for srv , cerr := range federationTest . ConnectionErrors {
if msg . Len ( ) > 0 {
msg . WriteString ( "; " )
}
msg . WriteString ( srv )
msg . WriteString ( ": " )
msg . WriteString ( cerr . Message )
}
2021-03-08 12:44:23 +00:00
return "" , fmt . Errorf ( "Connection errors: %s" , msg . String ( ) )
2021-03-12 11:28:25 +00:00
} else if federationTest . WellKnownResult . Server != strings . TrimSuffix ( domain , "." ) {
return "" , fmt . Errorf ( "Bad homeserver_name: got %s, expected %s." , federationTest . WellKnownResult . Server , strings . TrimSuffix ( domain , "." ) )
2021-03-07 15:06:53 +00:00
} else {
2021-03-12 11:28:25 +00:00
return "" , fmt . Errorf ( "An unimplemented error occurs. Please report to nemunaire. But know that federation seems to be broken. Check https://federationtester.matrix.org/#%s" , strings . TrimSuffix ( domain , "." ) )
2021-03-07 15:06:53 +00:00
}
}
2021-10-31 16:30:29 +00:00
type matrix_wk_client struct {
Homeserver struct {
BaseURL string ` json:"base_url" `
} ` json:"m.homeserver" `
IdentityServer struct {
BaseURL string ` json:"base_url" `
} ` json:"m.identity_server" `
}
type matrix_client_versions struct {
Versions [ ] string ` json:"versions" `
UnstableFeatures map [ string ] bool ` json:"unstable_features" `
}
func check_matrix_client ( domain string ) ( version string , err error ) {
var resp * http . Response
resp , err = http . Get ( fmt . Sprintf ( "https://%s/.well-known/matrix/client" , strings . TrimSuffix ( domain , "." ) ) )
if err != nil {
return
}
defer resp . Body . Close ( )
var HomeserverBase = fmt . Sprintf ( "https://%s" , strings . TrimSuffix ( domain , "." ) )
if resp . StatusCode < 300 {
var wellknown matrix_wk_client
if err = json . NewDecoder ( resp . Body ) . Decode ( & wellknown ) ; err != nil {
log . Printf ( "Error in check_matrix_client, when decoding json: %w" , err . Error ( ) )
return "" , fmt . Errorf ( "File at https://%s/.well-known/matrix/client is invalid: JSON parse error" , strings . TrimSuffix ( domain , "." ) )
} else if wellknown . Homeserver . BaseURL != "" {
if baseurl , err := url . Parse ( wellknown . Homeserver . BaseURL ) ; err != nil {
return "" , fmt . Errorf ( "File at https://%s/.well-known/matrix/client is invalid: Bad homeserver URL: %s" , strings . TrimSuffix ( domain , "." ) , err . Error ( ) )
} else if ! strings . HasSuffix ( strings . TrimSuffix ( baseurl . Host , "." ) , strings . TrimSuffix ( domain , "." ) ) {
return "" , fmt . Errorf ( "Your homeserver base_url is not under %s" , strings . TrimSuffix ( domain , "." ) )
} else if strings . TrimSuffix ( baseurl . Host , "." ) == strings . TrimSuffix ( domain , "." ) {
// This test can be optional
return "" , fmt . Errorf ( "Your homeserver should be on its own subdomain" )
} else {
HomeserverBase = wellknown . Homeserver . BaseURL
}
}
}
var resp2 * http . Response
resp2 , err = http . Get ( fmt . Sprintf ( "%s/_matrix/client/versions" , HomeserverBase ) )
if err != nil {
return
}
defer resp2 . Body . Close ( )
if resp . StatusCode != http . StatusOK {
return "" , fmt . Errorf ( "Unable to fetch your homeserver versions at %s/_matrix/client/versions: %s" , HomeserverBase , resp . Status )
}
var clientTest matrix_client_versions
if err = json . NewDecoder ( resp2 . Body ) . Decode ( & clientTest ) ; err != nil {
log . Printf ( "Error in check_matrix_client, when decoding versions json: %w" , err . Error ( ) )
return "" , fmt . Errorf ( "File at %s/_matrix/client/versions is invalid: JSON parse error: %s" , HomeserverBase , err . Error ( ) )
} else if len ( clientTest . Versions ) == 0 {
return "" , fmt . Errorf ( "File at %s/_matrix/client/versions is invalid: no protocol version supported" , HomeserverBase )
} else {
return clientTest . Versions [ len ( clientTest . Versions ) - 1 ] , nil
}
}
2020-03-27 12:09:54 +00:00
// Main
2021-03-07 11:39:38 +00:00
func minTunnelVersion ( std * adlin . Student , suffixip int ) ( int , error ) {
2020-04-09 10:27:25 +00:00
tunnels , err := std . GetTunnelTokens ( )
if err != nil {
return 0 , err
}
var minversion int = 2147483647
for _ , tunnel := range tunnels {
if tunnel . Version == 0 {
continue
}
2021-03-04 00:32:09 +00:00
if tunnel . Dump != nil && tunnel . Version < minversion && suffixip == tunnel . SuffixIP {
2020-04-09 10:27:25 +00:00
minversion = tunnel . Version
}
}
return minversion , nil
}
2021-10-31 17:16:58 +00:00
func studentChecker ( std * adlin . Student , also_check_matrix bool ) {
tuns , err := std . GetActivesTunnels ( )
2020-03-27 12:09:54 +00:00
if err != nil {
2021-10-31 17:16:58 +00:00
if verbose2 {
log . Printf ( "SKip %s due to error when getting active tunnels: %s" , std . Login , err . Error ( ) )
}
2020-03-27 12:09:54 +00:00
return
}
2021-10-31 17:16:58 +00:00
if verbose2 && len ( tuns ) == 0 {
log . Printf ( "%s has no active tunnels: %s" , std . Login , err . Error ( ) )
}
2020-03-27 12:09:54 +00:00
2021-10-31 17:16:58 +00:00
for _ , tun := range tuns {
stdIP := tun . GetStudentIP ( )
if verbose2 {
log . Printf ( "Tests %s on %s..." , std . Login , stdIP )
}
2020-03-27 12:09:54 +00:00
// Check ping
2021-10-31 17:16:58 +00:00
check_ping ( stdIP , func ( pkt * ping . Packet ) {
tunnel_version , err := minTunnelVersion ( std , tun . SuffixIP )
if verbose {
log . Printf ( "%s PONG (on %x); version=%d (%v)\n" , std . Login , tun . SuffixIP , tunnel_version , err )
2021-10-31 16:42:07 +00:00
}
2021-10-31 17:16:58 +00:00
std . OnPong ( true )
2020-03-27 12:09:54 +00:00
2021-10-31 17:16:58 +00:00
if tunnel_version == 2147483647 || tunnel_version == 0 {
log . Printf ( "%s unknown tunnel version: %d skipping tests (%v)" , std . Login , tunnel_version , err )
return
}
// PingResolver
if tunnel_version == 3 {
tmp := strings . Split ( stdIP , ":" )
tmp [ len ( tmp ) - 1 ] = "2"
stdResolverIP := strings . Join ( tmp , ":" )
go check_ping ( stdResolverIP , func ( _ * ping . Packet ) {
if verbose {
log . Printf ( "%s resolver PONG" , std . Login )
}
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ PingResolver ] , "" ) ; err != nil {
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
}
} )
2021-10-31 16:42:07 +00:00
}
2021-10-31 17:16:58 +00:00
dnsIP := stdIP
var glueErr error
// Is GLUE defined?
if glueIP , err := get_GLUE ( std . MyDelegatedDomain ( ) ) ; glueIP != nil {
dnsIP = glueIP . String ( )
2020-04-02 14:06:47 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s has defined GLUE: %s\n" , std . Login , dnsIP )
2020-03-27 12:09:54 +00:00
}
2021-10-31 17:16:58 +00:00
} else if err != nil {
log . Printf ( "%s and GLUE: %s\n" , std . Login , err )
glueErr = err
}
2020-03-27 12:09:54 +00:00
2021-10-31 17:16:58 +00:00
// Check DNS
if addr , err := check_dns ( std . MyDelegatedDomain ( ) , dnsIP ) ; err == nil {
if addr == nil {
dnsAt := " at " + dnsIP
if glueErr != nil {
dnsAt = " + there is a problem with the GLUE record: " + glueErr . Error ( )
}
if errreg := std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ DNSDelegation ] , fmt . Errorf ( "%s: empty response from the server%s" , std . MyDelegatedDomain ( ) , dnsAt ) ) ; errreg != nil {
log . Printf ( "Unable to register challenge error for %s: %s\n" , std . Login , errreg )
}
} else {
if verbose {
log . Printf ( "%s just unlocked DNS challenge\n" , std . Login )
}
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ DNSDelegation ] , addr . String ( ) ) ; err != nil {
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
}
2021-03-04 00:32:09 +00:00
2021-10-31 17:16:58 +00:00
// Check HTTP with DNS
if glueErr != nil {
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ HTTPonDelegatedDomain ] , fmt . Errorf ( "Unable to perform the test due to GLUE problem: %w" , glueErr ) )
} else if err := check_http ( addr . String ( ) , std . MyDelegatedDomain ( ) ) ; err == nil {
2021-03-22 00:08:39 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s just unlocked HTTP challenge\n" , std . Login )
2021-03-22 00:08:39 +00:00
}
2021-10-31 17:16:58 +00:00
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ HTTPonDelegatedDomain ] , "" ) ; err != nil {
2021-03-22 00:08:39 +00:00
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
}
2021-10-31 17:16:58 +00:00
} else {
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ HTTPonDelegatedDomain ] , err )
if verbose {
log . Printf ( "%s and HTTP (with DNS ip=%s): %s\n" , std . Login , addr . String ( ) , err )
}
2020-03-27 12:09:54 +00:00
}
2020-04-25 21:53:09 +00:00
2021-10-31 17:16:58 +00:00
// Check HTTPs with DNS
if glueErr != nil {
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ HTTPSonDelegatedDomain ] , fmt . Errorf ( "Unable to perform the test due to GLUE problem: %w" , glueErr ) )
} else if err := check_https ( std . MyDelegatedDomain ( ) , addr . String ( ) ) ; err == nil {
if verbose {
log . Printf ( "%s just unlocked HTTPS challenge\n" , std . Login )
2021-03-04 00:32:09 +00:00
}
2021-10-31 17:16:58 +00:00
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ HTTPSonDelegatedDomain ] , "" ) ; err != nil {
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
2021-03-05 14:14:45 +00:00
}
} else {
2021-10-31 17:16:58 +00:00
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ HTTPSonDelegatedDomain ] , err )
2021-03-04 00:32:09 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s and HTTPS (with DNS ip=%s): %s\n" , std . Login , addr . String ( ) , err )
2021-03-04 00:32:09 +00:00
}
2021-10-31 17:16:58 +00:00
}
2021-03-07 11:42:05 +00:00
2021-10-31 17:16:58 +00:00
// Check Matrix (only if GLUE Ok and defer contraint)
if glueErr == nil && also_check_matrix {
// Check Matrix Federation first
if v , err := check_matrix_federation ( std . MyDelegatedDomain ( ) ) ; err == nil {
2021-03-07 11:42:05 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s just unlocked Matrix federation challenge\n" , std . Login )
2021-03-07 11:42:05 +00:00
}
2021-10-31 17:16:58 +00:00
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ MatrixSrv ] , v ) ; err != nil {
2021-03-07 11:42:05 +00:00
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
}
} else {
2021-10-31 17:16:58 +00:00
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ MatrixSrv ] , err )
2021-03-07 11:42:05 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s and Matrix federation: %s\n" , std . Login , err )
2021-03-07 11:42:05 +00:00
}
}
2021-10-31 17:16:58 +00:00
// Check Matrix Client
if v , err := check_matrix_client ( std . MyDelegatedDomain ( ) ) ; err == nil {
2021-03-07 11:42:05 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s just unlocked Matrix client challenge\n" , std . Login )
2021-03-07 11:42:05 +00:00
}
2021-10-31 17:16:58 +00:00
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ MatrixClt ] , v ) ; err != nil {
2021-03-07 11:42:05 +00:00
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
}
} else {
2021-10-31 17:16:58 +00:00
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ MatrixClt ] , err )
2021-03-07 11:42:05 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s and Matrix client: %s\n" , std . Login , err )
2021-03-07 11:42:05 +00:00
}
2021-03-05 14:14:45 +00:00
}
2021-10-31 17:16:58 +00:00
}
2021-03-07 15:06:53 +00:00
2021-10-31 17:16:58 +00:00
// Check DNSSEC (only if GLUE Ok)
if glueErr == nil {
if err := check_dnssec ( std . MyDelegatedDomain ( ) , dnsIP ) ; err == nil {
if verbose {
log . Printf ( "%s just unlocked DNSSEC challenge\n" , std . Login )
2021-10-31 16:30:29 +00:00
}
2021-10-31 17:16:58 +00:00
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ DNSSEC ] , "" ) ; err != nil {
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
2021-03-07 15:06:53 +00:00
}
2021-10-31 17:16:58 +00:00
} else {
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ DNSSEC ] , err )
if verbose {
log . Printf ( "%s and DNSSEC: %s\n" , std . Login , err )
2021-03-12 11:46:22 +00:00
}
}
2021-03-05 14:14:45 +00:00
}
2021-10-31 17:16:58 +00:00
}
} else {
if errreg := std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ DNSDelegation ] , err ) ; errreg != nil {
log . Printf ( "Unable to register challenge error for %s: %s\n" , std . Login , errreg )
}
if verbose {
log . Printf ( "%s and DNS: %s\n" , std . Login , err )
}
}
// Check HTTP without DNS
if err := check_http ( stdIP , "" ) ; err == nil {
if verbose {
log . Printf ( "%s just unlocked HTTP IP (without DNS) challenge\n" , std . Login )
}
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ HTTPonIP ] , "" ) ; err != nil {
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
}
} else {
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ HTTPonIP ] , err )
if verbose {
log . Printf ( "%s and HTTP IP (without DNS): %s\n" , std . Login , err )
}
}
// Check DNS for association
if addr , err := check_dns ( std . MyAssociatedDomain ( ) , DEFAULT_RESOLVER ) ; err == nil {
// Check HTTP on delegated domain
if err := check_http ( addr . String ( ) , std . MyAssociatedDomain ( ) ) ; err == nil {
if verbose {
log . Printf ( "%s just unlocked HTTP (without DNS) challenge\n" , std . Login )
2021-03-05 14:14:45 +00:00
}
2021-10-31 17:16:58 +00:00
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ HTTPonAssociatedDomain ] , "" ) ; err != nil {
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
}
} else {
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ HTTPonAssociatedDomain ] , err )
2021-03-05 14:14:45 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s and HTTP (without DNS): %s\n" , std . Login , err )
2021-03-05 14:14:45 +00:00
}
}
2021-10-31 17:16:58 +00:00
// Check HTTPs without DNS
if err := check_https ( std . MyAssociatedDomain ( ) , stdIP ) ; err == nil {
2021-03-05 14:14:45 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s just unlocked HTTPS challenge\n" , std . Login )
2021-03-05 14:14:45 +00:00
}
2021-10-31 17:16:58 +00:00
if _ , err := std . UnlockChallenge ( CheckMap [ tunnel_version ] [ HTTPSonAssociatedDomain ] , "" ) ; err != nil {
2021-03-05 14:14:45 +00:00
log . Printf ( "Unable to register challenge for %s: %s\n" , std . Login , err . Error ( ) )
2020-04-25 21:53:09 +00:00
}
2021-03-04 00:32:09 +00:00
} else {
2021-10-31 17:16:58 +00:00
std . RegisterChallengeError ( CheckMap [ tunnel_version ] [ HTTPSonAssociatedDomain ] , err )
2021-03-05 14:14:45 +00:00
if verbose {
2021-10-31 17:16:58 +00:00
log . Printf ( "%s and HTTPS (without DNS): %s\n" , std . Login , err )
2021-03-05 14:14:45 +00:00
}
}
2021-10-31 17:16:58 +00:00
}
2021-03-05 14:14:45 +00:00
2021-10-31 17:16:58 +00:00
return
} )
}
2020-04-25 21:53:09 +00:00
2021-10-31 17:16:58 +00:00
}
2020-03-27 12:09:54 +00:00
2021-10-31 17:16:58 +00:00
func studentsChecker ( ) {
students , err := adlin . GetStudents ( )
if err != nil {
log . Println ( "Unable to check students:" , err )
return
}
check_matrix_for := ( time . Now ( ) . Second ( ) / 30 ) * 5 + time . Now ( ) . Minute ( ) % 5
log . Printf ( "Checking students... (std_matrix%%10=%d)\n" , check_matrix_for )
for istd , s := range students {
time . Sleep ( 250 * time . Millisecond )
go studentChecker ( s , istd % 10 == check_matrix_for )
2020-03-27 12:09:54 +00:00
}
}