Skip to content

Commit

Permalink
Merge pull request #229 from jumpserver/dev
Browse files Browse the repository at this point in the history
v3.5.0
  • Loading branch information
BaiJiangJie authored Jul 20, 2023
2 parents 0404600 + 52646c8 commit 8ca4d97
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 29 deletions.
14 changes: 6 additions & 8 deletions pkg/jms-sdk-go/model/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,12 @@ type PlatformProtocol struct {
Setting ProtocolSetting `json:"setting"`
}
type ProtocolSetting struct {
Security string `json:"security"`
Console bool `json:"console"`
SftpEnabled bool `json:"sftp_enabled"`
SftpHome string `json:"sftp_home"`
AutoFill bool `json:"auto_fill"`
UsernameSelector string `json:"username_selector"`
PasswordSelector string `json:"password_selector"`
SubmitSelector string `json:"submit_selector"`
Security string `json:"security"`
Console bool `json:"console"`
SftpEnabled bool `json:"sftp_enabled"`
SftpHome string `json:"sftp_home"`
AutoFill bool `json:"auto_fill"`
AdDomain string `json:"ad_domain"`
}

/*
Expand Down
8 changes: 7 additions & 1 deletion pkg/session/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ func (r RDPConfiguration) GetGuacdConfiguration() guacd.Configuration {
//if r.SystemUser.AdDomain != "" {
// conf.SetParameter(guacd.RDPDomain, r.SystemUser.AdDomain)
//}

if r.Platform != nil {
if rdpSetting, ok := r.Platform.GetProtocolSetting("rdp"); ok {
if rdpSetting.Setting.AdDomain != "" {
conf.SetParameter(guacd.RDPDomain, rdpSetting.Setting.AdDomain)
}
}
}
// 设置 录像路径
if r.TerminalConfig.ReplayStorage.TypeName != "null" {
recordDirPath := filepath.Join(config.GlobalConfig.RecordPath,
Expand Down
16 changes: 10 additions & 6 deletions pkg/tunnel/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (t *Connection) Run(ctx *gin.Context) (err error) {
switch instruction.Opcode {
case guacd.InstructionServerDisconnect,
guacd.InstructionServerError:
logger.Infof("Session[%s] receive guacamole server disconnect opcode", t)
logger.Infof("Session[%s] receive guacamole server disconnect: %s", t, instruction.String())
case guacd.InstructionStreamingAck:
select {
case activeChan <- struct{}{}:
Expand Down Expand Up @@ -179,17 +179,21 @@ func (t *Connection) Run(ctx *gin.Context) (err error) {
continue
}

switch ret.Opcode {
case guacd.InstructionKey:
userInputMessageChan <- &session.Message{
Opcode: ret.Opcode, Body: ret.Args,
Meta: meta}
default:

}

switch ret.Opcode {
case guacd.InstructionClientSync,
guacd.InstructionClientNop,
guacd.InstructionStreamingAck:
case guacd.InstructionClientDisconnect:
logger.Errorf("Session[%s] receive web client disconnect opcode", t)
case guacd.InstructionKey:
userInputMessageChan <- &session.Message{
Opcode: ret.Opcode, Body: ret.Args,
Meta: meta}
fallthrough
default:
select {
case activeChan <- struct{}{}:
Expand Down
12 changes: 9 additions & 3 deletions pkg/tunnel/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
)

type MonitorCon struct {
Id string
guacdTunnel Tunneler

ws *websocket.Conn
Expand Down Expand Up @@ -53,7 +54,8 @@ func (m *MonitorCon) Run(ctx context.Context) (err error) {
for {
instruction, err := t.readTunnelInstruction()
if err != nil {
logger.Error(err)
_ = t.writeWsMessage([]byte(ErrDisconnect.String()))
logger.Infof("Monitor[%s] guacd tunnel read err: %+v", t.Id, err)
exit <- err
break
}
Expand All @@ -70,6 +72,8 @@ func (m *MonitorCon) Run(ctx context.Context) (err error) {
for {
_, message, err := t.ws.ReadMessage()
if err != nil {
logger.Infof("Monitor[%s] ws read err: %+v", t.Id, err)

exit <- err
break
}
Expand All @@ -82,11 +86,11 @@ func (m *MonitorCon) Run(ctx context.Context) (err error) {
continue
}
} else {
logger.Errorf("Parse instruction err %s", err)
logger.Errorf("Monitor[%s] parse instruction err %s", t.Id, err)
}
_, err = t.writeTunnelMessage(message)
if err != nil {
logger.Errorf("Guacamole server write err: %+v", err)
logger.Errorf("Monitor[%s] guacamole tunnel write err: %+v", t.Id, err)
exit <- err
break
}
Expand All @@ -97,8 +101,10 @@ func (m *MonitorCon) Run(ctx context.Context) (err error) {
for {
select {
case err = <-exit:
logger.Infof("Monitor[%s] exit: %+v", m.Id, err)
return err
case <-ctx.Done():
logger.Info("Monitor[%s] done", m.Id)
return nil
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/tunnel/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ func (g *GuacamoleTunnelServer) Monitor(ctx *gin.Context) {
}
defer tunnelCon.Close()
conn := MonitorCon{
Id: sessionId,
guacdTunnel: tunnelCon,
ws: ws,
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/tunnel/ws_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@ var (
ErrGuacamoleServer = NewJMSGuacamoleError(1008, "Connect guacamole server failed")

ErrPermission = NewJMSGuacamoleError(256, "No permission")

ErrDisconnect = NewJMSGuacamoleError(1009, "Disconnect by client")
)
6 changes: 3 additions & 3 deletions ui/src/components/GuacamoleConnect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<RightPanel>
<Settings :settings="settings" :title="$t('Settings')">
<el-button type="text" class="item-button el-icon-c-scale-to-original">
{{ $t('Display') }}
{{ $t('Display') }}
</el-button>
<div class="content"> <i class="el-icon-remove-outline" @click="decreaseScale" />
<span>{{ scaleValue }}%</span>
Expand Down Expand Up @@ -62,7 +62,7 @@ import GuacFileSystem from './GuacFileSystem'
import RightPanel from './RightPanel'
import Settings from './Settings'
import { default as i18n, getLanguage } from '@/i18n'
import { ErrorStatusCodes, ConvertAPIError } from '@/utils'
import { ErrorStatusCodes, ConvertAPIError, ConvertGuacamoleError } from '@/utils'
import { localStorageGet } from '@/utils/common'
const pixelDensity = 1
Expand Down Expand Up @@ -505,7 +505,7 @@ export default {
const code = status.code
let msg = status.message
const currentLang = getLanguage()
msg = ErrorStatusCodes[code] ? this.$t(ErrorStatusCodes[code]) : status.message
msg = ErrorStatusCodes[code] ? this.$t(ErrorStatusCodes[code]) : this.$t(ConvertGuacamoleError(status.message))
switch (code) {
case 1005:
// 管理员终断会话,特殊处理
Expand Down
8 changes: 3 additions & 5 deletions ui/src/components/GuacamoleMonitor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import { getMonitorConnectParams } from '@/utils/common'
import { getSupportedMimetypes } from '@/utils/image'
import { getSupportedGuacAudios } from '@/utils/audios'
import { getSupportedGuacVideos } from '@/utils/video'
import { getLanguage } from '@/i18n'
import { ErrorStatusCodes } from '@/utils/status'
import { ConvertGuacamoleError, ErrorStatusCodes } from '@/utils/status'
const pixelDensity = window.devicePixelRatio || 1
export default {
Expand Down Expand Up @@ -220,9 +219,7 @@ export default {
this.$log.debug(status, i18n.locale)
const code = status.code
let msg = status.message
if (getLanguage() === 'cn') {
msg = ErrorStatusCodes[code] ? this.$t(ErrorStatusCodes[code]) : status.message
}
msg = ErrorStatusCodes[code] ? this.$t(ErrorStatusCodes[code]) : this.$t(ConvertGuacamoleError(status.message))
this.$alert(msg, this.$t('ErrTitle'), {
confirmButtonText: this.$t('OK'),
callback: action => {
Expand All @@ -239,6 +236,7 @@ export default {
const tunnel = new Guacamole.WebSocketTunnel(wsURL)
const client = new Guacamole.Client(tunnel)
const vm = this
tunnel.receiveTimeout = 60 * 1000
tunnel.onerror = function tunnelError(status) {
vm.$log.debug('tunnelError ', status)
display.innerHTML = ''
Expand Down
24 changes: 23 additions & 1 deletion ui/src/i18n/lang/cn.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const message = {
JMSErrAPIFailed: 'Core API 发生错误',
JMSErrGatewayFailed: '网关连接失败',
JMSErrGuacamoleServer: '无法连接 Guacamole 服务器',
JMSErrDisconnected: '会话连接已断开',
GuaErrUpstreamNotFound: '无法连接到远程桌面服务器(网络不可达 | 安全策略错误)',
GuaErrSessionConflict: '因与另一个连接冲突,远程桌面服务器关闭了本连接。请稍后重试。',
GuaErrClientUnauthorized: '用户名和密码认证错误,登录失败',
Expand All @@ -34,7 +35,28 @@ const message = {
Settings: '设置',
UploadSuccess: '上传成功',
Display: '显示',
AutoFit: '自动适应'
AutoFit: '自动适应',

GuacamoleErrDisconnected: '远程连接断开',
GuacamoleErrCredentialsExpired: '远程连接的凭证过期',
GuacamoleErrSecurityNegotiationFailed: '远程连接的安全协商失败',
GuacamoleErrAccessDenied: '远程连接的访问被拒绝',
GuacamoleErrAuthenticationFailure: '远程连接的认证失败',
GuacamoleErrSSLTLSConnectionFailed: '远程连接的 SSL/TLS 连接失败',
GuacamoleErrDNSLookupFailed: '远程连接的 DNS 查询失败',
GuacamoleErrServerRefusedConnectionBySecurityType: '远程连接的服务器拒绝连接,可能安全类型不匹配',
GuacamoleErrConnectionFailed: '远程连接失败',
GuacamoleErrUpstreamError: '远程连接的服务器发生错误',
GuacamoleErrForciblyDisconnected: '远程连接被强制断开',
GuacamoleErrLoggedOff: '远程连接的用户已注销',
GuacamoleErrIdleSessionTimeLimitExceeded: '远程连接的空闲时间超过限制',
GuacamoleErrActiveSessionTimeLimitExceeded: '远程连接的活动时间超过限制',
GuacamoleErrDisconnectedByOtherConnection: '远程连接被其他连接断开',
GuacamoleErrServerRefusedConnection: '远程连接的服务器拒绝连接',
GuacamoleErrInsufficientPrivileges: '远程连接的用户权限不足',
GuacamoleErrManuallyDisconnected: '远程连接被手动断开',
GuacamoleErrManuallyLoggedOff: '远程连接的用户被手动注销',
GuacamoleErrUnsupportedCredentialTypeRequested: '远程连接的凭证类型不支持'
}

export default {
Expand Down
24 changes: 23 additions & 1 deletion ui/src/i18n/lang/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const message = {
JMSErrAPIFailed: 'Core API failed',
JMSErrGatewayFailed: 'Gateway not available',
JMSErrGuacamoleServer: 'Connect guacamole server failed',
JMSErrDisconnected: 'Session Disconnected',
GuaErrUpstreamNotFound: 'The remote desktop server does not appear to exist, or cannot be reached over the network.',
GuaErrSessionConflict: 'The session has ended because it conflicts with another session.',
GuaErrClientUnauthorized: 'User failed to logged in. (username and password are incorrect)',
Expand All @@ -33,7 +34,28 @@ const message = {
Settings: 'Settings',
UploadSuccess: 'Upload success',
Display: 'Display',
AutoFit: 'Auto Fit'
AutoFit: 'Auto Fit',

GuacamoleErrDisconnected: 'Disconnected.',
GuacamoleErrCredentialsExpired: 'Credentials expired.',
GuacamoleErrSecurityNegotiationFailed: 'Security negotiation failed (wrong security type?)',
GuacamoleErrAccessDenied: 'Access denied by server (account locked/disabled?)',
GuacamoleErrAuthenticationFailure: 'Authentication failure (invalid credentials?)',
GuacamoleErrSSLTLSConnectionFailed: 'SSL/TLS connection failed (untrusted/self-signed certificate?)',
GuacamoleErrDNSLookupFailed: 'DNS lookup failed (incorrect hostname?)',
GuacamoleErrServerRefusedConnectionBySecurityType: 'Server refused connection (wrong security type?)',
GuacamoleErrConnectionFailed: 'Connection failed (server unreachable?)',
GuacamoleErrUpstreamError: 'Upstream error.',
GuacamoleErrForciblyDisconnected: 'Forcibly disconnected.',
GuacamoleErrLoggedOff: 'Logged off.',
GuacamoleErrIdleSessionTimeLimitExceeded: 'Idle session time limit exceeded.',
GuacamoleErrActiveSessionTimeLimitExceeded: 'Active session time limit exceeded.',
GuacamoleErrDisconnectedByOtherConnection: 'Disconnected by other connection.',
GuacamoleErrServerRefusedConnection: 'Server refused connection.',
GuacamoleErrInsufficientPrivileges: 'Insufficient privileges.',
GuacamoleErrManuallyDisconnected: 'Manually disconnected.',
GuacamoleErrManuallyLoggedOff: 'Manually logged off.',
GuacamoleErrUnsupportedCredentialTypeRequested: 'Unsupported credential type requested.'
}

export default {
Expand Down
34 changes: 33 additions & 1 deletion ui/src/utils/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export const ErrorStatusCodes = {
1005: 'JMSErrTerminatedByAdmin',
1006: 'JMSErrAPIFailed',
1007: 'JMSErrGatewayFailed',
1008: 'JMSErrGuacamoleServer'
1008: 'JMSErrGuacamoleServer',
1009: 'JMSErrDisconnected'
}

export function ConvertAPIError(errMsg) {
Expand All @@ -32,3 +33,34 @@ export const APIErrorType = {
'unsupported protocol': 'JMSErrBadParams',
'permission deny': 'JMSErrPermission'
}

export function ConvertGuacamoleError(errMsg) {
if (typeof errMsg !== 'string') {
return errMsg
}
return GuacamoleErrMsg[errMsg] || errMsg
}

export const GuacamoleErrMsg = {
'Disconnected.': 'GuacamoleErrDisconnected',
'Credentials expired.': 'GuacamoleErrCredentialsExpired',
'Security negotiation failed (wrong security type?)': 'GuacamoleErrSecurityNegotiationFailed',
'Access denied by server (account locked/disabled?)': 'GuacamoleErrAccessDenied',
'Authentication failure (invalid credentials?)': 'GuacamoleErrAuthenticationFailure',
'SSL/TLS connection failed (untrusted/self-signed certificate?)': 'GuacamoleErrSSLTLSConnectionFailed',
'DNS lookup failed (incorrect hostname?)': 'GuacamoleErrDNSLookupFailed',
'Server refused connection (wrong security type?)': 'GuacamoleErrServerRefusedConnectionBySecurityType',
'Connection failed (server unreachable?)': 'GuacamoleErrConnectionFailed',
'Upstream error.': 'GuacamoleErrUpstreamError',
'Forcibly disconnected.': 'GuacamoleErrForciblyDisconnected',
'Logged off.': 'GuacamoleErrLoggedOff',
'Idle session time limit exceeded.': 'GuacamoleErrIdleSessionTimeLimitExceeded',
'Active session time limit exceeded.': 'GuacamoleErrActiveSessionTimeLimitExceeded',
'Disconnected by other connection.': 'GuacamoleErrDisconnectedByOtherConnection',
'Server refused connection.': 'GuacamoleErrServerRefusedConnection',
'Insufficient privileges.': 'GuacamoleErrInsufficientPrivileges',
'Manually disconnected.': 'GuacamoleErrManuallyDisconnected',
'Manually logged off.': 'GuacamoleErrManuallyLoggedOff',

'Unsupported credential type requested.': 'GuacamoleErrUnsupportedCredentialTypeRequested'
}

0 comments on commit 8ca4d97

Please sign in to comment.