upgrade deps, clean up (#83)

This commit is contained in:
Pierre Carrier
2025-02-07 23:48:54 +01:00
committed by GitHub
parent 5aeffe7a0c
commit 9adade7502
361 changed files with 19353 additions and 9076 deletions

1
vendor/github.com/creachadair/otp/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
.go-update

View File

@ -1,3 +0,0 @@
module github.com/creachadair/otp
go 1.18

View File

@ -146,6 +146,9 @@ func (c Config) format(v []byte, nd int) string {
// Truncate truncates the specified digest using the algorithm from RFC 4226.
// Only the low-order 31 bits of the value are populated; the rest are zero.
//
// Note that RFC 6238 stipulates the same truncation algorithm regardless of
// the length of the chosen digest.
func Truncate(digest []byte) uint64 {
offset := digest[len(digest)-1] & 0x0f
code := (uint64(digest[offset]&0x7f) << 24) |

164
vendor/github.com/creachadair/otp/otpauth/migration.go generated vendored Normal file
View File

@ -0,0 +1,164 @@
package otpauth
import (
"bytes"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"io"
"net/url"
"strings"
"github.com/creachadair/wirepb"
)
// ParseMigrationURL parses an otpauth-migration URL in the format generated by
// the Google Authenticator for "exported" configurations. Typically these URLs
// are embedded as QR codes, encoding a proprietary URL in this format:
//
// otpauth-migration://offline?data=<content>
//
// The content is a protocol buffer message encoded as base64 in standard
// encoding. Note that a single migration URL may encode multiple OTP
// settings; on success this function returns all the otpauth URLs encoded by
// the content. It will always return at least one URL, or report an error.
func ParseMigrationURL(s string) ([]*URL, error) {
rest, ok := strings.CutPrefix(s, "otpauth-migration://")
if !ok {
return nil, errors.New("missing otpauth-migration schema prefix")
}
content, ok := strings.CutPrefix(rest, "offline?data=")
if !ok {
return nil, errors.New("unrecognized path format")
}
dec, err := url.QueryUnescape(content)
if err != nil {
return nil, fmt.Errorf("invalid data: %w", err)
}
bits, err := base64.StdEncoding.DecodeString(dec)
if err != nil {
return nil, fmt.Errorf("invalid base64: %w", err)
}
return parseMigrations(bits)
}
/*
The content of a migration URL is a wire-format protocol buffer message.
I don't want to take a dependency on protobuf, since that pulls in a lot of
other expensive Google nonsense, but fortunately the message structure is
fairly simple:
message Content {
repeated Params params = 1;
// ... other fields not of interest.
// If you're exporting more data than can fit in one QR code, the app may
// split up the export into multiple codes. There are some fields here to
// keep track of that, but they aren't relevant here.
}
message Params {
bytes secret = 1;
string account = 2;
string issuer = 3;
int32 algorithm = 4; // 0: unspec, 1: SHA1, 2: SHA256, 3: SHA512, 4: MD5
int32 digits = 5; // 0: unspec, 1: 6 digits, 2: 8 digits (typical Google)
int32 type = 6; // 0: unspec, 1: HOTP, 2: TOTP
uint64 counter = 7;
}
So here we just unpack the wire format directly.
*/
// parseMigrations parses data as a wire-format protobuf message in the Content
// format described above, and returns a single URL for each instance of the
// Params found therein. Other fields of the message are ignored.
func parseMigrations(data []byte) ([]*URL, error) {
const paramsField = 1
var out []*URL
s := wirepb.NewScanner(bytes.NewReader(data))
for s.Next() == nil {
if s.ID() == paramsField {
u, err := parseParams(s.Data())
if err != nil {
return nil, err
}
out = append(out, u)
}
}
if s.Err() != io.EOF {
return nil, s.Err()
} else if len(out) == 0 {
return nil, errors.New("no URLs found")
}
return out, nil
}
func parseParams(data []byte) (*URL, error) {
const (
secretField = 1 + iota
accountField
issuerField
algorithmField
digitsField
typeField
counterField
)
var out = URL{Algorithm: defaultAlgorithm, Digits: defaultDigits, Period: defaultPeriod}
s := wirepb.NewScanner(bytes.NewReader(data))
for s.Next() == nil {
switch s.ID() {
case secretField:
out.SetSecret(s.Data())
case accountField:
out.Account = string(s.Data())
case issuerField:
out.Issuer = string(s.Data())
case algorithmField:
switch v, _ := binary.Uvarint(s.Data()); v {
case 1:
out.Algorithm = "SHA1"
case 2:
out.Algorithm = "SHA256"
case 3:
out.Algorithm = "SHA512"
case 4:
out.Algorithm = "MD5"
default:
return nil, fmt.Errorf("unknown algorithm code %d", v)
}
case digitsField:
switch v, _ := binary.Uvarint(s.Data()); v {
case 1:
out.Digits = 6
case 2:
out.Digits = 8
default:
return nil, fmt.Errorf("unknown digits code %d", v)
}
case typeField:
switch v, _ := binary.Uvarint(s.Data()); v {
case 1:
out.Type = "hotp"
case 2:
out.Type = "totp"
default:
return nil, fmt.Errorf("unknown type code %d", v)
}
case counterField:
v, n := binary.Uvarint(s.Data())
if n <= 0 {
return nil, errors.New("invalid counter value")
}
out.Counter = v
}
}
if s.Err() != io.EOF {
return nil, s.Err()
}
return &out, nil
}

View File

@ -60,7 +60,7 @@ func (u *URL) String() string {
// Encode parameters if there are any non-default values.
var params []string
if a := strings.ToUpper(u.Algorithm); a != "" && a != "SHA1" {
params = append(params, "algorithm="+url.PathEscape(a))
params = append(params, "algorithm="+queryEscape(a))
}
if c := u.Counter; c > 0 || typ == "hotp" {
params = append(params, "counter="+strconv.FormatUint(c, 10))
@ -69,14 +69,14 @@ func (u *URL) String() string {
params = append(params, "digits="+strconv.Itoa(d))
}
if o := u.Issuer; o != "" {
params = append(params, "issuer="+url.PathEscape(o))
params = append(params, "issuer="+queryEscape(o))
}
if p := u.Period; p > 0 && p != defaultPeriod {
params = append(params, "period="+strconv.Itoa(p))
}
if s := u.RawSecret; s != "" {
enc := strings.ToUpper(strings.Join(strings.Fields(strings.TrimRight(s, "=")), ""))
params = append(params, "secret="+url.PathEscape(enc))
params = append(params, "secret="+queryEscape(enc))
}
if len(params) != 0 {
sb.WriteByte('?')
@ -182,7 +182,7 @@ func ParseURL(s string) (*URL, error) {
if len(ps) == 1 {
ps = append(ps, "") // check value below
}
value, err := url.PathUnescape(ps[1])
value, err := url.QueryUnescape(ps[1])
if err != nil {
return nil, fmt.Errorf("invalid value: %v", err)
}
@ -219,3 +219,7 @@ func ParseURL(s string) (*URL, error) {
}
return out, nil
}
func queryEscape(s string) string {
return strings.ReplaceAll(url.QueryEscape(s), "+", "%20")
}

26
vendor/github.com/creachadair/wirepb/LICENSE generated vendored Normal file
View File

@ -0,0 +1,26 @@
Copyright (C) 2024, Michael J. Fromberger
All Rights Reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
(1) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
(3) The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.

7
vendor/github.com/creachadair/wirepb/README.md generated vendored Normal file
View File

@ -0,0 +1,7 @@
# wirepb
[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=white)](https://pkg.go.dev/github.com/creachadair/wirepb)
[![CI](https://github.com/creachadair/wirepb/actions/workflows/go-presubmit.yml/badge.svg?event=push&branch=main)](https://github.com/creachadair/wirepb/actions/workflows/go-presubmit.yml)
This repository defines a low-level protocol buffer wire format scanner in Go.
It has no dependency on the protocol buffer compiler or code generators.

32
vendor/github.com/creachadair/wirepb/enums.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
// Code generated by enumgen. DO NOT EDIT.
package wirepb
// Type is a protobuf wire type code.
type Type struct{ _Type uint8 }
// Enum returns the name of the enumeration type for Type.
func (Type) Enum() string { return "Type" }
// String returns the string representation of Type v.
func (v Type) String() string { return _str_Type[v._Type] }
// Valid reports whether v is a valid non-zero Type value.
func (v Type) Valid() bool { return v._Type > 0 && int(v._Type) < len(_str_Type) }
// Index returns the integer index of Type v.
func (v Type) Index() int { return _idx_Type[v._Type] }
// Values for low-level wire types.
var (
_str_Type = []string{"<invalid>", "Varint", "I64", "Len", "StartGroup", "EndGroup", "I32"}
_idx_Type = []int{0, 0, 1, 2, 3, 4, 5}
Invalid = Type{0}
Varint = Type{1} // Base 128 varint
I64 = Type{2} // 64-bit fixed-width integer
Len = Type{3} // Length-prefixed string
StartGroup = Type{4} // Group start marker (obsolete, unused)
EndGroup = Type{5} // Group end marker (obsolete, unused)
I32 = Type{6} // 32-bit fixed-width integer
)

122
vendor/github.com/creachadair/wirepb/wirepb.go generated vendored Normal file
View File

@ -0,0 +1,122 @@
// Package wirepb implements a rudimentary decoder for the protocol buffers wire format.
//
// See: https://protobuf.dev/programming-guides/encoding
package wirepb
import (
"bufio"
"encoding/binary"
"fmt"
"io"
)
//go:generate go run github.com/creachadair/enumgen@latest -output enums.go
/*enumgen:type Type
doc: Type is a protobuf wire type code.
zero: Invalid
val-doc: Values for low-level wire types.
values:
- name: Varint
doc: Base 128 varint
index: 0
- name: I64
doc: 64-bit fixed-width integer
- name: Len
doc: Length-prefixed string
- name: StartGroup
doc: Group start marker (obsolete, unused)
- name: EndGroup
doc: Group end marker (obsolete, unused)
- name: I32
doc: 32-bit fixed-width integer
*/
// Scanner is a protocol buffer wire format lexical scanner.
type Scanner struct {
r *bufio.Reader
tok Type // current token type
id int // current field ID
data []byte // current field contents
err error // last error
}
// NewScanner creates a new scanner that consumes input from r.
func NewScanner(r io.Reader) *Scanner {
return &Scanner{r: bufio.NewReader(r), id: -1}
}
// Type returns the type of the current token, or Invalid if there is not
// currently a token available.
func (s *Scanner) Type() Type { return s.tok }
// Data returns the contents of the current token in binary form, or nil if
// there is not currently a token available. The contents of the returned slice
// are only valid until the next call to Next.
func (s *Scanner) Data() []byte { return s.data }
// ID returns the field ID of the current token, or -1 if there is no token.
func (s *Scanner) ID() int { return s.id }
// Next advances s to the next token of the input or reports an error. At the
// end of the input, Next returns io.EOF.
func (s *Scanner) Next() error {
s.tok = Invalid
s.id = -1
s.data = nil
s.err = nil
tag, err := binary.ReadUvarint(s.r)
if err == io.EOF {
return s.fail(err) // return unwrapped
} else if err != nil {
return s.failf("read tag: %w", err)
}
id, wtype := tag>>3, tag&7
switch wtype {
case 0:
v, err := binary.ReadUvarint(s.r)
if err != nil {
return s.failf("read varint: %w", err)
}
s.data = binary.AppendUvarint(s.data, v)
s.tok = Varint
case 1:
var buf [8]byte
if _, err := io.ReadFull(s.r, buf[:]); err != nil {
return s.failf("read i64: %w", err)
}
s.data, s.tok = buf[:], I64
case 2:
v, err := binary.ReadUvarint(s.r)
if err != nil {
return s.failf("read length: %w", err)
}
buf := make([]byte, int(v))
if _, err := io.ReadFull(s.r, buf); err != nil {
return s.failf("read string: %w", err)
}
s.data, s.tok = buf, Len
case 5:
var buf [4]byte
if _, err := io.ReadFull(s.r, buf[:]); err != nil {
return s.failf("read i32: %w", err)
}
s.data, s.tok = buf[:], I32
case 3, 4:
return s.failf("obsolete wire type %d", wtype)
default:
return s.failf("invalid wire type %d", wtype)
}
s.id = int(id)
return nil
}
// Err returns the last error reported by Next, or nil if none.
func (s *Scanner) Err() error { return s.err }
func (s *Scanner) fail(err error) error { s.err = err; return err }
func (s *Scanner) failf(msg string, args ...any) error { return s.fail(fmt.Errorf(msg, args...)) }