Client using AdminUID can now use the proxy without adding themselves to the db

pull/2/head
Qian Wang 6 years ago
parent ed1253ff4c
commit 36a743c3ca

@ -75,7 +75,7 @@ func adminHandshake(sta *client.State) (*administrator, error) {
return a, nil
}
func (a *administrator) getCommand() []byte {
func (a *administrator) getRequest() (req []byte, err error) {
fmt.Println("Select your command")
fmt.Println(`1 listActiveUsers none []uids
2 listAllUsers none []userinfo
@ -85,15 +85,18 @@ func (a *administrator) getCommand() []byte {
fmt.Scanln(&cmd)
switch cmd {
case "1":
return a.request([]byte{0x01})
req = a.request([]byte{0x01})
return
case "2":
return a.request([]byte{0x02})
req = a.request([]byte{0x02})
return
case "3":
fmt.Println("Enter UID")
var b64UID string
fmt.Scanln(&b64UID)
UID, _ := base64.StdEncoding.DecodeString(b64UID)
return a.request(append([]byte{0x03}, UID...))
req = a.request(append([]byte{0x03}, UID...))
return
case "4":
var uinfo UserInfo
var b64UID string
@ -114,9 +117,10 @@ func (a *administrator) getCommand() []byte {
fmt.Printf("ExpiryTime:")
fmt.Scanf("%d", &uinfo.ExpiryTime)
marshed, _ := json.Marshal(uinfo)
return a.request(append([]byte{0x04}, marshed...))
req = a.request(append([]byte{0x04}, marshed...))
return
default:
return nil
return nil, errors.New("Unreconised cmd")
}
}

@ -86,9 +86,14 @@ func adminPrompt(sta *client.State) error {
if err != nil {
return err
}
log.Println(err)
buf := make([]byte, 16000)
for {
req := a.getCommand()
req, err := a.getRequest()
if err != nil {
log.Println(err)
continue
}
a.adminConn.Write(req)
n, err := a.adminConn.Read(buf)
if err != nil {
@ -112,7 +117,7 @@ func main() {
// The proxy port,should be 443
var remotePort string
var pluginOpts string
var isAdmin bool
var isAdmin *bool
log.SetFlags(log.LstdFlags | log.Lshortfile)
@ -131,7 +136,7 @@ func main() {
flag.StringVar(&remotePort, "p", "443", "remotePort: proxy port, should be 443")
flag.StringVar(&pluginOpts, "c", "ckclient.json", "pluginOpts: path to ckclient.json or options seperated with semicolons")
askVersion := flag.Bool("v", false, "Print the version number")
isAdmin = *flag.Bool("a", false, "Admin mode")
isAdmin = flag.Bool("a", false, "Admin mode")
printUsage := flag.Bool("h", false, "Print this message")
flag.Parse()
@ -151,7 +156,12 @@ func main() {
// sessionID is usergenerated. There shouldn't be a security concern because the scope of
// sessionID is limited to its UID.
rand.Seed(time.Now().UnixNano())
sessionID := rand.Uint32()
var sessionID uint32
if *isAdmin {
sessionID = 0
} else {
sessionID = rand.Uint32()
}
// opaque is used to generate the padding of session ticket
sta := client.InitState(localHost, localPort, remoteHost, remotePort, time.Now, sessionID)
@ -160,7 +170,7 @@ func main() {
log.Fatal(err)
}
if isAdmin {
if *isAdmin {
err = adminPrompt(sta)
if err != nil {
log.Println(err)

@ -16,6 +16,7 @@ import (
mux "github.com/cbeuw/Cloak/internal/multiplex"
"github.com/cbeuw/Cloak/internal/server"
"github.com/cbeuw/Cloak/internal/server/usermanager"
"github.com/cbeuw/Cloak/internal/util"
)
@ -78,13 +79,12 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
return
}
if bytes.Equal(UID, sta.AdminUID) {
finishHandshake := func() error {
reply := server.ComposeReply(ch)
_, err = conn.Write(reply)
if err != nil {
log.Printf("Sending reply to remote: %v\n", err)
go conn.Close()
return
return err
}
// Two discarded messages: ChangeCipherSpec and Finished
@ -92,12 +92,19 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
for c := 0; c < 2; c++ {
_, err = util.ReadTLS(conn, discardBuf)
if err != nil {
log.Printf("Reading discarded message %v: %v\n", c, err)
go conn.Close()
return
return err
}
}
return nil
}
if bytes.Equal(UID, sta.AdminUID) && sessionID == 0 {
err = finishHandshake()
if err != nil {
log.Println(err)
return
}
c := sta.Userpanel.MakeController(sta.AdminUID)
for {
n, err := conn.Read(data)
@ -107,6 +114,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
}
resp, err := c.HandleRequest(data[:n])
if err != nil {
log.Println(err)
return
}
_, err = conn.Write(resp)
@ -117,33 +125,26 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
}
}
user, err := sta.Userpanel.GetAndActivateUser(UID)
var user *usermanager.User
if bytes.Equal(UID, sta.AdminUID) {
user, err = sta.Userpanel.GetAndActivateAdminUser(UID)
} else {
user, err = sta.Userpanel.GetAndActivateUser(UID)
}
if err != nil {
log.Printf("+1 unauthorised user from %v, uid: %x\n", conn.RemoteAddr(), UID)
goWeb(data)
return
}
reply := server.ComposeReply(ch)
_, err = conn.Write(reply)
err = finishHandshake()
if err != nil {
log.Printf("Sending reply to remote: %v\n", err)
go conn.Close()
log.Println(err)
return
}
// Two discarded messages: ChangeCipherSpec and Finished
discardBuf := make([]byte, 1024)
for c := 0; c < 2; c++ {
_, err = util.ReadTLS(conn, discardBuf)
if err != nil {
log.Printf("Reading discarded message %v: %v\n", c, err)
go conn.Close()
return
}
}
if sesh, existing := user.GetOrCreateSession(sessionID, mux.MakeObfs(UID), mux.MakeDeobfs(UID), util.ReadTLS); existing {
if sesh, existing := user.GetSession(sessionID, mux.MakeObfs(UID), mux.MakeDeobfs(UID), util.ReadTLS); existing {
sesh.AddConnection(conn)
return
} else {

@ -12,7 +12,6 @@ type Deobfser func([]byte) (*Frame, error)
// For each frame, the three parts of the header is xored with three keys.
// The keys are generated from the SID and the payload of the frame.
// FIXME: this code will panic if len(data)<18.
func genXorKeys(secret []byte, data []byte) (i uint32, ii uint32, iii uint32) {
h := xxhash.New32()
ret := make([]uint32, 3)

@ -17,7 +17,7 @@ var ErrBrokenSession = errors.New("broken session")
var errRepeatSessionClosing = errors.New("trying to close a closed session")
type Session struct {
id uint32 // This field isn't acutally used
id uint32
// Used in Stream.Write. Add multiplexing headers, encrypt and add TLS header
obfs Obfser

@ -16,6 +16,7 @@ type rawConfig struct {
WebServerAddr string
PrivateKey string
AdminUID string
SingleUser bool
}
type stateManager interface {
ParseConfig(string) error

@ -65,13 +65,6 @@ func (u *User) updateInfo(uinfo UserInfo) {
u.setExpiryTime(uinfo.ExpiryTime)
}
func (u *User) GetSession(sessionID uint32) *mux.Session {
u.sessionsM.RLock()
sesh := u.sessions[sessionID]
u.sessionsM.RUnlock()
return sesh
}
func (u *User) PutSession(sessionID uint32, sesh *mux.Session) {
u.sessionsM.Lock()
u.sessions[sessionID] = sesh
@ -89,7 +82,7 @@ func (u *User) DelSession(sessionID uint32) {
u.sessionsM.Unlock()
}
func (u *User) GetOrCreateSession(sessionID uint32, obfs mux.Obfser, deobfs mux.Deobfser, obfsedRead func(net.Conn, []byte) (int, error)) (sesh *mux.Session, existing bool) {
func (u *User) GetSession(sessionID uint32, obfs mux.Obfser, deobfs mux.Deobfser, obfsedRead func(net.Conn, []byte) (int, error)) (sesh *mux.Session, existing bool) {
// TODO: session cap
u.sessionsM.Lock()
if sesh = u.sessions[sessionID]; sesh != nil {

@ -92,6 +92,31 @@ func (up *Userpanel) backupDB(bakPath string) error {
var ErrUserNotFound = errors.New("User does not exist in db")
var ErrUserNotActive = errors.New("User is not active")
func (up *Userpanel) GetAndActivateAdminUser(AdminUID []byte) (*User, error) {
up.activeUsersM.Lock()
var arrUID [32]byte
copy(arrUID[:], AdminUID)
if user, ok := up.activeUsers[arrUID]; ok {
up.activeUsersM.Unlock()
return user, nil
}
uinfo := UserInfo{
UID: AdminUID,
SessionsCap: 1e9,
UpRate: 1e12,
DownRate: 1e12,
UpCredit: 1e15,
DownCredit: 1e15,
ExpiryTime: 1e15,
}
user := MakeUser(up, &uinfo)
up.activeUsers[arrUID] = user
up.activeUsersM.Unlock()
return user, nil
}
// TODO: expiry check
// GetUser is used to retrieve a user if s/he is active, or to retrieve the user's infor
@ -253,7 +278,6 @@ func (up *Userpanel) addNewUser(uinfo UserInfo) error {
if err != nil {
return err
}
// FIXME: obnoxious code
if err = b.Put([]byte("SessionsCap"), u32ToB(uinfo.SessionsCap)); err != nil {
return err
}

Loading…
Cancel
Save