shadow1ng/fscan · error

Not a valid license packet

Error message

Not a valid license packet

What it means

During the RDP connect sequence, the client received a licensing PDU whose message type is not one it handles (e.g. not PLATFORM_CHALLENGE). The sec layer cannot process the license packet, emits the error on the 'error' channel, and aborts the connection before emitting 'connect'. It indicates the server sent an unexpected licensing message type.

Source

Thrown at libs/grdp/protocol/sec/sec.go:757

		goto connect
	case lic.ERROR_ALERT:
		message := p.LicensingMessage.(*lic.ErrorMessage)
		glog.Info("sec ERROR_ALERT and ErrorCode:", message.DwErrorCode)
		if message.DwErrorCode == lic.STATUS_VALID_CLIENT && message.DwStateTransaction == lic.ST_NO_TRANSITION {
			goto connect
		}
		goto retry
	case lic.LICENSE_REQUEST:
		glog.Info("sec LICENSE_REQUEST")
		c.sendClientNewLicenseRequest(p.LicensingMessage.([]byte))
		goto retry
	case lic.PLATFORM_CHALLENGE:
		glog.Info("sec PLATFORM_CHALLENGE")
		c.sendClientChallengeResponse(p.LicensingMessage.([]byte))
		goto retry
	default:
		glog.Error("Not a valid license packet")
		c.Emit("error", errors.New("Not a valid license packet"))
		return
	}

connect:
	c.transport.On("sec", c.recvData)
	c.Emit("connect", c.clientData[0].(*gcc.ClientCoreData), c.userId, c.channelId)
	return

retry:
	c.transport.Once("sec", c.recvLicenceInfo)
	return
}

func (c *Client) sendClientNewLicenseRequest(data []byte) {
	var req lic.ServerLicenseRequest
	struc.Unpack(bytes.NewReader(data), &req)

	var sc gcc.ServerCertificate

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Identify the server product; if it is xrdp/FreeRDP-based, update the server or grdp to a version handling its license PDU type
  2. Capture the licensing PDU (e.g. Wireshark with RDP decryption) and add a case for the received message type in the license switch, treating it like PLATFORM_CHALLENGE or ignoring it
  3. Try disabling NLA/licensing-sensitive negotiation (set security level to standard RDP or TLS-only) so the server sends a simpler license flow
  4. Verify you are actually talking to an RDP server on that port and not another service that emits garbage in the license slot

Example fix

// before
default:
    glog.Error("Not a valid license packet")
    c.Emit("error", errors.New("Not a valid license packet"))
    return

// after
case lic.LICENSE_VALID_CLIENT, lic.NEW_LICENSE:
    glog.Info("sec: license accepted, continuing")
    goto retry
default:
    glog.Errorf("Not a valid license packet: type %v", p.LicensingMessage)
    c.Emit("error", errors.New("Not a valid license packet"))
    return
Defensive patterns

Strategy: try-catch

Validate before calling

// before connecting, verify the server speaks RDP
conn, _ := net.DialTimeout("tcp", host+":3389", 5*time.Second)
// X.224 negotiation completes only against a real RDP endpoint; also ensure server version supports this client's license handling
_ = conn

Try / catch

client.On("error", func(err error) {
    if strings.Contains(err.Error(), "Not a valid license packet") {
        // fall back: retry with different requestedProtocols or flag server for manual review
    }
})

Prevention

When it happens

Trigger: Calling client.Connect()/NewClient against an RDP server whose licensing PDU uses a message type other than PLATFORM_CHALLENGE (e.g. valid-client license, error alert, or a malformed/garbage packet landing in the license switch's default branch).

Common situations: Connecting to non-Windows or partially implemented RDP servers (xrdp, FreeRDP-based gateways, VNC-over-RDP bridges) that send licensing data this library doesn't understand; middleboxes/proxies corrupting the license PDU; targeting servers that skip standard licensing negotiation.

Related errors


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