Add server-registry store methods with record-ID validation (step 1)
New IStore methods for a per-server registry (GetServers, GetServerByID, CreateServer, DeleteServer, GetServerSettings/SaveServerSettings, GetServerHashes/SaveServerHashes), all additive - existing single-server methods untouched. Adds util.ValidateRecordID/ValidateInterfaceName and applies them to every new method taking a server ID, closing a path- traversal gap before serverID is ever driven by user input (flagged by a security review pass).
This commit is contained in:
@@ -535,3 +535,122 @@ func (o *JsonDB) SaveHashes(hashes model.ClientServerHashes) error {
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// GetServers func to get all servers from the database
|
||||
func (o *JsonDB) GetServers() ([]model.Server, error) {
|
||||
var servers []model.Server
|
||||
results, err := o.conn.ReadAll("servers")
|
||||
if err != nil {
|
||||
if err == scribble.ErrMissingCollection {
|
||||
return servers, nil
|
||||
}
|
||||
return servers, err
|
||||
}
|
||||
for _, i := range results {
|
||||
server := model.Server{}
|
||||
if err := json.Unmarshal([]byte(i), &server); err != nil {
|
||||
return servers, fmt.Errorf("cannot decode server json structure: %v", err)
|
||||
}
|
||||
servers = append(servers, server)
|
||||
}
|
||||
return servers, nil
|
||||
}
|
||||
|
||||
// GetServerByID func to query a single server by id from the database
|
||||
func (o *JsonDB) GetServerByID(serverID string) (model.Server, error) {
|
||||
server := model.Server{}
|
||||
if !util.ValidateRecordID(serverID) {
|
||||
return server, fmt.Errorf("invalid server id: %s", serverID)
|
||||
}
|
||||
err := o.conn.Read("servers", serverID, &server)
|
||||
return server, err
|
||||
}
|
||||
|
||||
// CreateServer func to create a new server in the database
|
||||
func (o *JsonDB) CreateServer(server model.Server) error {
|
||||
if server.ID == "" {
|
||||
return fmt.Errorf("cannot create server: missing id")
|
||||
}
|
||||
if !util.ValidateRecordID(server.ID) {
|
||||
return fmt.Errorf("invalid server id: %s", server.ID)
|
||||
}
|
||||
if server.Interface != nil && server.Interface.Name != "" && !util.ValidateInterfaceName(server.Interface.Name) {
|
||||
return fmt.Errorf("invalid interface name: %s", server.Interface.Name)
|
||||
}
|
||||
if err := o.conn.Write("servers", server.ID, server); err != nil {
|
||||
return err
|
||||
}
|
||||
return util.ManagePerms(path.Join(o.dbPath, "servers", server.ID+".json"))
|
||||
}
|
||||
|
||||
// DeleteServer func to remove a server from the database, refusing if
|
||||
// any client still references it
|
||||
func (o *JsonDB) DeleteServer(serverID string) error {
|
||||
if !util.ValidateRecordID(serverID) {
|
||||
return fmt.Errorf("invalid server id: %s", serverID)
|
||||
}
|
||||
records, err := o.conn.ReadAll("clients")
|
||||
if err != nil && err != scribble.ErrMissingCollection {
|
||||
return err
|
||||
}
|
||||
count := 0
|
||||
for _, rec := range records {
|
||||
var client model.Client
|
||||
if err := json.Unmarshal(rec, &client); err != nil {
|
||||
return fmt.Errorf("cannot decode client json structure: %v", err)
|
||||
}
|
||||
if client.ServerID == serverID {
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count > 0 {
|
||||
return fmt.Errorf("cannot delete server %s: %d client(s) still reference it", serverID, count)
|
||||
}
|
||||
return o.conn.Delete("servers", serverID)
|
||||
}
|
||||
|
||||
// GetServerSettings func to query per-server settings from the database
|
||||
func (o *JsonDB) GetServerSettings(serverID string) (model.ServerSetting, error) {
|
||||
settings := model.ServerSetting{}
|
||||
if !util.ValidateRecordID(serverID) {
|
||||
return settings, fmt.Errorf("invalid server id: %s", serverID)
|
||||
}
|
||||
return settings, o.conn.Read("server_settings", serverID, &settings)
|
||||
}
|
||||
|
||||
// SaveServerSettings func to save per-server settings in the database
|
||||
func (o *JsonDB) SaveServerSettings(serverID string, settings model.ServerSetting) error {
|
||||
if !util.ValidateRecordID(serverID) {
|
||||
return fmt.Errorf("invalid server id: %s", serverID)
|
||||
}
|
||||
settingsPath := path.Join(o.dbPath, "server_settings", serverID+".json")
|
||||
output := o.conn.Write("server_settings", serverID, settings)
|
||||
err := util.ManagePerms(settingsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// GetServerHashes func to query per-server client/server hashes from the database
|
||||
func (o *JsonDB) GetServerHashes(serverID string) (model.ClientServerHashes, error) {
|
||||
hashes := model.ClientServerHashes{}
|
||||
if !util.ValidateRecordID(serverID) {
|
||||
return hashes, fmt.Errorf("invalid server id: %s", serverID)
|
||||
}
|
||||
return hashes, o.conn.Read("server_hashes", serverID, &hashes)
|
||||
}
|
||||
|
||||
// SaveServerHashes func to save per-server client/server hashes in the database
|
||||
func (o *JsonDB) SaveServerHashes(serverID string, hashes model.ClientServerHashes) error {
|
||||
if !util.ValidateRecordID(serverID) {
|
||||
return fmt.Errorf("invalid server id: %s", serverID)
|
||||
}
|
||||
hashesPath := path.Join(o.dbPath, "server_hashes", serverID+".json")
|
||||
output := o.conn.Write("server_hashes", serverID, hashes)
|
||||
err := util.ManagePerms(hashesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user