Compare commits
16 Commits
fix-client
...
v0.105.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1789c96c7f | ||
|
|
8811c8817e | ||
|
|
5aa0ca9319 | ||
|
|
90054974bc | ||
|
|
9f774d776c | ||
|
|
8ead755b67 | ||
|
|
90ebc4d8c9 | ||
|
|
400b76d47b | ||
|
|
8aa8be2921 | ||
|
|
52575d0247 | ||
|
|
7e1b4ca6fe | ||
|
|
a234b63da1 | ||
|
|
94e783d572 | ||
|
|
91403d0b95 | ||
|
|
d6a059e395 | ||
|
|
f893df7e64 |
26
CHANGELOG.md
26
CHANGELOG.md
@@ -13,19 +13,32 @@ and this project adheres to
|
|||||||
## [v0.106.0] - 2021-04-26
|
## [v0.106.0] - 2021-04-26
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!--
|
## [v0.105.2] - 2021-03-10
|
||||||
## [v0.105.2] - 2021-02-24
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Incomplete hostnames with trailing zero-bytes handling ([#2582]).
|
||||||
|
- Wrong DNS-over-TLS ALPN configuration ([#2681]).
|
||||||
|
- Inconsistent responses for messages with EDNS0 and AD when DNS caching is
|
||||||
|
enabled ([#2600]).
|
||||||
|
- Incomplete OpenWRT detection ([#2757]).
|
||||||
- DHCP lease's `expired` field incorrect time format ([#2692]).
|
- DHCP lease's `expired` field incorrect time format ([#2692]).
|
||||||
- Incomplete DNS upstreams validation ([#2674]).
|
- Incomplete DNS upstreams validation ([#2674]).
|
||||||
- Wrong parsing of DHCP options of the `ip` type ([#2688]).
|
- Wrong parsing of DHCP options of the `ip` type ([#2688]).
|
||||||
|
|
||||||
|
[#2582]: https://github.com/AdguardTeam/AdGuardHome/issues/2582
|
||||||
|
[#2600]: https://github.com/AdguardTeam/AdGuardHome/issues/2600
|
||||||
[#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674
|
[#2674]: https://github.com/AdguardTeam/AdGuardHome/issues/2674
|
||||||
|
[#2681]: https://github.com/AdguardTeam/AdGuardHome/issues/2681
|
||||||
[#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688
|
[#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688
|
||||||
[#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692
|
[#2692]: https://github.com/AdguardTeam/AdGuardHome/issues/2692
|
||||||
|
[#2757]: https://github.com/AdguardTeam/AdGuardHome/issues/2757
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Session token doesn't contain user's information anymore ([#2470]).
|
||||||
|
|
||||||
|
[#2470]: https://github.com/AdguardTeam/AdGuardHome/issues/2470
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -210,11 +223,12 @@ and this project adheres to
|
|||||||
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.2...HEAD
|
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.106.0...HEAD
|
||||||
[v0.105.2]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.1...v0.105.2
|
[v0.106.0]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.2...v0.106.0
|
||||||
-->
|
-->
|
||||||
|
|
||||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.1...HEAD
|
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.2...HEAD
|
||||||
|
[v0.105.2]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.1...v0.105.2
|
||||||
[v0.105.1]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.0...v0.105.1
|
[v0.105.1]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.105.0...v0.105.1
|
||||||
[v0.105.0]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.3...v0.105.0
|
[v0.105.0]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.3...v0.105.0
|
||||||
[v0.104.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.2...v0.104.3
|
[v0.104.3]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.104.2...v0.104.3
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useRef,
|
useRef,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import propTypes from 'prop-types';
|
import propTypes from 'prop-types';
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
@@ -25,19 +25,21 @@ const InfiniteTable = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const loader = useRef(null);
|
const loader = useRef(null);
|
||||||
|
const loadingRef = useRef(null);
|
||||||
|
|
||||||
const {
|
const isEntireLog = useSelector((state) => state.queryLogs.isEntireLog);
|
||||||
isEntireLog,
|
const processingGetLogs = useSelector((state) => state.queryLogs.processingGetLogs);
|
||||||
processingGetLogs,
|
|
||||||
} = useSelector((state) => state.queryLogs, shallowEqual);
|
|
||||||
|
|
||||||
const loading = isLoading || processingGetLogs;
|
const loading = isLoading || processingGetLogs;
|
||||||
|
|
||||||
const listener = useCallback(() => {
|
const listener = useCallback(() => {
|
||||||
if (loader.current && isScrolledIntoView(loader.current)) {
|
if (!loadingRef.current && loader.current && isScrolledIntoView(loader.current)) {
|
||||||
dispatch(getLogs());
|
dispatch(getLogs());
|
||||||
}
|
}
|
||||||
}, [loader.current, isScrolledIntoView, getLogs]);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadingRef.current = processingGetLogs;
|
||||||
|
}, [processingGetLogs]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
listener();
|
listener();
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome
|
|||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdguardTeam/dnsproxy v0.33.9
|
github.com/AdguardTeam/dnsproxy v0.35.5
|
||||||
github.com/AdguardTeam/golibs v0.4.4
|
github.com/AdguardTeam/golibs v0.4.4
|
||||||
github.com/AdguardTeam/urlfilter v0.14.3
|
github.com/AdguardTeam/urlfilter v0.14.3
|
||||||
github.com/NYTimes/gziphandler v1.1.1
|
github.com/NYTimes/gziphandler v1.1.1
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -18,8 +18,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
|
|||||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||||
github.com/AdguardTeam/dnsproxy v0.33.9 h1:HUwywkhUV/M73E7qWcBAF+SdsNq742s82Lvox4pr/tM=
|
github.com/AdguardTeam/dnsproxy v0.35.5 h1:SsRF0eDzuLGaSUDKABIu9Mn1joi4v4kvEU1vju2DQPQ=
|
||||||
github.com/AdguardTeam/dnsproxy v0.33.9/go.mod h1:dkI9VWh43XlOzF2XogDm1EmoVl7PANOR4isQV6X9LZs=
|
github.com/AdguardTeam/dnsproxy v0.35.5/go.mod h1:dkI9VWh43XlOzF2XogDm1EmoVl7PANOR4isQV6X9LZs=
|
||||||
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||||
github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o=
|
github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o=
|
||||||
github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -463,7 +464,16 @@ func (s *v4Server) processRequest(req, resp *dhcpv4.DHCPv4) (*Lease, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if lease.Expiry.Unix() != leaseExpireStatic {
|
if lease.Expiry.Unix() != leaseExpireStatic {
|
||||||
lease.Hostname = string(hostname)
|
// The trimming is required since some devices include trailing
|
||||||
|
// zero-byte in DHCP option length calculation.
|
||||||
|
//
|
||||||
|
// See https://github.com/AdguardTeam/AdGuardHome/issues/2582.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): Remove after the trimming for hostname option
|
||||||
|
// will be added into github.com/insomniacslk/dhcp module.
|
||||||
|
hostnameStr := strings.TrimRight(string(hostname), "\x00")
|
||||||
|
|
||||||
|
lease.Hostname = hostnameStr
|
||||||
s.commitLease(lease)
|
s.commitLease(lease)
|
||||||
} else if len(lease.Hostname) != 0 {
|
} else if len(lease.Hostname) != 0 {
|
||||||
o := &optFQDN{
|
o := &optFQDN{
|
||||||
|
|||||||
@@ -276,14 +276,24 @@ func (s *Server) prepareUpstreamSettings() error {
|
|||||||
upstreams = s.conf.UpstreamDNS
|
upstreams = s.conf.UpstreamDNS
|
||||||
}
|
}
|
||||||
upstreams = filterOutComments(upstreams)
|
upstreams = filterOutComments(upstreams)
|
||||||
upstreamConfig, err := proxy.ParseUpstreamsConfig(upstreams, s.conf.BootstrapDNS, DefaultTimeout)
|
upstreamConfig, err := proxy.ParseUpstreamsConfig(upstreams,
|
||||||
|
upstream.Options{
|
||||||
|
Bootstrap: s.conf.BootstrapDNS,
|
||||||
|
Timeout: DefaultTimeout,
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("dns: proxy.ParseUpstreamsConfig: %w", err)
|
return fmt.Errorf("dns: proxy.ParseUpstreamsConfig: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(upstreamConfig.Upstreams) == 0 {
|
if len(upstreamConfig.Upstreams) == 0 {
|
||||||
log.Info("warning: no default upstream servers specified, using %v", defaultDNS)
|
log.Info("warning: no default upstream servers specified, using %v", defaultDNS)
|
||||||
uc, err := proxy.ParseUpstreamsConfig(defaultDNS, s.conf.BootstrapDNS, DefaultTimeout)
|
uc, err := proxy.ParseUpstreamsConfig(defaultDNS,
|
||||||
|
upstream.Options{
|
||||||
|
Bootstrap: s.conf.BootstrapDNS,
|
||||||
|
Timeout: DefaultTimeout,
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("dns: failed to parse default upstreams: %v", err)
|
return fmt.Errorf("dns: failed to parse default upstreams: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ func (req *dnsConfig) checkBootstrap() (string, error) {
|
|||||||
return boot, fmt.Errorf("invalid bootstrap server address: empty")
|
return boot, fmt.Errorf("invalid bootstrap server address: empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := upstream.NewResolver(boot, 0); err != nil {
|
if _, err := upstream.NewResolver(boot, upstream.Options{Timeout: 0}); err != nil {
|
||||||
return boot, fmt.Errorf("invalid bootstrap server address: %w", err)
|
return boot, fmt.Errorf("invalid bootstrap server address: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,12 @@ func ValidateUpstreams(upstreams []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := proxy.ParseUpstreamsConfig(upstreams, []string{}, DefaultTimeout)
|
_, err := proxy.ParseUpstreamsConfig(upstreams,
|
||||||
|
upstream.Options{
|
||||||
|
Bootstrap: []string{},
|
||||||
|
Timeout: DefaultTimeout,
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,10 @@ package home
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"math/big"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -20,8 +17,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cookieTTL = 365 * 24 // in hours
|
// cookieTTL is given in hours.
|
||||||
|
cookieTTL = 365 * 24
|
||||||
sessionCookieName = "agh_session"
|
sessionCookieName = "agh_session"
|
||||||
|
|
||||||
|
// sessionTokenSize is the length of session token in bytes.
|
||||||
|
sessionTokenSize = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
type session struct {
|
type session struct {
|
||||||
@@ -285,16 +286,29 @@ type loginJSON struct {
|
|||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSession(u *User) ([]byte, error) {
|
// newSessionToken returns cryptographically secure randomly generated slice of
|
||||||
maxSalt := big.NewInt(math.MaxUint32)
|
// bytes of sessionTokenSize length.
|
||||||
salt, err := rand.Int(rand.Reader, maxSalt)
|
//
|
||||||
|
// TODO(e.burkov): Think about using byte array instead of byte slice.
|
||||||
|
func newSessionToken() (data []byte, err error) {
|
||||||
|
randData := make([]byte, sessionTokenSize)
|
||||||
|
|
||||||
|
_, err = rand.Read(randData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
d := []byte(fmt.Sprintf("%s%s%s", salt, u.Name, u.PasswordHash))
|
return randData, nil
|
||||||
hash := sha256.Sum256(d)
|
}
|
||||||
return hash[:], nil
|
|
||||||
|
// cookieTimeFormat is the format to be used in (time.Time).Format for cookie's
|
||||||
|
// expiry field.
|
||||||
|
const cookieTimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||||
|
|
||||||
|
// cookieExpiryFormat returns the formatted exp to be used in cookie string.
|
||||||
|
// It's quite simple for now, but probably will be expanded in the future.
|
||||||
|
func cookieExpiryFormat(exp time.Time) (formatted string) {
|
||||||
|
return exp.Format(cookieTimeFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Auth) httpCookie(req loginJSON) (string, error) {
|
func (a *Auth) httpCookie(req loginJSON) (string, error) {
|
||||||
@@ -303,24 +317,23 @@ func (a *Auth) httpCookie(req loginJSON) (string, error) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sess, err := getSession(&u)
|
sess, err := newSessionToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
expire := now.Add(cookieTTL * time.Hour)
|
|
||||||
expstr := expire.Format(time.RFC1123)
|
|
||||||
expstr = expstr[:len(expstr)-len("UTC")] // "UTC" -> "GMT"
|
|
||||||
expstr += "GMT"
|
|
||||||
|
|
||||||
s := session{}
|
a.addSession(sess, &session{
|
||||||
s.userName = u.Name
|
userName: u.Name,
|
||||||
s.expire = uint32(now.Unix()) + a.sessionTTL
|
expire: uint32(now.Unix()) + a.sessionTTL,
|
||||||
a.addSession(sess, &s)
|
})
|
||||||
|
|
||||||
return fmt.Sprintf("%s=%s; Path=/; HttpOnly; Expires=%s",
|
return fmt.Sprintf(
|
||||||
sessionCookieName, hex.EncodeToString(sess), expstr), nil
|
"%s=%s; Path=/; HttpOnly; Expires=%s",
|
||||||
|
sessionCookieName, hex.EncodeToString(sess),
|
||||||
|
cookieExpiryFormat(now.Add(cookieTTL*time.Hour)),
|
||||||
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleLogin(w http.ResponseWriter, r *http.Request) {
|
func handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package home
|
package home
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -11,6 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
@@ -24,14 +27,34 @@ func prepareTestDir() string {
|
|||||||
return dir
|
return dir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewSessionToken(t *testing.T) {
|
||||||
|
// Successful case.
|
||||||
|
token, err := newSessionToken()
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Len(t, token, sessionTokenSize)
|
||||||
|
|
||||||
|
// Break the rand.Reader.
|
||||||
|
prevReader := rand.Reader
|
||||||
|
t.Cleanup(func() {
|
||||||
|
rand.Reader = prevReader
|
||||||
|
})
|
||||||
|
rand.Reader = &bytes.Buffer{}
|
||||||
|
|
||||||
|
// Unsuccessful case.
|
||||||
|
token, err = newSessionToken()
|
||||||
|
require.NotNil(t, err)
|
||||||
|
assert.Empty(t, token)
|
||||||
|
}
|
||||||
|
|
||||||
func TestAuth(t *testing.T) {
|
func TestAuth(t *testing.T) {
|
||||||
dir := prepareTestDir()
|
dir := prepareTestDir()
|
||||||
defer func() { _ = os.RemoveAll(dir) }()
|
t.Cleanup(func() { _ = os.RemoveAll(dir) })
|
||||||
fn := filepath.Join(dir, "sessions.db")
|
fn := filepath.Join(dir, "sessions.db")
|
||||||
|
|
||||||
users := []User{
|
users := []User{{
|
||||||
{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
Name: "name",
|
||||||
}
|
PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2",
|
||||||
|
}}
|
||||||
a := InitAuth(fn, nil, 60)
|
a := InitAuth(fn, nil, 60)
|
||||||
s := session{}
|
s := session{}
|
||||||
|
|
||||||
@@ -41,7 +64,7 @@ func TestAuth(t *testing.T) {
|
|||||||
assert.Equal(t, checkSessionNotFound, a.checkSession("notfound"))
|
assert.Equal(t, checkSessionNotFound, a.checkSession("notfound"))
|
||||||
a.RemoveSession("notfound")
|
a.RemoveSession("notfound")
|
||||||
|
|
||||||
sess, err := getSession(&users[0])
|
sess, err := newSessionToken()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
sessStr := hex.EncodeToString(sess)
|
sessStr := hex.EncodeToString(sess)
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
||||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||||
|
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/utils"
|
"github.com/AdguardTeam/golibs/utils"
|
||||||
)
|
)
|
||||||
@@ -295,7 +296,12 @@ func (clients *clientsContainer) FindUpstreams(ip string) *proxy.UpstreamConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.upstreamConfig == nil {
|
if c.upstreamConfig == nil {
|
||||||
config, err := proxy.ParseUpstreamsConfig(c.Upstreams, config.DNS.BootstrapDNS, dnsforward.DefaultTimeout)
|
config, err := proxy.ParseUpstreamsConfig(c.Upstreams,
|
||||||
|
upstream.Options{
|
||||||
|
Bootstrap: config.DNS.BootstrapDNS,
|
||||||
|
Timeout: dnsforward.DefaultTimeout,
|
||||||
|
},
|
||||||
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.upstreamConfig = &config
|
c.upstreamConfig = &config
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ func TestHome(t *testing.T) {
|
|||||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
// test DNS over UDP
|
// test DNS over UDP
|
||||||
r, err := upstream.NewResolver("127.0.0.1:5354", 3*time.Second)
|
r, err := upstream.NewResolver("127.0.0.1:5354", upstream.Options{Timeout: 3 * time.Second})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
addrs, err := r.LookupIPAddr(context.TODO(), "static.adguard.com")
|
addrs, err := r.LookupIPAddr(context.TODO(), "static.adguard.com")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type onChangedT func()
|
|||||||
// AutoHosts - automatic DNS records
|
// AutoHosts - automatic DNS records
|
||||||
type AutoHosts struct {
|
type AutoHosts struct {
|
||||||
// lock protects table and tableReverse.
|
// lock protects table and tableReverse.
|
||||||
lock sync.Mutex
|
lock sync.RWMutex
|
||||||
// table is the host-to-IPs map.
|
// table is the host-to-IPs map.
|
||||||
table map[string][]net.IP
|
table map[string][]net.IP
|
||||||
// tableReverse is the IP-to-hosts map.
|
// tableReverse is the IP-to-hosts map.
|
||||||
@@ -119,15 +119,14 @@ func (a *AutoHosts) Process(host string, qtype uint16) []net.IP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ipsCopy []net.IP
|
var ipsCopy []net.IP
|
||||||
a.lock.Lock()
|
a.lock.RLock()
|
||||||
|
defer a.lock.RUnlock()
|
||||||
|
|
||||||
if ips, ok := a.table[host]; ok {
|
if ips, ok := a.table[host]; ok {
|
||||||
ipsCopy = make([]net.IP, len(ips))
|
ipsCopy = make([]net.IP, len(ips))
|
||||||
copy(ipsCopy, ips)
|
copy(ipsCopy, ips)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.lock.Unlock()
|
|
||||||
|
|
||||||
log.Debug("AutoHosts: answer: %s -> %v", host, ipsCopy)
|
log.Debug("AutoHosts: answer: %s -> %v", host, ipsCopy)
|
||||||
return ipsCopy
|
return ipsCopy
|
||||||
}
|
}
|
||||||
@@ -145,8 +144,8 @@ func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) (hosts []string) {
|
|||||||
|
|
||||||
ipStr := ipReal.String()
|
ipStr := ipReal.String()
|
||||||
|
|
||||||
a.lock.Lock()
|
a.lock.RLock()
|
||||||
defer a.lock.Unlock()
|
defer a.lock.RUnlock()
|
||||||
|
|
||||||
hosts = a.tableReverse[ipStr]
|
hosts = a.tableReverse[ipStr]
|
||||||
|
|
||||||
@@ -161,8 +160,8 @@ func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) (hosts []string) {
|
|||||||
|
|
||||||
// List returns an IP-to-hostnames table. It is safe for concurrent use.
|
// List returns an IP-to-hostnames table. It is safe for concurrent use.
|
||||||
func (a *AutoHosts) List() (ipToHosts map[string][]string) {
|
func (a *AutoHosts) List() (ipToHosts map[string][]string) {
|
||||||
a.lock.Lock()
|
a.lock.RLock()
|
||||||
defer a.lock.Unlock()
|
defer a.lock.RUnlock()
|
||||||
|
|
||||||
ipToHosts = make(map[string][]string, len(a.tableReverse))
|
ipToHosts = make(map[string][]string, len(a.tableReverse))
|
||||||
for k, v := range a.tableReverse {
|
for k, v := range a.tableReverse {
|
||||||
@@ -339,10 +338,13 @@ func (a *AutoHosts) updateHosts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.lock.Lock()
|
func() {
|
||||||
a.table = table
|
a.lock.Lock()
|
||||||
a.tableReverse = tableRev
|
defer a.lock.Unlock()
|
||||||
a.lock.Unlock()
|
|
||||||
|
a.table = table
|
||||||
|
a.tableReverse = tableRev
|
||||||
|
}()
|
||||||
|
|
||||||
a.notify()
|
a.notify()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -64,16 +66,43 @@ func SplitNext(str *string, splitBy byte) string {
|
|||||||
return strings.TrimSpace(s)
|
return strings.TrimSpace(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsOpenWRT checks if OS is OpenWRT.
|
// IsOpenWRT returns true if host OS is OpenWRT.
|
||||||
func IsOpenWRT() bool {
|
func IsOpenWRT() bool {
|
||||||
if runtime.GOOS != "linux" {
|
if runtime.GOOS != "linux" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := ioutil.ReadFile("/etc/os-release")
|
const etcDir = "/etc"
|
||||||
|
|
||||||
|
// TODO(e.burkov): Take care of dealing with fs package after updating
|
||||||
|
// Go version to 1.16.
|
||||||
|
fileInfos, err := ioutil.ReadDir(etcDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.Contains(string(body), "OpenWrt")
|
// fNameSubstr is a part of a name of the desired file.
|
||||||
|
const fNameSubstr = "release"
|
||||||
|
osNameData := []byte("OpenWrt")
|
||||||
|
|
||||||
|
for _, fileInfo := range fileInfos {
|
||||||
|
if fileInfo.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(fileInfo.Name(), fNameSubstr) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadFile(filepath.Join(etcDir, fileInfo.Name()))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Contains(body, osNameData) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1279,6 +1279,8 @@
|
|||||||
'type': 'string'
|
'type': 'string'
|
||||||
'edns_cs_enabled':
|
'edns_cs_enabled':
|
||||||
'type': 'boolean'
|
'type': 'boolean'
|
||||||
|
'disable_ipv6':
|
||||||
|
'type': 'boolean'
|
||||||
'dnssec_enabled':
|
'dnssec_enabled':
|
||||||
'type': 'boolean'
|
'type': 'boolean'
|
||||||
'cache_size':
|
'cache_size':
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ set -e -f -u
|
|||||||
readonly awk_program='/^v[0-9]+\.[0-9]+\.[0-9]+.*$/ {
|
readonly awk_program='/^v[0-9]+\.[0-9]+\.[0-9]+.*$/ {
|
||||||
if (!$4) {
|
if (!$4) {
|
||||||
# The last tag is a full release version, so bump the
|
# The last tag is a full release version, so bump the
|
||||||
# minor one to get the next one.
|
# minor release number and zero the patch release number
|
||||||
|
# to get the next release.
|
||||||
$2++;
|
$2++;
|
||||||
|
$3 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
print($1 "." $2 "." $3);
|
print($1 "." $2 "." $3);
|
||||||
|
|||||||
Reference in New Issue
Block a user