shadow1ng/fscan · warning

unhandle server gcc block %v

Error message

unhandle server gcc block %v

What it means

After decoding the MCS Connect Response, recvConnectResponse parses the embedded GCC blocks from userData. The library only handles ServerSecurityData, ServerCoreData and ServerNetworkData; any other GCC block type hits the default branch and emits this error with the block's reflect.TypeOf name. It means the server sent GCC server settings this client cannot process.

Source

Thrown at libs/grdp/protocol/t125/mcs.go:331

	if err != nil {
		c.Emit("error", errors.New(fmt.Sprintf("ReadConnectResponse %v", err)))
		return
	}
	// record server gcc block
	serverSettings := gcc.ReadConferenceCreateResponse(cResp.userData)
	for _, v := range serverSettings {
		switch v.(type) {
		case *gcc.ServerSecurityData:
			c.serverSecurityData = v.(*gcc.ServerSecurityData)

		case *gcc.ServerCoreData:
			c.serverCoreData = v.(*gcc.ServerCoreData)

		case *gcc.ServerNetworkData:
			c.serverNetworkData = v.(*gcc.ServerNetworkData)

		default:
			err := errors.New(fmt.Sprintf("unhandle server gcc block %v", reflect.TypeOf(v)))
			glog.Error(err)
			c.Emit("error", err)
			return
		}
	}
	glog.Debugf("serverSecurityData: %+v", c.serverSecurityData)
	glog.Debugf("serverCoreData: %+v", c.serverCoreData)
	glog.Info("version", c.serverCoreData.RdpVersion, c.serverCoreData.ClientRequestedProtocol)
	glog.Debugf("serverNetworkData: %+v", c.serverNetworkData)
	glog.Debug("mcs sendErectDomainRequest")
	c.sendErectDomainRequest()

	glog.Debug("mcs sendAttachUserRequest")
	c.sendAttachUserRequest()

	c.transport.Once("data", c.recvAttachUserConfirm)
}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Note the type name printed in the error and add a case for that GCC block type in recvConnectResponse (parse or skip it).
  2. For unknown-but-harmless blocks, change the default branch to log a warning and continue instead of returning an error.
  3. Compare with FreeRDP behavior for the same server to see which GCC blocks are standard for that target.
  4. Check gcc.ReadConferenceCreateResponse parsing — a misaligned stream can fabricate spurious block types.

Example fix

// before
default:
    err := errors.New(fmt.Sprintf("unhandle server gcc block %v", reflect.TypeOf(v)))
    glog.Error(err)
    c.Emit("error", err)
    return
// after
default:
    glog.Warn("ignoring server gcc block", reflect.TypeOf(v)) // skip unknown blocks instead of failing
Defensive patterns

Strategy: fallback

Validate before calling

// Inspect which GCC block types a server sends before connecting:
for _, v := range gcc.ReadConferenceCreateResponse(userData) {
    glog.Debug("gcc block:", reflect.TypeOf(v))
}

Try / catch

mcs.On("error", func(err error) {
    if strings.Contains(err.Error(), "unhandle server gcc block") {
        // proceed with defaults or patch grdp to skip the unknown block
    }
})

Prevention

When it happens

Trigger: gcc.ReadConferenceCreateResponse returns a settings list containing a block whose concrete type is none of *gcc.ServerSecurityData, *gcc.ServerCoreData, *gcc.ServerNetworkData — e.g. a ServerMessageChannelData or Monitor Data block — during recvConnectResponse.

Common situations: Connecting to servers that include additional GCC blocks (xrdp, virtualization hosts, RDP brokers with load-balance/monitor data); a newer server OS adding settings this fork of grdp does not implement; a mis-parsed userData stream producing a bogus block type.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/00f285f39218bb32. Report an issue: GitHub.