使用GCDAsyncSocket通过套接字进行Telnet [英] Telnet over a socket with GCDAsyncSocket
问题描述
我正在尝试从目标c通过telnet连接到Cisco C40编解码器.在计算机上使用终端时,我得到:
I'm trying to connect to a Cisco C40 codec via telnet from objective c. When using the terminal on my computer I get:
密码:
但是,在进行套接字连接时,需要进行telnet协商.我是哪位,但由于某种原因,我无法进入上方的密码:"提示.
However when doing a socket connection there are telnet negotiations that need to be made. Which I am but for some reason I cannot get to the "Password:" prompt above.
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
NSLog(@"RECEIVE BUFFER %@",data);
//store read bytes to rawData
self.rawData = [[NSMutableData alloc] initWithData:data];
//cast bytes
const uint8_t *bytes = [self.rawData bytes];
//go through rawdata format and save it to networkbuffer
for (int i =0; i < [self.rawData length]; i++)
{
if (![[NSString stringWithFormat:@"%02X", bytes[i]]isEqual:@"0D"])
{
[self.networkBuffer addObject:[NSString stringWithFormat:@"%02X", bytes[i]]];
}
}
//negotiate any telnet protocal stuff (just accept options )
//example:
//FF:FD:18 returns FF:FB:18
while([[self.networkBuffer objectAtIndex:0]isEqualToString:@"FF"] && [[self.networkBuffer objectAtIndex:1]isEqualToString:@"FD"] ) {
// NSLog(@"HERE");
NSData * tempData =[data subdataWithRange:NSMakeRange(0, 3)];
NSMutableData * tempMutData = [NSMutableData dataWithData:tempData];
const unsigned char replacement[] = {
0xFC
};
[tempMutData replaceBytesInRange:NSMakeRange(1, 1) withBytes:replacement];
[self sendCommand:tempMutData];
data = [data subdataWithRange:NSMakeRange(3, [data length]-3)];
self.networkBuffer = [NSMutableArray arrayWithArray:[self.networkBuffer subarrayWithRange:NSMakeRange(3, [self.networkBuffer count]-3)]];
// NSLog(@"network buffer after removal: %@", data);
if ([self.networkBuffer count]<3) {
[self.networkBuffer insertObject:@" " atIndex:0];
}
}
//decode from bytes to text
for ( NSString * component in self.networkBuffer)
{
int value = 0;
sscanf([component cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
[self.dataString appendFormat:@"%c", (char)value];
NSLog(@"data byte: %c",(char)value);
}
[self telnetResponse:self.dataString];
[self.networkBuffer removeAllObjects];
[self.socket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];//CRLFData
}
以下是我接收和发送的telnet协商选项的明细:
Here is a breakdown of the telnet negotiation options Im receiving and sending:
服务器向我发送邮件:
FF,FD,18(0x18 = 24dec)(Do终端类型)
FF,FD,18 (0x18 = 24dec) (Do terminal type)
FF,FD,20(0x20 = 32dec)(终端速度)
FF,FD,20 (0x20 = 32dec) (Do terminal speed)
FF,FD,23(0x23 = 35dec)(Do X显示位置)
FF,FD,23 (0x23 = 35dec) (Do X Display Location)
FF,FD,27(0x27 = 39dec)(执行新环境选项)
FF,FD,27 (0x27 = 39dec) (Do New Environment Option)
我尝试的响应无效(没有提示进一步输入):
FF,FC,18(0x18 = 24dec)(Wont终端类型)
FF,FC,18 (0x18 = 24dec) (Wont terminal type)
FF,FC,20(0x20 = 32dec)(Wont终端速度)
FF,FC,20 (0x20 = 32dec) (Wont terminal speed)
FF,FC,23(0x23 = 35dec)(Wont X显示位置)
FF,FC,23 (0x23 = 35dec) (Wont X Display Location)
FF,FC,27(0x27 = 39dec)(Wont New Environment Option)
FF,FC,27 (0x27 = 39dec) (Wont New Environment Option)
如果您查看代码,将会看到我正在检查FF,如果是,则以相似的字节进行响应(将FD替换为FC),希望不会接受这些选项,但似乎不起作用.
If you look at the code you will see that I am checking for FF and if so responding with similar bytes (replacing FD with FC), in hopes that wont accept the options but that does not seem to be working.
对我有帮助的链接:
https://stackoverflow.com/a/2913991/530933
http://www.iprodeveloper.com/forums/aft/52910
更新
我使用命令外壳和cisco编解码器进行了Wireshk.之后,我复制了这些协商设置/数据包.现在唯一的问题是,我只得到回声.因此,我什么也不会收到,发送命令,然后返回提示以及我的文字. (示例.什么都不做-发送用户名"admin"-重新获得"login:admin")因此,我的意思是仅获取回显.我应该得到一个提示登录:",然后发送"admin",然后它会提示我输入密码.
I did a wireshark with a command shell and the cisco codec. After which I duplicated those negotiation setting/packets. Now the only problem is that Im only getting the echo. So i will get nothing, send a command, then get back a prompt plus my text. (Example. get nothing - send username "admin" - get back "login: admin") Hence what I mean by only getting the echo. I should get a prompt "login:" then send "admin" then it should prompt me for the password.
这是我在连接上发送的协商选项:
here are the negotiation options Im sending on connect:
//will terminal type
//will negotiate about window size
const unsigned char nineteen[] = {
0xFF, 0xFB, 0x18, 0xFF, 0xFB, 0x1F
};
self.dataToBeSent = [[NSData alloc]initWithBytes:nineteen length:sizeof(nineteen)];
[self sendCommand:self.dataToBeSent];
//wont terminal speed
//wont X display location
//will new environment option
const unsigned char twenty[] = {
0xFF, 0xFC, 0x20, 0xFF, 0xFC, 0x23, 0xFF, 0xFB, 0x27
};
self.dataToBeSent = [[NSData alloc]initWithBytes:twenty length:sizeof(twenty)];
[self sendCommand:self.dataToBeSent];
//Suboption being: negotiate about window size
//end
const unsigned char twentyOne[] = {
//0xFF,0xFC, 0x18
0xFF, 0xFA, 0x1F, 0x00, 0x50, 0x00, 0x19, 0xFF, 0xF0
};
self.dataToBeSent = [[NSData alloc]initWithBytes:twentyOne length:sizeof(twentyOne)];
[self sendCommand:self.dataToBeSent];
//new enviroment option
//end
const unsigned char twentyThree[] = {
0xFF,0xFA, 0x27, 0x00, 0xFF, 0xF0
};
self.dataToBeSent = [[NSData alloc]initWithBytes:twentyThree length:sizeof(twentyThree)];
[self sendCommand:self.dataToBeSent];
//Terminal Type (ANSI)
//end
const unsigned char twentySeven[] = {
0xFF,0xFA, 0x18, 0x00, 0x41, 0x4E, 0x53, 0x49, 0xFF, 0xF0
};
self.dataToBeSent = [[NSData alloc]initWithBytes:twentySeven length:sizeof(twentySeven)];
[self sendCommand:self.dataToBeSent];
//do suppress go ahead
const unsigned char twentyEight[] = {
0xFF, 0xFD, 0x03
};
self.dataToBeSent = [[NSData alloc]initWithBytes:twentyEight length:sizeof(twentyEight)];
[self sendCommand:self.dataToBeSent];
//will echo
//dont status
//wont remote flow control
const unsigned char twentyFour[] = {
0xFF, 0xFB, 0x01, 0xFF, 0xFE, 0x05, 0xFF,0xFC, 0x21
};
self.dataToBeSent = [[NSData alloc]initWithBytes:twentyFour length:sizeof(twentyFour)];
[self sendCommand:self.dataToBeSent];
//wont echo
const unsigned char twentyFive[] = {
0xFF, 0xFC, 0x01
};
self.dataToBeSent = [[NSData alloc]initWithBytes:twentyFive length:sizeof(twentyFive)];
[self sendCommand:self.dataToBeSent];
//Do echo
const unsigned char twentySix[] = {
0xFF,0xFD, 0x01
};
self.dataToBeSent = [[NSData alloc]initWithBytes:twentySix length:sizeof(twentySix)];
[self sendCommand:self.dataToBeSent];
推荐答案
因此,一个大问题来自于提示(登录名或密码:)没有以CR NL(0D:0A)结尾的事实.而我在做
So a big problem came from the fact that the prompts (login: or password:) do no end the line with CR NL (0D:0A). And I was doing
[self.socket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];
所以我从来没有读过保存该提示的数据(另一个大问题是wireshark无法正常工作(
so I was never reading the data that held the prompt (a big problem also was that wireshark wasnt working (fixed that myself too)). Once I figured this out I changed the line above to:
[self.socket readDataWithTimeout:-1 tag:0];
哪个成功给了我提示.以下是我为达到这一点而进行的谈判,以及原始问题(与更新中的上述内容相同)的含义:
Which successfully gave me my prompt. Below are the negotiations Im sending to get to this point and what the original questions entailed (same as above in the update):
终端类型-0xFF,0xFB,0x18
will terminal type - 0xFF, 0xFB, 0x18
将就窗口大小进行协商-0xFF,0xFB,0x1F
will negotiate about window size - 0xFF, 0xFB, 0x1F
不会获得终端速度-0xFF,0xFC,0x20
wont terminal speed - 0xFF, 0xFC, 0x20
不会显示X的位置-0xFF,0xFC,0x23
wont X display location - 0xFF, 0xFC, 0x23
将提供新的环境选项-0xFF,0xFB,0x27
will new environment option - 0xFF, 0xFB, 0x27
子选项
negotiate about window size - 0xFF, 0xFA, 0x1F, 0x00, 0x50, 0x00, 0x19
end - 0xFF, 0xF0
new enviroment option - 0xFF,0xFA, 0x27, 0x00,
end - 0xFF, 0xF0
Terminal Type (ANSI) - 0xFF,0xFA, 0x18, 0x00, 0x41, 0x4E, 0x53, 0x49,
end - 0xFF, 0xF0
执行抑制操作-0xFF,0xFD,0x03
do suppress go ahead - 0xFF, 0xFD, 0x03
将回显-0xFF,0xFB,0x01
will echo - 0xFF, 0xFB, 0x01
dont状态-0xFF,0xFE,0x05
dont status - 0xFF, 0xFE, 0x05
不会获得远程流控制-0xFF,0xFC,0x21
wont remote flow control - 0xFF,0xFC, 0x21
不会回显-0xFF,0xFC,0x01
wont echo - 0xFF, 0xFC, 0x01
做回声-0xFF,0xFD,0x01
Do echo - 0xFF,0xFD, 0x01
这可能也有帮助.它从流中删除协商字节,因此在进行字符串编码时不包括协商字节.
This might also help. It removes the negotiation bytes from the stream so when your encoding to make the string it doesnt include negotiation bytes.
while([[self.networkBuffer objectAtIndex:0]isEqualToString:@"FF"])
{
if ([[self.networkBuffer objectAtIndex:1]isEqualToString:@"FD"] || [[self.networkBuffer objectAtIndex:1]isEqualToString:@"FB"] || [[self.networkBuffer objectAtIndex:1]isEqualToString:@"FE"] || [[self.networkBuffer objectAtIndex:1]isEqualToString:@"FA"]) {
//most negotiation options are 3 bytes long
int indexToRemoveFromBuffer = 3;
//if FA then they are longer then 3 bytes
if ([[self.networkBuffer objectAtIndex:1]isEqualToString:@"FA"]) {
//look for indicator of END (F0)
indexToRemoveFromBuffer = [self.networkBuffer indexOfObject:@"F0"]+1;
}
//remove these bytes from networkbuffer
self.networkBuffer = [NSMutableArray arrayWithArray:[self.networkBuffer subarrayWithRange:NSMakeRange(indexToRemoveFromBuffer, [self.networkBuffer count]-indexToRemoveFromBuffer)]];
if ([self.networkBuffer count] == 0) {
if (self.isLoggedIn) {
[self.socket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 tag:0];//CRLFData
}else{
[self.socket readDataWithTimeout:-1 tag:0];
}
return;
}
}else{
break;
}
}
这篇关于使用GCDAsyncSocket通过套接字进行Telnet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!