mirror of
https://github.com/evilsocket/opensnitch.git
synced 2025-03-04 00:24:40 +01:00
python ui server
This commit is contained in:
parent
a17b4c689c
commit
2bda290899
17 changed files with 678 additions and 367 deletions
8
Makefile
8
Makefile
|
@ -1,4 +1,4 @@
|
|||
all: protocol osd osgui
|
||||
all: protocol osd
|
||||
|
||||
protocol:
|
||||
@cd ui.proto && make
|
||||
|
@ -6,12 +6,8 @@ protocol:
|
|||
osd:
|
||||
@cd daemon && make && mv daemon ../osd
|
||||
|
||||
osgui:
|
||||
@cd ui.gtk && make && mv ui.gtk ../osgui
|
||||
|
||||
clean:
|
||||
@cd rules && rm -rf user.rule*.json
|
||||
@cd daemon && make clean
|
||||
@cd ui.proto && make clean
|
||||
@cd ui.gtk && make clean
|
||||
@rm -rf osd osgui
|
||||
@rm -rf osd
|
||||
|
|
|
@ -62,7 +62,7 @@ func FromReply(reply *protocol.RuleReply) *Rule {
|
|||
Duration(reply.Duration),
|
||||
Cmp{
|
||||
What: OperandType(reply.What),
|
||||
With: reply.With,
|
||||
With: reply.Value,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
1
ui.gtk/.gitignore
vendored
1
ui.gtk/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
ui.gtk
|
|
@ -1,7 +0,0 @@
|
|||
all: ui.gtk
|
||||
|
||||
ui.gtk:
|
||||
@go build .
|
||||
|
||||
clean:
|
||||
@rm -rf ui.gtk
|
|
@ -1,178 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkListStore" id="durationStore">
|
||||
<columns>
|
||||
<!-- column-name gchararray1 -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Forever
|
||||
Until Restart
|
||||
Once</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkWindow" id="askWindow">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="window_position">center-always</property>
|
||||
<property name="urgency_hint">True</property>
|
||||
<property name="deletable">False</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="mainBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="headerGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">20</property>
|
||||
<property name="margin_bottom">20</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="appIcon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="stock">gtk-dialog-question</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="appMainGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="appNameLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="label" translatable="yes">Application Name</property>
|
||||
<attributes>
|
||||
<attribute name="font-desc" value="<Inserire il valore> 13"/>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="gravity" value="west"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="descLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="label" translatable="yes">Wants to connect to www.google.com on tcp port 443</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="detailsGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">15</property>
|
||||
<property name="label" translatable="yes">More Details ></property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">1</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="footerGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="column_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="allowButton">
|
||||
<property name="label" translatable="yes">Allow</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="denyButton">
|
||||
<property name="label" translatable="yes">Deny</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="durationCombo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="model">durationStore</property>
|
||||
<property name="active">0</property>
|
||||
<property name="id_column">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
138
ui.gtk/main.go
138
ui.gtk/main.go
|
@ -1,138 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/evilsocket/opensnitch/daemon/core"
|
||||
"github.com/evilsocket/opensnitch/daemon/log"
|
||||
protocol "github.com/evilsocket/opensnitch/ui.proto"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/reflection"
|
||||
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
"github.com/gotk3/gotk3/gtk"
|
||||
)
|
||||
|
||||
var (
|
||||
socketPath = "opensnitch-ui.sock"
|
||||
uiBuilder = (*gtk.Builder)(nil)
|
||||
askWindow = (*gtk.Window)(nil)
|
||||
listener = (net.Listener)(nil)
|
||||
server = (*grpc.Server)(nil)
|
||||
err = (error)(nil)
|
||||
sigChan = (chan os.Signal)(nil)
|
||||
isClosing = (bool)(false)
|
||||
)
|
||||
|
||||
type service struct{}
|
||||
|
||||
func (s *service) Ping(ctx context.Context, ping *protocol.PingRequest) (*protocol.PingReply, error) {
|
||||
log.Debug("Got ping 0x%x", ping.Id)
|
||||
return &protocol.PingReply{Id: ping.Id}, nil
|
||||
}
|
||||
|
||||
func (s *service) AskRule(ctx context.Context, req *protocol.RuleRequest) (*protocol.RuleReply, error) {
|
||||
log.Info("Got rule request: %v", req)
|
||||
|
||||
glib.IdleAdd(func() bool {
|
||||
askWindow.Show()
|
||||
return false
|
||||
})
|
||||
|
||||
return &protocol.RuleReply{
|
||||
Name: "user.choice",
|
||||
Action: "allow",
|
||||
Duration: "always",
|
||||
What: "process.path",
|
||||
With: req.ProcessPath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func setupSignals() {
|
||||
sigChan = make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan,
|
||||
syscall.SIGHUP,
|
||||
syscall.SIGINT,
|
||||
syscall.SIGTERM,
|
||||
syscall.SIGQUIT)
|
||||
go func() {
|
||||
sig := <-sigChan
|
||||
isClosing = true
|
||||
log.Raw("\n")
|
||||
log.Important("Got signal: %v", sig)
|
||||
|
||||
if listener != nil {
|
||||
listener.Close()
|
||||
}
|
||||
os.Exit(0)
|
||||
}()
|
||||
}
|
||||
|
||||
// TODO: this will be loaded from compiled resources
|
||||
const uiGladeFile = "ui.gtk/glade/ask_window.glade"
|
||||
|
||||
func setupGtk() {
|
||||
gtk.Init(&os.Args)
|
||||
|
||||
if uiBuilder, err = gtk.BuilderNew(); err != nil {
|
||||
log.Fatal("Error while creating GTK builder: %s", err)
|
||||
} else if err = uiBuilder.AddFromFile(uiGladeFile); err != nil {
|
||||
log.Fatal("Error while loading %s: %s", uiGladeFile, err)
|
||||
}
|
||||
|
||||
obj, err := uiBuilder.GetObject("askWindow")
|
||||
if err != nil {
|
||||
log.Fatal("Error while getting window: %s", err)
|
||||
}
|
||||
|
||||
var ok bool
|
||||
askWindow, ok = obj.(*gtk.Window)
|
||||
if !ok {
|
||||
log.Fatal("Could not cast window object.")
|
||||
}
|
||||
|
||||
askWindow.SetTitle("OpenSnitch v" + Version)
|
||||
go func() {
|
||||
gtk.Main()
|
||||
}()
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&socketPath, "socket-path", socketPath, "UNIX socket for this gRPC service.")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
socketPath, err = core.ExpandPath(socketPath)
|
||||
if err != nil {
|
||||
log.Fatal("%s", err)
|
||||
}
|
||||
|
||||
setupSignals()
|
||||
setupGtk()
|
||||
|
||||
log.Important("Starting %s v%s on socket %s", Name, Version, socketPath)
|
||||
|
||||
listener, err = net.Listen("unix", socketPath)
|
||||
if err != nil {
|
||||
log.Fatal("%s", err)
|
||||
}
|
||||
|
||||
server = grpc.NewServer()
|
||||
protocol.RegisterUIServer(server, &service{})
|
||||
reflection.Register(server)
|
||||
|
||||
if err := server.Serve(listener); err != nil {
|
||||
if isClosing == false {
|
||||
log.Fatal("Failed to start: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package main
|
||||
|
||||
const (
|
||||
Name = "opensnitch-test-ui"
|
||||
Version = "1.0.0b"
|
||||
Author = "Simone 'evilsocket' Margaritelli"
|
||||
Website = "https://github.com/evilsocket/opensnitch"
|
||||
)
|
1
ui.proto/.gitiignore
Normal file
1
ui.proto/.gitiignore
Normal file
|
@ -0,0 +1 @@
|
|||
*.pyc
|
|
@ -1,5 +1,7 @@
|
|||
all:
|
||||
protoc -I. ui.proto --go_out=plugins=grpc:.
|
||||
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ui.proto
|
||||
|
||||
clean:
|
||||
@rm -rf ui.pb.go
|
||||
@rm -rf *.go
|
||||
@rm -rf *.py
|
||||
|
|
|
@ -152,7 +152,7 @@ type RuleReply struct {
|
|||
Action string `protobuf:"bytes,2,opt,name=action" json:"action,omitempty"`
|
||||
Duration string `protobuf:"bytes,3,opt,name=duration" json:"duration,omitempty"`
|
||||
What string `protobuf:"bytes,4,opt,name=what" json:"what,omitempty"`
|
||||
With string `protobuf:"bytes,5,opt,name=with" json:"with,omitempty"`
|
||||
Value string `protobuf:"bytes,5,opt,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *RuleReply) Reset() { *m = RuleReply{} }
|
||||
|
@ -188,9 +188,9 @@ func (m *RuleReply) GetWhat() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (m *RuleReply) GetWith() string {
|
||||
func (m *RuleReply) GetValue() string {
|
||||
if m != nil {
|
||||
return m.With
|
||||
return m.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -310,27 +310,27 @@ var _UI_serviceDesc = grpc.ServiceDesc{
|
|||
func init() { proto.RegisterFile("ui.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 341 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x51, 0xcd, 0x4a, 0xeb, 0x40,
|
||||
0x14, 0x6e, 0xd3, 0x34, 0x3f, 0xa7, 0xb7, 0xf7, 0xc2, 0xc0, 0x95, 0x58, 0x29, 0xd4, 0xac, 0x0a,
|
||||
0x42, 0x17, 0xfa, 0x04, 0xdd, 0xd9, 0x5d, 0x09, 0xb8, 0x72, 0x51, 0x62, 0x26, 0x34, 0x83, 0xb1,
|
||||
0x33, 0xce, 0x39, 0x41, 0x8a, 0xcf, 0xe0, 0x3b, 0xcb, 0xfc, 0xa4, 0x06, 0xdc, 0x9d, 0xf3, 0xfd,
|
||||
0x31, 0xf3, 0x1d, 0x48, 0x3a, 0xb1, 0x51, 0x5a, 0x92, 0x64, 0x41, 0x27, 0xf2, 0x25, 0xcc, 0xf6,
|
||||
0xe2, 0x74, 0x2c, 0xea, 0xf7, 0xae, 0x46, 0x62, 0x7f, 0x21, 0x10, 0x3c, 0x1b, 0xaf, 0xc6, 0xeb,
|
||||
0xb0, 0x08, 0x04, 0xcf, 0x6f, 0x20, 0x75, 0xb4, 0x6a, 0xcf, 0xbf, 0xc8, 0xaf, 0x00, 0x66, 0x45,
|
||||
0xd7, 0xd6, 0xbd, 0x79, 0x01, 0x89, 0x0d, 0xae, 0x64, 0x6b, 0x55, 0x69, 0x71, 0xd9, 0xd9, 0x7f,
|
||||
0x88, 0x50, 0x57, 0x07, 0xa1, 0xb2, 0xc0, 0x32, 0x53, 0xd4, 0xd5, 0x4e, 0xb1, 0x6b, 0x48, 0x0c,
|
||||
0xac, 0xa4, 0xa6, 0x6c, 0xb2, 0x1a, 0xaf, 0xe7, 0x45, 0x8c, 0xba, 0xda, 0x4b, 0x4d, 0xc6, 0xc1,
|
||||
0x91, 0x8c, 0x23, 0x74, 0x0e, 0x8e, 0xe4, 0x1c, 0x06, 0x6e, 0x24, 0x52, 0x36, 0xb5, 0x44, 0xcc,
|
||||
0x91, 0x1e, 0x25, 0x52, 0x4f, 0xd9, 0xb0, 0xc8, 0x85, 0x71, 0x24, 0x1b, 0xb6, 0x04, 0x50, 0x5a,
|
||||
0x56, 0x35, 0xe2, 0x41, 0xf0, 0x2c, 0xb6, 0x64, 0xea, 0x91, 0x1d, 0x67, 0xb7, 0xf0, 0xa7, 0xa7,
|
||||
0x55, 0x49, 0x4d, 0x96, 0xd8, 0xe0, 0x99, 0xc7, 0xf6, 0x25, 0x35, 0x43, 0x49, 0xa9, 0x8f, 0x98,
|
||||
0xa5, 0xab, 0xc9, 0x40, 0xb2, 0xd5, 0x47, 0xcc, 0x3f, 0x21, 0x75, 0x75, 0x98, 0xb2, 0x18, 0x84,
|
||||
0xa7, 0xf2, 0xad, 0xf6, 0x45, 0xd8, 0x99, 0x5d, 0x41, 0x54, 0x56, 0x24, 0xe4, 0xc9, 0x97, 0xe0,
|
||||
0x37, 0x53, 0x1c, 0xef, 0x74, 0x69, 0x99, 0x89, 0x2b, 0xae, 0xdf, 0x4d, 0xce, 0x47, 0x53, 0x92,
|
||||
0x2f, 0xc1, 0xce, 0x16, 0x13, 0xd4, 0xf8, 0xff, 0xdb, 0xf9, 0xfe, 0x19, 0x82, 0xa7, 0x1d, 0x5b,
|
||||
0x43, 0x68, 0xee, 0xc5, 0xfe, 0x6d, 0x3a, 0xb1, 0x19, 0x1c, 0x76, 0x31, 0xff, 0x01, 0x54, 0x7b,
|
||||
0xce, 0x47, 0xec, 0x0e, 0xe2, 0x2d, 0xbe, 0x9a, 0xf7, 0x3a, 0xf1, 0xe0, 0x90, 0x4e, 0x7c, 0xf9,
|
||||
0x4a, 0x3e, 0x7a, 0x89, 0xec, 0x1d, 0x1f, 0xbe, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd9, 0x36, 0xbf,
|
||||
0xe7, 0x3c, 0x02, 0x00, 0x00,
|
||||
// 343 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x51, 0xcb, 0x4a, 0xc3, 0x40,
|
||||
0x14, 0x6d, 0xd3, 0x34, 0x8f, 0x5b, 0xab, 0x30, 0xa8, 0xc4, 0x4a, 0xa1, 0x66, 0x55, 0x10, 0xba,
|
||||
0xd0, 0x2f, 0xe8, 0xce, 0xee, 0x4a, 0xc0, 0x95, 0x8b, 0x32, 0x66, 0x42, 0x33, 0x18, 0x3b, 0xe3,
|
||||
0xdc, 0x89, 0xd2, 0x85, 0x9f, 0xe0, 0x3f, 0xcb, 0x3c, 0x52, 0x03, 0xee, 0xe6, 0x9e, 0x17, 0xc9,
|
||||
0x39, 0x90, 0xb4, 0x7c, 0x25, 0x95, 0xd0, 0x82, 0x04, 0x2d, 0xcf, 0xe7, 0x30, 0xd9, 0xf2, 0xc3,
|
||||
0xbe, 0xa8, 0x3e, 0xda, 0x0a, 0x35, 0x39, 0x87, 0x80, 0xb3, 0x6c, 0xb8, 0x18, 0x2e, 0xc3, 0x22,
|
||||
0xe0, 0x2c, 0xbf, 0x85, 0xd4, 0xd1, 0xb2, 0x39, 0xfe, 0x23, 0x7f, 0x02, 0x98, 0x14, 0x6d, 0x53,
|
||||
0x75, 0xe6, 0x19, 0x24, 0x36, 0xb8, 0x14, 0x8d, 0x55, 0xa5, 0xc5, 0xe9, 0x26, 0x57, 0x10, 0xa1,
|
||||
0x2a, 0x77, 0x5c, 0x66, 0x81, 0x65, 0xc6, 0xa8, 0xca, 0x8d, 0x24, 0x37, 0x90, 0x18, 0x58, 0x0a,
|
||||
0xa5, 0xb3, 0xd1, 0x62, 0xb8, 0x9c, 0x16, 0x31, 0xaa, 0x72, 0x2b, 0x94, 0x36, 0x0e, 0x86, 0xda,
|
||||
0x38, 0x42, 0xe7, 0x60, 0xa8, 0x9d, 0xc3, 0xc0, 0xb5, 0x40, 0x9d, 0x8d, 0x2d, 0x11, 0x33, 0xd4,
|
||||
0x4f, 0x02, 0x75, 0x47, 0xd9, 0xb0, 0xc8, 0x85, 0x31, 0xd4, 0x36, 0x6c, 0x0e, 0x20, 0x95, 0x28,
|
||||
0x2b, 0xc4, 0x1d, 0x67, 0x59, 0x6c, 0xc9, 0xd4, 0x23, 0x1b, 0x46, 0xee, 0xe0, 0xac, 0xa3, 0x25,
|
||||
0xd5, 0x75, 0x96, 0xd8, 0xe0, 0x89, 0xc7, 0xb6, 0x54, 0xd7, 0x7d, 0x09, 0x55, 0x7b, 0xcc, 0xd2,
|
||||
0xc5, 0xa8, 0x27, 0x59, 0xab, 0x3d, 0xe6, 0xdf, 0x90, 0xba, 0x3a, 0x4c, 0x59, 0x04, 0xc2, 0x03,
|
||||
0x7d, 0xaf, 0x7c, 0x11, 0xf6, 0x4d, 0xae, 0x21, 0xa2, 0xa5, 0xe6, 0xe2, 0xe0, 0x4b, 0xf0, 0x97,
|
||||
0x29, 0x8e, 0xb5, 0x8a, 0x5a, 0x66, 0xe4, 0x8a, 0xeb, 0x6e, 0x93, 0xf3, 0x55, 0x53, 0xed, 0x4b,
|
||||
0xb0, 0x6f, 0x72, 0x09, 0xe3, 0x4f, 0xda, 0xb4, 0x95, 0x2f, 0xc0, 0x1d, 0x0f, 0x2f, 0x10, 0x3c,
|
||||
0x6f, 0xc8, 0x12, 0x42, 0xb3, 0x18, 0xb9, 0x58, 0xb5, 0x7c, 0xd5, 0x9b, 0x76, 0x36, 0xfd, 0x03,
|
||||
0x64, 0x73, 0xcc, 0x07, 0xe4, 0x1e, 0xe2, 0x35, 0xbe, 0x99, 0x2f, 0x76, 0xe2, 0xde, 0x94, 0x4e,
|
||||
0x7c, 0xfa, 0x99, 0x7c, 0xf0, 0x1a, 0xd9, 0x25, 0x1f, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x8d,
|
||||
0xa3, 0x76, 0xb5, 0x3e, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -32,5 +32,5 @@ message RuleReply {
|
|||
string action = 2;
|
||||
string duration = 3;
|
||||
string what = 4;
|
||||
string with = 5;
|
||||
string value = 5;
|
||||
}
|
||||
|
|
303
ui.proto/ui_pb2.py
Normal file
303
ui.proto/ui_pb2.py
Normal file
|
@ -0,0 +1,303 @@
|
|||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: ui.proto
|
||||
|
||||
import sys
|
||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf import descriptor_pb2
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='ui.proto',
|
||||
package='ui',
|
||||
syntax='proto3',
|
||||
serialized_pb=_b('\n\x08ui.proto\x12\x02ui\"\x19\n\x0bPingRequest\x12\n\n\x02id\x18\x01 \x01(\x04\"\x17\n\tPingReply\x12\n\n\x02id\x18\x01 \x01(\x04\"\xb5\x01\n\x0bRuleRequest\x12\x10\n\x08protocol\x18\x01 \x01(\t\x12\x0e\n\x06src_ip\x18\x02 \x01(\t\x12\x10\n\x08src_port\x18\x03 \x01(\r\x12\x0e\n\x06\x64st_ip\x18\x04 \x01(\t\x12\x10\n\x08\x64st_host\x18\x05 \x01(\t\x12\x10\n\x08\x64st_port\x18\x06 \x01(\r\x12\x12\n\nprocess_id\x18\x07 \x01(\r\x12\x14\n\x0cprocess_path\x18\x08 \x01(\t\x12\x14\n\x0cprocess_args\x18\t \x03(\t\"X\n\tRuleReply\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tion\x18\x02 \x01(\t\x12\x10\n\x08\x64uration\x18\x03 \x01(\t\x12\x0c\n\x04what\x18\x04 \x01(\t\x12\r\n\x05value\x18\x05 \x01(\t2[\n\x02UI\x12(\n\x04Ping\x12\x0f.ui.PingRequest\x1a\r.ui.PingReply\"\x00\x12+\n\x07\x41skRule\x12\x0f.ui.RuleRequest\x1a\r.ui.RuleReply\"\x00\x62\x06proto3')
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
_PINGREQUEST = _descriptor.Descriptor(
|
||||
name='PingRequest',
|
||||
full_name='ui.PingRequest',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='ui.PingRequest.id', index=0,
|
||||
number=1, type=4, cpp_type=4, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=16,
|
||||
serialized_end=41,
|
||||
)
|
||||
|
||||
|
||||
_PINGREPLY = _descriptor.Descriptor(
|
||||
name='PingReply',
|
||||
full_name='ui.PingReply',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='ui.PingReply.id', index=0,
|
||||
number=1, type=4, cpp_type=4, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=43,
|
||||
serialized_end=66,
|
||||
)
|
||||
|
||||
|
||||
_RULEREQUEST = _descriptor.Descriptor(
|
||||
name='RuleRequest',
|
||||
full_name='ui.RuleRequest',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='protocol', full_name='ui.RuleRequest.protocol', index=0,
|
||||
number=1, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='src_ip', full_name='ui.RuleRequest.src_ip', index=1,
|
||||
number=2, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='src_port', full_name='ui.RuleRequest.src_port', index=2,
|
||||
number=3, type=13, cpp_type=3, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='dst_ip', full_name='ui.RuleRequest.dst_ip', index=3,
|
||||
number=4, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='dst_host', full_name='ui.RuleRequest.dst_host', index=4,
|
||||
number=5, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='dst_port', full_name='ui.RuleRequest.dst_port', index=5,
|
||||
number=6, type=13, cpp_type=3, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='process_id', full_name='ui.RuleRequest.process_id', index=6,
|
||||
number=7, type=13, cpp_type=3, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='process_path', full_name='ui.RuleRequest.process_path', index=7,
|
||||
number=8, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='process_args', full_name='ui.RuleRequest.process_args', index=8,
|
||||
number=9, type=9, cpp_type=9, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=69,
|
||||
serialized_end=250,
|
||||
)
|
||||
|
||||
|
||||
_RULEREPLY = _descriptor.Descriptor(
|
||||
name='RuleReply',
|
||||
full_name='ui.RuleReply',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='name', full_name='ui.RuleReply.name', index=0,
|
||||
number=1, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='action', full_name='ui.RuleReply.action', index=1,
|
||||
number=2, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='duration', full_name='ui.RuleReply.duration', index=2,
|
||||
number=3, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='what', full_name='ui.RuleReply.what', index=3,
|
||||
number=4, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='value', full_name='ui.RuleReply.value', index=4,
|
||||
number=5, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=252,
|
||||
serialized_end=340,
|
||||
)
|
||||
|
||||
DESCRIPTOR.message_types_by_name['PingRequest'] = _PINGREQUEST
|
||||
DESCRIPTOR.message_types_by_name['PingReply'] = _PINGREPLY
|
||||
DESCRIPTOR.message_types_by_name['RuleRequest'] = _RULEREQUEST
|
||||
DESCRIPTOR.message_types_by_name['RuleReply'] = _RULEREPLY
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
PingRequest = _reflection.GeneratedProtocolMessageType('PingRequest', (_message.Message,), dict(
|
||||
DESCRIPTOR = _PINGREQUEST,
|
||||
__module__ = 'ui_pb2'
|
||||
# @@protoc_insertion_point(class_scope:ui.PingRequest)
|
||||
))
|
||||
_sym_db.RegisterMessage(PingRequest)
|
||||
|
||||
PingReply = _reflection.GeneratedProtocolMessageType('PingReply', (_message.Message,), dict(
|
||||
DESCRIPTOR = _PINGREPLY,
|
||||
__module__ = 'ui_pb2'
|
||||
# @@protoc_insertion_point(class_scope:ui.PingReply)
|
||||
))
|
||||
_sym_db.RegisterMessage(PingReply)
|
||||
|
||||
RuleRequest = _reflection.GeneratedProtocolMessageType('RuleRequest', (_message.Message,), dict(
|
||||
DESCRIPTOR = _RULEREQUEST,
|
||||
__module__ = 'ui_pb2'
|
||||
# @@protoc_insertion_point(class_scope:ui.RuleRequest)
|
||||
))
|
||||
_sym_db.RegisterMessage(RuleRequest)
|
||||
|
||||
RuleReply = _reflection.GeneratedProtocolMessageType('RuleReply', (_message.Message,), dict(
|
||||
DESCRIPTOR = _RULEREPLY,
|
||||
__module__ = 'ui_pb2'
|
||||
# @@protoc_insertion_point(class_scope:ui.RuleReply)
|
||||
))
|
||||
_sym_db.RegisterMessage(RuleReply)
|
||||
|
||||
|
||||
|
||||
_UI = _descriptor.ServiceDescriptor(
|
||||
name='UI',
|
||||
full_name='ui.UI',
|
||||
file=DESCRIPTOR,
|
||||
index=0,
|
||||
options=None,
|
||||
serialized_start=342,
|
||||
serialized_end=433,
|
||||
methods=[
|
||||
_descriptor.MethodDescriptor(
|
||||
name='Ping',
|
||||
full_name='ui.UI.Ping',
|
||||
index=0,
|
||||
containing_service=None,
|
||||
input_type=_PINGREQUEST,
|
||||
output_type=_PINGREPLY,
|
||||
options=None,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='AskRule',
|
||||
full_name='ui.UI.AskRule',
|
||||
index=1,
|
||||
containing_service=None,
|
||||
input_type=_RULEREQUEST,
|
||||
output_type=_RULEREPLY,
|
||||
options=None,
|
||||
),
|
||||
])
|
||||
_sym_db.RegisterServiceDescriptor(_UI)
|
||||
|
||||
DESCRIPTOR.services_by_name['UI'] = _UI
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
63
ui.proto/ui_pb2_grpc.py
Normal file
63
ui.proto/ui_pb2_grpc.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
import grpc
|
||||
|
||||
import ui_pb2 as ui__pb2
|
||||
|
||||
|
||||
class UIStub(object):
|
||||
# missing associated documentation comment in .proto file
|
||||
pass
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.Ping = channel.unary_unary(
|
||||
'/ui.UI/Ping',
|
||||
request_serializer=ui__pb2.PingRequest.SerializeToString,
|
||||
response_deserializer=ui__pb2.PingReply.FromString,
|
||||
)
|
||||
self.AskRule = channel.unary_unary(
|
||||
'/ui.UI/AskRule',
|
||||
request_serializer=ui__pb2.RuleRequest.SerializeToString,
|
||||
response_deserializer=ui__pb2.RuleReply.FromString,
|
||||
)
|
||||
|
||||
|
||||
class UIServicer(object):
|
||||
# missing associated documentation comment in .proto file
|
||||
pass
|
||||
|
||||
def Ping(self, request, context):
|
||||
# missing associated documentation comment in .proto file
|
||||
pass
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def AskRule(self, request, context):
|
||||
# missing associated documentation comment in .proto file
|
||||
pass
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_UIServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'Ping': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.Ping,
|
||||
request_deserializer=ui__pb2.PingRequest.FromString,
|
||||
response_serializer=ui__pb2.PingReply.SerializeToString,
|
||||
),
|
||||
'AskRule': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.AskRule,
|
||||
request_deserializer=ui__pb2.RuleRequest.FromString,
|
||||
response_serializer=ui__pb2.RuleReply.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'ui.UI', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
1
ui/.gitignore
vendored
Normal file
1
ui/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
*.pyc
|
40
ui/dialog.py
Normal file
40
ui/dialog.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
from PyQt5 import QtCore, QtGui, uic, QtWidgets
|
||||
from PyQt5 import QtDBus
|
||||
import threading
|
||||
import logging
|
||||
import queue
|
||||
import sys
|
||||
import os
|
||||
|
||||
DIALOG_UI_PATH = "%s/res/dialog.ui" % os.path.dirname(sys.modules[__name__].__file__)
|
||||
|
||||
class Dialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
|
||||
def __init__(self, parent=None):
|
||||
QtWidgets.QDialog.__init__(self, parent, QtCore.Qt.WindowStaysOnTopHint)
|
||||
|
||||
self.setupUi(self)
|
||||
|
||||
self._done = threading.Event()
|
||||
self._allow_button = self.findChild(QtWidgets.QPushButton, "allowButton")
|
||||
self._allow_button.clicked.connect(self._on_allow_click)
|
||||
self._block_button = self.findChild(QtWidgets.QPushButton, "denyButton")
|
||||
self._block_button.clicked.connect(self._on_block_click)
|
||||
self._duration_combo = self.findChild(QtWidgets.QComboBox, "actionComboBox")
|
||||
self._duration_combo.currentIndexChanged[str].connect(self._on_duration_changed)
|
||||
|
||||
def promptUser(self, req):
|
||||
self._done.clear()
|
||||
self.show()
|
||||
self._done.wait()
|
||||
|
||||
def _on_duration_changed(self):
|
||||
s_option = self._duration_combo.currentText()
|
||||
|
||||
def _on_allow_click(self):
|
||||
self.hide()
|
||||
self._done.set()
|
||||
|
||||
def _on_block_click(self):
|
||||
self.hide()
|
||||
self._done.set()
|
||||
|
53
ui/main.py
Normal file
53
ui/main.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
from PyQt5 import QtWidgets
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import signal
|
||||
|
||||
path = os.path.abspath(os.path.dirname(__file__))
|
||||
sys.path.append(path)
|
||||
sys.path.append(path + "/../ui.proto/")
|
||||
|
||||
import grpc
|
||||
from concurrent import futures
|
||||
import ui_pb2
|
||||
import ui_pb2_grpc
|
||||
|
||||
from dialog import Dialog
|
||||
|
||||
class UIServicer(ui_pb2_grpc.UIServicer):
|
||||
def __init__(self):
|
||||
self.dialog = Dialog()
|
||||
|
||||
def Ping(self, request, context):
|
||||
# print "Got ping 0x%x" % request.id
|
||||
return ui_pb2.PingReply(id=request.id)
|
||||
|
||||
def AskRule(self, request, context):
|
||||
print "Got request: %s" % request
|
||||
self.dialog.promptUser(request)
|
||||
return ui_pb2.RuleReply(
|
||||
name="user.choice",
|
||||
action="allow",
|
||||
duration="always",
|
||||
what="process.path",
|
||||
value=request.process_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=1))
|
||||
|
||||
ui_pb2_grpc.add_UIServicer_to_server(UIServicer(), server)
|
||||
|
||||
server.add_insecure_port("unix:./opensnitch-ui.sock")
|
||||
|
||||
# https://stackoverflow.com/questions/5160577/ctrl-c-doesnt-work-with-pyqt
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
|
||||
try:
|
||||
server.start()
|
||||
app.exec_()
|
||||
except KeyboardInterrupt:
|
||||
app.quit()
|
||||
server.stop(0)
|
||||
|
184
ui/res/dialog.ui
Normal file
184
ui/res/dialog.ui
Normal file
|
@ -0,0 +1,184 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>653</width>
|
||||
<height>316</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>37</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>490</width>
|
||||
<height>220</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>1000</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>OpenSnitch</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="appNameLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
<width>433</width>
|
||||
<height>42</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>15</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Chromium Web Browser</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="Line" name="line">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>60</y>
|
||||
<width>651</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="messageLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>90</y>
|
||||
<width>611</width>
|
||||
<height>81</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Chromium Web Browser (/usr/lib/chromium-browser) wants to connect to host 127.0.0.1 on TCP port 443 (https)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="denyButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>220</x>
|
||||
<y>260</y>
|
||||
<width>191</width>
|
||||
<height>50</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Block</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="allowButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>260</y>
|
||||
<width>191</width>
|
||||
<height>50</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<strikeout>false</strikeout>
|
||||
</font>
|
||||
</property>
|
||||
<property name="mouseTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="actionComboBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>450</x>
|
||||
<y>260</y>
|
||||
<width>191</width>
|
||||
<height>50</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>97</width>
|
||||
<height>26</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>204</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Once</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Until Quit</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Forever</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
<widget class="QLabel" name="iconLabel">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>590</x>
|
||||
<y>5</y>
|
||||
<width>60</width>
|
||||
<height>60</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Add table
Reference in a new issue