WIP - cleanup / local discovery
This commit is contained in:
		
							
								
								
									
										128
									
								
								hub/api/api.go
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								hub/api/api.go
									
									
									
									
									
								
							| @@ -15,6 +15,7 @@ import ( | ||||
| 	"git.crumpington.com/lib/go/sqliteutil" | ||||
| 	"golang.org/x/crypto/bcrypt" | ||||
| 	"golang.org/x/crypto/nacl/box" | ||||
| 	"golang.org/x/crypto/nacl/sign" | ||||
| ) | ||||
|  | ||||
| //go:embed migrations | ||||
| @@ -24,6 +25,7 @@ type API struct { | ||||
| 	db          *sql.DB | ||||
| 	lock        sync.Mutex | ||||
| 	peerIntents map[string]PeerCreateArgs | ||||
| 	initIntents map[string]byte // Map from intent key to peer IP | ||||
| } | ||||
|  | ||||
| func New(dbPath string) (*API, error) { | ||||
| @@ -39,6 +41,7 @@ func New(dbPath string) (*API, error) { | ||||
| 	a := &API{ | ||||
| 		db:          sqlDB, | ||||
| 		peerIntents: map[string]PeerCreateArgs{}, | ||||
| 		initIntents: map[string]byte{}, | ||||
| 	} | ||||
|  | ||||
| 	return a, a.ensurePassword() | ||||
| @@ -141,6 +144,16 @@ func (a *API) Session_SignIn(s *Session, pwd string) error { | ||||
| 	return db.Session_SetSignedIn(a.db, s.SessionID) | ||||
| } | ||||
|  | ||||
| func (a *API) Peer_CreateNew(p *Peer) error { | ||||
| 	p.Version = idgen.NextID(0) | ||||
| 	p.PubKey = []byte{} | ||||
| 	p.PubSignKey = []byte{} | ||||
| 	p.APIKey = idgen.NewToken() | ||||
|  | ||||
| 	return db.Peer_Insert(a.db, p) | ||||
| } | ||||
|  | ||||
| // TODO: Remove | ||||
| type PeerCreateArgs struct { | ||||
| 	Name     string | ||||
| 	PublicIP []byte | ||||
| @@ -148,6 +161,7 @@ type PeerCreateArgs struct { | ||||
| 	Relay    bool | ||||
| } | ||||
|  | ||||
| // TODO: Remove | ||||
| // Create the intention to add a peer. The returned code is used to complete | ||||
| // the peer creation. The code is valid for 5 minutes. | ||||
| func (a *API) Peer_CreateIntent(args PeerCreateArgs) string { | ||||
| @@ -167,6 +181,78 @@ func (a *API) Peer_CreateIntent(args PeerCreateArgs) string { | ||||
| 	return code | ||||
| } | ||||
|  | ||||
| // Create the intention to initialize a peer. The returned code is used to | ||||
| // complete the peer initialization. The code is valid for 5 minutes. | ||||
| func (a *API) Peer_CreateInitIntent(peerIP byte) string { | ||||
| 	a.lock.Lock() | ||||
| 	defer a.lock.Unlock() | ||||
|  | ||||
| 	code := idgen.NewToken() | ||||
| 	a.initIntents[code] = peerIP | ||||
|  | ||||
| 	go func() { | ||||
| 		time.Sleep(5 * time.Minute) | ||||
| 		a.lock.Lock() | ||||
| 		defer a.lock.Unlock() | ||||
| 		delete(a.initIntents, code) | ||||
| 	}() | ||||
|  | ||||
| 	return code | ||||
| } | ||||
|  | ||||
| func (a *API) Peer_Init(initCode string) (*m.PeerConfig, error) { | ||||
| 	a.lock.Lock() | ||||
| 	defer a.lock.Unlock() | ||||
|  | ||||
| 	ip, ok := a.initIntents[initCode] | ||||
| 	if !ok { | ||||
| 		return nil, ErrNotAuthorized | ||||
| 	} | ||||
|  | ||||
| 	peer, err := a.Peer_Get(ip) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	delete(a.initIntents, initCode) | ||||
|  | ||||
| 	encPubKey, encPrivKey, err := box.GenerateKey(rand.Reader) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	signPubKey, signPrivKey, err := sign.GenerateKey(rand.Reader) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	peer.Version = idgen.NextID(0) | ||||
| 	peer.APIKey = idgen.NewToken() | ||||
| 	peer.PubKey = encPubKey[:] | ||||
| 	peer.PubSignKey = signPubKey[:] | ||||
|  | ||||
| 	if err := db.Peer_UpdateFull(a.db, peer); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	conf := a.Config_Get() | ||||
|  | ||||
| 	return &m.PeerConfig{ | ||||
| 		PeerIP:      peer.PeerIP, | ||||
| 		HubAddress:  conf.HubAddress, | ||||
| 		APIKey:      peer.APIKey, | ||||
| 		Network:     conf.VPNNetwork, | ||||
| 		PublicIP:    peer.PublicIP, | ||||
| 		Port:        peer.Port, | ||||
| 		Relay:       peer.Relay, | ||||
| 		PubKey:      encPubKey[:], | ||||
| 		PrivKey:     encPrivKey[:], | ||||
| 		PubSignKey:  signPubKey[:], | ||||
| 		PrivSignKey: signPrivKey[:], | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // TODO: Remove | ||||
| func (a *API) Peer_Create(creationCode string) (*m.PeerConfig, error) { | ||||
| 	a.lock.Lock() | ||||
| 	defer a.lock.Unlock() | ||||
| @@ -183,6 +269,11 @@ func (a *API) Peer_Create(creationCode string) (*m.PeerConfig, error) { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	signPubKey, signPrivKey, err := sign.GenerateKey(rand.Reader) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Get peer IP. | ||||
| 	peerIP := byte(0) | ||||
|  | ||||
| @@ -202,14 +293,15 @@ func (a *API) Peer_Create(creationCode string) (*m.PeerConfig, error) { | ||||
| 	} | ||||
|  | ||||
| 	peer := &Peer{ | ||||
| 		PeerIP:   peerIP, | ||||
| 		Version:  idgen.NextID(0), | ||||
| 		APIKey:   idgen.NewToken(), | ||||
| 		Name:     args.Name, | ||||
| 		PublicIP: args.PublicIP, | ||||
| 		Port:     args.Port, | ||||
| 		Relay:    args.Relay, | ||||
| 		PubKey:   encPubKey[:], | ||||
| 		PeerIP:     peerIP, | ||||
| 		Version:    idgen.NextID(0), | ||||
| 		APIKey:     idgen.NewToken(), | ||||
| 		Name:       args.Name, | ||||
| 		PublicIP:   args.PublicIP, | ||||
| 		Port:       args.Port, | ||||
| 		Relay:      args.Relay, | ||||
| 		PubKey:     encPubKey[:], | ||||
| 		PubSignKey: signPubKey[:], | ||||
| 	} | ||||
|  | ||||
| 	if err := db.Peer_Insert(a.db, peer); err != nil { | ||||
| @@ -219,15 +311,17 @@ func (a *API) Peer_Create(creationCode string) (*m.PeerConfig, error) { | ||||
| 	conf := a.Config_Get() | ||||
|  | ||||
| 	return &m.PeerConfig{ | ||||
| 		PeerIP:     peer.PeerIP, | ||||
| 		HubAddress: conf.HubAddress, | ||||
| 		APIKey:     peer.APIKey, | ||||
| 		Network:    conf.VPNNetwork, | ||||
| 		PublicIP:   peer.PublicIP, | ||||
| 		Port:       peer.Port, | ||||
| 		Relay:   peer.Relay, | ||||
| 		PubKey:     encPubKey[:], | ||||
| 		PrivKey:    encPrivKey[:], | ||||
| 		PeerIP:      peer.PeerIP, | ||||
| 		HubAddress:  conf.HubAddress, | ||||
| 		APIKey:      peer.APIKey, | ||||
| 		Network:     conf.VPNNetwork, | ||||
| 		PublicIP:    peer.PublicIP, | ||||
| 		Port:        peer.Port, | ||||
| 		Relay:       peer.Relay, | ||||
| 		PubKey:      encPubKey[:], | ||||
| 		PrivKey:     encPrivKey[:], | ||||
| 		PubSignKey:  signPubKey[:], | ||||
| 		PrivSignKey: signPrivKey[:], | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -307,17 +307,18 @@ func Session_List( | ||||
| // ---------------------------------------------------------------------------- | ||||
|  | ||||
| type Peer struct { | ||||
| 	PeerIP   byte | ||||
| 	Version  int64 | ||||
| 	APIKey   string | ||||
| 	Name     string | ||||
| 	PublicIP []byte | ||||
| 	Port     uint16 | ||||
| 	Relay    bool | ||||
| 	PubKey   []byte | ||||
| 	PeerIP     byte | ||||
| 	Version    int64 | ||||
| 	APIKey     string | ||||
| 	Name       string | ||||
| 	PublicIP   []byte | ||||
| 	Port       uint16 | ||||
| 	Relay      bool | ||||
| 	PubKey     []byte | ||||
| 	PubSignKey []byte | ||||
| } | ||||
|  | ||||
| const Peer_SelectQuery = "SELECT PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey FROM peers" | ||||
| const Peer_SelectQuery = "SELECT PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey FROM peers" | ||||
|  | ||||
| func Peer_Insert( | ||||
| 	tx TX, | ||||
| @@ -328,7 +329,7 @@ func Peer_Insert( | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_, err = tx.Exec("INSERT INTO peers(PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey) VALUES(?,?,?,?,?,?,?,?)", row.PeerIP, row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey) | ||||
| 	_, err = tx.Exec("INSERT INTO peers(PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey) VALUES(?,?,?,?,?,?,?,?,?)", row.PeerIP, row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PubSignKey) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| @@ -369,7 +370,7 @@ func Peer_UpdateFull( | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	result, err := tx.Exec("UPDATE peers SET Version=?,APIKey=?,Name=?,PublicIP=?,Port=?,Relay=?,PubKey=? WHERE PeerIP=?", row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PeerIP) | ||||
| 	result, err := tx.Exec("UPDATE peers SET Version=?,APIKey=?,Name=?,PublicIP=?,Port=?,Relay=?,PubKey=?,PubSignKey=? WHERE PeerIP=?", row.Version, row.APIKey, row.Name, row.PublicIP, row.Port, row.Relay, row.PubKey, row.PubSignKey, row.PeerIP) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -419,8 +420,8 @@ func Peer_Get( | ||||
| 	err error, | ||||
| ) { | ||||
| 	row = &Peer{} | ||||
| 	r := tx.QueryRow("SELECT PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey FROM peers WHERE PeerIP=?", PeerIP) | ||||
| 	err = r.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey) | ||||
| 	r := tx.QueryRow("SELECT PeerIP,Version,APIKey,Name,PublicIP,Port,Relay,PubKey,PubSignKey FROM peers WHERE PeerIP=?", PeerIP) | ||||
| 	err = r.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @@ -434,7 +435,7 @@ func Peer_GetWhere( | ||||
| ) { | ||||
| 	row = &Peer{} | ||||
| 	r := tx.QueryRow(query, args...) | ||||
| 	err = r.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey) | ||||
| 	err = r.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @@ -454,7 +455,7 @@ func Peer_Iterate( | ||||
| 		defer rows.Close() | ||||
| 		for rows.Next() { | ||||
| 			row := &Peer{} | ||||
| 			err := rows.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey) | ||||
| 			err := rows.Scan(&row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.PublicIP, &row.Port, &row.Relay, &row.PubKey, &row.PubSignKey) | ||||
| 			if !yield(row, err) { | ||||
| 				return | ||||
| 			} | ||||
|   | ||||
| @@ -21,5 +21,6 @@ TABLE peers OF Peer ( | ||||
|   PublicIP   []byte, | ||||
|   Port       uint16, | ||||
|   Relay      bool, | ||||
|   PubKey     []byte NoUpdate | ||||
|   PubKey     []byte NoUpdate, | ||||
|   PubSignKey []byte NoUpdate | ||||
| ); | ||||
|   | ||||
							
								
								
									
										1
									
								
								hub/api/migrations/2024-12-27-signing-keys.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								hub/api/migrations/2024-12-27-signing-keys.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ALTER TABLE peers ADD COLUMN PubSignKey BLOB NOT NULL DEFAULT ''; | ||||
		Reference in New Issue
	
	Block a user