Add logging, including the json one

get infos from I've been pwned and the API on install.dm.gg/vpn-log.php

and send mail if there is anything strange
This commit is contained in:
Xavier Henner
2019-07-10 17:47:43 +02:00
parent 44cfdea6ed
commit 68de442333
14 changed files with 612 additions and 55 deletions

View File

@@ -0,0 +1,5 @@
sudo: false
language: go
go:
- 1.11.x
- tip

19
vendor/github.com/mattevans/pwned-passwords/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (C) 2018 by Matt Evans
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

62
vendor/github.com/mattevans/pwned-passwords/README.md generated vendored Normal file
View File

@@ -0,0 +1,62 @@
# pwned-passwords
[![GoDoc](https://godoc.org/github.com/mattevans/pwned-passwords?status.svg)](https://godoc.org/github.com/mattevans/pwned-passwords)
[![Build Status](https://travis-ci.org/mattevans/pwned-passwords.svg?branch=master)](https://travis-ci.org/mattevans/pwned-passwords)
[![Go Report Card](https://goreportcard.com/badge/github.com/mattevans/pwned-passwords)](https://goreportcard.com/report/github.com/mattevans/pwned-passwords)
[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/mattevans/pwned-passwords/blob/master/LICENSE)
A simple [Go](http://golang.org) client library for checking compromised passwords against [HIBP Pwned Passwords](https://haveibeenpwned.com/Passwords).
Upon request, results will be cached (in-memory), keyed by hash. With a two hour expiry window, subsequent requests will use cached data or fetch fresh data accordingly.
Installation
-----------------
`go get -u github.com/mattevans/pwned-passwords`
Usage
-----------------
```go
package main
import (
"fmt"
hibp "github.com/mattevans/pwned-passwords"
"os"
)
func main() {
// Init a client.
client := hibp.NewClient()
// Check to see if your given string is compromised.
pwned, err := client.Pwned.Compromised("string to check")
if err != nil {
fmt.Println("Pwned failed")
os.Exit(1)
}
if pwned {
// Oh dear!
// You should avoid using that password
} else {
// Woo!
// All clear!
}
}
```
**Expire in-memory cache**
```go
client.Cache.Expire(HASHED_VALUE)
```
```go
client.Cache.ExpireAll()
```
Contributing
-----------------
If you've found a bug or would like to contribute, please create an issue here on GitHub, or better yet fork the project and submit a pull request!

65
vendor/github.com/mattevans/pwned-passwords/cache.go generated vendored Normal file
View File

@@ -0,0 +1,65 @@
package hibp
import "time"
// cache holds our our cached hash/compromised pairs results.
var cache map[string]*PwnedStore
// cacheTTL stores the time to live of our cache (2 hours).
var cacheTTL = 2 * time.Hour
// CacheService handles in-memory caching of our hash/compromised pairs.
type CacheService service
// Get will return our stored in-memory hash/compromised pairs, if we have them.
func (s *CacheService) Get(hash string) *PwnedStore {
// Is our cache expired?
if s.IsExpired(hash) {
return nil
}
// Use stored results.
return cache[hash]
}
// Store will save our hash/compromised pairs to a PwnedStore.
func (s *CacheService) Store(hash string, compromised bool) {
// No cache? Initialize it.
if cache == nil {
cache = map[string]*PwnedStore{}
}
// Store
tn := time.Now()
cache[hash] = &PwnedStore{
Hash: hash,
Compromised: compromised,
UpdatedAt: &tn,
}
}
// IsExpired checks if we have cached hash and that it isn't expired.
func (s *CacheService) IsExpired(hash string) bool {
// No cache? bail.
if cache[hash] == nil {
return true
}
// Expired cache? bail.
lastUpdated := cache[hash].UpdatedAt
if lastUpdated != nil && lastUpdated.Add(cacheTTL).Before(time.Now()) {
return true
}
return false
}
// Expire will expire the cache for a given hash.
func (s *CacheService) Expire(hash string) {
cache[hash] = nil
}
// ExpireAll will expire all cache.
func (s *CacheService) ExpireAll() {
cache = nil
}

115
vendor/github.com/mattevans/pwned-passwords/hibp.go generated vendored Normal file
View File

@@ -0,0 +1,115 @@
package hibp
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
const (
packageVersion = "0.0.1"
backendURL = "https://api.pwnedpasswords.com"
userAgent = "pwned-passwords-golang/" + packageVersion
)
// Client holds a connection to the HIBP API.
type Client struct {
client *http.Client
AppID string
UserAgent string
BackendURL *url.URL
// Services used for communicating with the API.
Pwned *PwnedService
Cache *CacheService
}
type service struct {
client *Client
}
// NewClient creates a new Client with the appropriate connection details and
// services used for communicating with the API.
func NewClient() *Client {
// Init new http.Client.
httpClient := http.DefaultClient
// Parse BE URL.
baseURL, _ := url.Parse(backendURL)
c := &Client{
client: httpClient,
BackendURL: baseURL,
UserAgent: userAgent,
}
c.Pwned = &PwnedService{client: c}
c.Cache = &CacheService{client: c}
return c
}
// NewRequest creates an API request. A relative URL can be provided in urlPath,
// which will be resolved to the BackendURL of the Client.
func (c *Client) NewRequest(method, urlPath string, body interface{}) (*http.Request, error) {
// Parse our URL.
rel, err := url.Parse(urlPath)
if err != nil {
return nil, err
}
// Resolve to absolute URI.
u := c.BackendURL.ResolveReference(rel)
buf := new(bytes.Buffer)
if body != nil {
err = json.NewEncoder(buf).Encode(body)
if err != nil {
return nil, err
}
}
// Create the request.
req, err := http.NewRequest(method, u.String(), buf)
if err != nil {
return nil, err
}
// Add our packages UA.
req.Header.Add("User-Agent", c.UserAgent)
return req, nil
}
// Do sends an API request and returns the API response.
func (c *Client) Do(req *http.Request) ([]string, error) {
resp, err := c.client.Do(req)
if err != nil {
return nil, err
}
defer func() {
if rerr := resp.Body.Close(); err == nil {
err = rerr
}
}()
// Error if anything else but 200.
// The API should always return a 200 (unless something is wrong) as per
// https://haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("Unexpected API response status: %v", resp.StatusCode)
}
// Parse our resp.Body.
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
// Response is returned as new-line'd string, split and return.
return strings.Split(string(body), "\r\n"), err
}

89
vendor/github.com/mattevans/pwned-passwords/pwned.go generated vendored Normal file
View File

@@ -0,0 +1,89 @@
package hibp
import (
"crypto/sha1"
"encoding/hex"
"errors"
"fmt"
"strconv"
"strings"
"time"
)
// PwnedService handles retrieving pwned hashes from in-memory cache or
// by fetching fresh results.
type PwnedService service
// PwnedStore holds our pwned password hashes and compromised status.
type PwnedStore struct {
Hash string `json:"hash"`
Compromised bool `json:"compromised"`
UpdatedAt *time.Time `json:"updated_at"`
}
// Compromised will build and execute a request to HIBP to check to see
// if the passed value is compromised or not.
func (s *PwnedService) Compromised(value string) (bool, error) {
var err error
// Our value being checked is empty, we don't want that.
if value == "" {
return false, errors.New("Value for compromised check cannot be empty")
}
// SHA-1 hash our input value.
hashedStr := _hashString(value)
// If we have cached results, use them.
cache := s.client.Cache.Get(hashedStr)
if cache != nil {
hashedStr = cache.Hash
return cache.Compromised, err
}
// Pop our prefix and suffix.
prefix := strings.ToUpper(hashedStr[:5])
suffix := strings.ToUpper(hashedStr[5:])
// Build request.
request, err := s.client.NewRequest("GET", fmt.Sprintf("range/%s", prefix), nil)
if err != nil {
return false, err
}
// Make request.
response, err := s.client.Do(request)
if err != nil {
return false, err
}
// Range our response ([]string).
for _, target := range response {
// If our target, minus the compromised count matches our suffix.
if string(target[:35]) == suffix {
_, err = strconv.ParseInt(target[36:], 10, 64)
if err != nil {
return false, err
}
// Store in cache as compromised.
s.client.Cache.Store(hashedStr, true)
// Return.
return true, err
}
}
// Store in cache as non-compromised.
s.client.Cache.Store(hashedStr, false)
// Return.
return false, err
}
// _hashString will return a sha1 hash of the given value.
func _hashString(value string) string {
alg := sha1.New()
alg.Write([]byte(value))
return strings.ToUpper(hex.EncodeToString(alg.Sum(nil)))
}

2
vendor/modules.txt vendored
View File

@@ -1,3 +1,5 @@
# github.com/mattevans/pwned-passwords v0.0.0-20190611210716-1da592be4a34
github.com/mattevans/pwned-passwords
# github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9
github.com/pyke369/golang-support/uconfig
github.com/pyke369/golang-support/rcache