Telnet em um soquete com o GCDAsyncSocket
Eu estou tentando se conectar a um codec Cisco C40 via telnet do objetivo c. Ao usar o terminal no meu computador eu recebo:
Senha:
No entanto, ao fazer uma conexão de soquete, há negociações de telnet que precisam ser feitas. Que eu sou, mas por algum motivo eu não consigo acessar o prompt "Senha:" acima.
- (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
}
Aqui está uma análise das opções de negociação de telnet que estou recebendo e enviando:
servidor me enviando:
FF, FD, 18 (0x18 = 24dec) (tipo Do terminal)
FF, FD, 20 (0x20 = 32dec) (velocidade do terminal)
FF, FD, 23 (0x23 = 35dec) (Do X local de exibição)
FF, FD, 27 (0x27 = 39dec) (fazer nova opção de ambiente)
Minha tentativa de resposta que não funciona (nenhum prompt para mais entrada):
FF, FC, 18 (0x18 = 24dec) (tipo de terminal Wont)
FF, FC, 20 (0x20 = 32dec) (velocidade do terminal Wont)
FF, FC, 23 (0x23 = 35dec) (não será exibido na tela X)
FF, FC, 27 (0x27 = 39dec) (não é possível nova opção de ambiente)
Se você olhar o código, verá que estou verificando o FF e, em caso afirmativo, respondendo com bytes semelhantes (substituindo o FD pelo FC), na esperança de que ele não aceitará as opções, mas isso não parece estar funcionando.
Links que me ajudaram:
https://stackoverflow.com/a/2913991/530933
Comandos Telnet IAC (socket NSStream)
http://www.iprodeveloper.com/forums/aft/52910
ATUALIZAR
Eu fiz um wireshark com um shell de comando e o codec cisco. Depois disso, eu dupliquei essas configurações / pacotes de negociação. Agora o único problema é que estou recebendo apenas o eco. Então, eu não vou conseguir nada, enviar um comando, em seguida, voltar um prompt mais meu texto. (Exemplo: não receba nada - envie o nome de usuário "admin" - retorne "login: admin") Daí o que quero dizer com apenas obter o eco. Eu deveria ter um prompt "login:", em seguida, enviar "admin", então ele deve me pedir a senha.
aqui estão as opções de negociação que estou enviando na conexão:
//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];