實際的環境中,有些用戶使用了非ASCII碼的用戶名或者密碼,這里引發了兩個問題:
- 在非NLA驗證中,如果沒有把這些字符串正常的轉換成Unicode并發送出去,會導致在RDP協議驗證過程中失敗。因為是在Javascript端做的這個事情,所以要格外注意這一點。Javascript使用的是UTF-16 (也就是Windows里所謂的Unicode)。這種情況下,要注意區分
String.prototype.charCodeAt()
獲取到的值是 ASCII 范圍內的,還是超出這個范圍的,以組成正確的Windows可讀的Unicode的字符串。
示例:
function rdp_write_unicode_string(stream, string, len) {
var j=0, i=0;
while(i < len) {
var code = string.charCodeAt(j++);
if (code > 256) {
code &= 0xffff;
stream.data[stream.p+i] = code & 0xff;
i++;
stream.data[stream.p+i] = (code>>8) & 0xff;
i++;
}
else {
stream.data[stream.p+i] = code;
i++;
stream.data[stream.p+i] = 0;
i++;
}
}
stream.data[stream.p+i] = 0;
i++;
stream.data[stream.p+i] = 0;
i++;
stream.p += len + 2;
}
- 還有一種是NLA驗證,這種情況下有可能引起問題的是CharUpperW這個類型的函數。因為在NLA驗證中,協議要求(可能如此,根據現有的開源代碼進行的推斷)把用戶名和密碼轉換成全大寫的字符串。問題在于,在非Windows系統中想要做到這點(支持非ASCII碼)是比較困難的。FreeRDP中有個關于這個的Issue。最后能找到的解決方案實際上是從Wine這個項目中得到的。在非Windows系統中想要做到CharUpperW,需要使用Wine的相同的功能的函數。并且,需要引入一個自動生成的Map,Map文件的位置是casemap.c。 對于只關心轉化到大寫的人來說,只要引入wine_casemap_upper 這個Map就可以了。