tree_cell * nasl_telnet_init(lex_ctxt * lexic) { int soc = get_int_var_by_num(lexic, 0, -1); int opts; /* number of options recorded */ unsigned char buffer[1024]; #define iac buffer[0] #define code buffer[1] #define option buffer[2] tree_cell * retc; int n = 0, n2; if(soc <= 0 ) { nasl_perror(lexic, "Syntax error in the telnet_init() function\n"); nasl_perror(lexic, "Correct syntax is : output = telnet_init(<socket>)\n"); return NULL; } iac = 255; opts = 0; while(iac == 255) { n = read_stream_connection_min(soc, buffer, 3, 3); if((iac!=255)||(n<=0)||(n!=3))break; if((code == 251)||(code == 252))code = 254; /* WILL , WONT -> DON'T */ else if((code == 253)||(code == 254))code = 252; /* DO,DONT -> WONT */ write_stream_connection(soc, buffer,3); opts++; if (opts>100) break; } if (n <= 0) { if (opts == 0) return NULL; else n = 0; } if (opts>100) /* remote telnet server is crazy */ { nasl_perror(lexic, "More than 100 options received by telnet_init() function! exiting telnet_init.\n"); return NULL; } n2 = read_stream_connection(soc, buffer + n, sizeof(buffer) - n); if (n2 > 0) n += n2; retc = alloc_typed_cell(CONST_DATA); retc->size = n; retc->x.str_val = strndup(buffer, n); #undef iac #undef data #undef option return retc; }
tree_cell * nasl_recv_line(lex_ctxt * lexic) { int len = get_int_local_var_by_name(lexic, "length", -1); int soc = get_int_local_var_by_name(lexic, "socket", 0); int timeout = get_int_local_var_by_name(lexic, "timeout", -1); char * data; int new_len = 0; int n = 0; tree_cell * retc; time_t t1 = 0; if(timeout < 0) timeout = lexic->recv_timeout; if(len == -1 || soc <= 0) { nasl_perror(lexic, "recv_line: missing or undefined parameter length or soc\n"); return NULL; } if (timeout >= 0) /* sycalls are much more expensive than simple tests */ t1 = time(NULL); if ( fd_is_stream(soc) != 0 ) { int bufsz = stream_get_buffer_sz ( soc ); if ( bufsz <= 0 ) stream_set_buffer(soc, len + 1 ); } data = emalloc(len+1); for(;;) { int e = read_stream_connection_min(soc, data+n, 1, 1); if(e < 0) break; if(e == 0) { if( timeout >= 0 && time(NULL) - t1 < timeout) continue; else break; } n++; if((data[n-1] == '\n') || (n >= len))break; } if(n <= 0) { efree(&data); return NULL; } new_len = n; retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = new_len; retc->x.str_val = nasl_strndup(data, new_len); efree(&data); return retc; }
tree_cell * nasl_recv(lex_ctxt * lexic) { char * data; int len = get_int_local_var_by_name(lexic, "length", -1); int min_len = get_int_local_var_by_name(lexic, "min", -1); int soc = get_int_local_var_by_name(lexic, "socket", 0); int to = get_int_local_var_by_name(lexic, "timeout", lexic->recv_timeout); fd_set rd; struct timeval tv; int new_len = 0; tree_cell * retc; int type = -1, opt_len = sizeof(type); int e; if(len <= 0 || soc <= 0) return NULL; if (to <= 0) to = 5; tv.tv_sec = to; tv.tv_usec = 0; data = emalloc(len); if ( !fd_is_stream(soc) ) e = getsockopt(soc, SOL_SOCKET, SO_TYPE, &type, &opt_len); else e = -1; if(e == 0 && type == SOCK_DGRAM) { /* * As UDP packets may be lost, we retry up to 5 times */ int retries = 5; int i; tv.tv_sec = to / retries; tv.tv_usec = (to % retries) * 100000; for(i=0;i<retries;i++) { FD_ZERO(&rd); FD_SET(soc, &rd); if(!to || select(soc+1, &rd, NULL, NULL, &tv)>0) { int e; e = recv(soc, data+new_len, len-new_len, 0); if(e <= 0) { if(!new_len) { efree(&data); return NULL; } else break; } else new_len+=e; if(new_len >= len)break; break; /* UDP data is never fragmented */ } else { /* * The packet may have been lost en route - we resend it */ char * data; int len; data = get_udp_data(lexic->script_infos, soc, &len); if(data != NULL)send(soc, data, len, 0); tv.tv_sec = to / retries; tv.tv_usec = ( to % retries) * 100000; } } } else { int old = stream_set_timeout(soc, tv.tv_sec); new_len = read_stream_connection_min(soc, data, min_len, len); stream_set_timeout(soc, old); } if(new_len > 0) { retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->x.str_val = nasl_strndup(data, new_len); retc->size = new_len; efree(&data); return retc; } else { efree(&data); return NULL; } }