/* * Syntax: insstr(s1, s2, i1, i2) or insstr(s1, s2, i1) * Insert string s2 into slice [i1:i2] of string s1 and returns the result * Warning: returns a CONST_DATA! */ tree_cell* nasl_insstr(lex_ctxt* lexic) { char *s1, *s2, *s3; int sz1, sz2, sz3, i1, i2; tree_cell *retc; s1 = get_str_var_by_num(lexic, 0); sz1 = get_var_size_by_num(lexic, 0); s2 = get_str_var_by_num(lexic, 1); sz2 = get_var_size_by_num(lexic, 1); i1 = get_int_var_by_num(lexic, 2, -1); i2 = get_int_var_by_num(lexic, 3, -1); if (i2 > sz1 || i2 == -1) i2 = sz1-1; if (s1 == NULL || s2 == NULL || i1 < 0 || i2 < 0) { nasl_perror(lexic, "Usage: insstr(str1, str2, idx_start [,idx_end])\n"); return NULL; } if (i1 > sz1) { nasl_perror(lexic, "insstr: cannot insert string2 after end of string1\n"); return NULL; } retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; if (i1 > i2) { nasl_perror(lexic," insstr: warning! 1st index %d greater than 2nd index %d\n", i1, i2); sz3 = sz2; } else sz3 = sz1 + i1 - i2 - 1 + sz2; s3 = retc->x.str_val = emalloc(sz3); retc->size = sz3; if (i1 <= sz1) { memcpy(s3, s1, i1); s3 += i1; } memcpy(s3, s2, sz2); s3 += sz2; if (i2 < sz1 - 1) memcpy(s3, s1 + i2 +1, sz1 - 1 - i2); return retc; }
/*---------------------------------------------------------------------*/ tree_cell * nasl_close_socket(lex_ctxt * lexic) { int soc; int type; int opt_len = sizeof(type); int e; soc = get_int_var_by_num(lexic, 0, -1); if(soc <= 4) { nasl_perror(lexic, "close(): invalid argument\n"); return NULL; } if ( fd_is_stream(soc) ) { return close_stream_connection(soc) < 0 ? NULL:FAKE_CELL; } e = getsockopt(soc, SOL_SOCKET, SO_TYPE, &type, &opt_len); if(e == 0 ) { if (type == SOCK_DGRAM) { rm_udp_data(lexic->script_infos, soc); return FAKE_CELL; } closesocket(soc); return FAKE_CELL; } else nasl_perror(lexic, "close(): invalid argument\n"); return NULL; }
/* * Opening a UDP socket is a little more tricky, since * UDP works in a way which is different from TCP... * * Our goal is to hide this difference for the end-user */ tree_cell * nasl_open_sock_udp(lex_ctxt * lexic) { int soc; tree_cell * retc; int port; struct sockaddr_in soca; struct arglist * script_infos = lexic->script_infos; struct in_addr * ia; port = get_int_var_by_num(lexic, 0, -1); if(port < 0) return NULL; ia = plug_get_host_ip(script_infos); bzero(&soca, sizeof(soca)); soca.sin_addr.s_addr = ia->s_addr; soca.sin_port = htons(port); soca.sin_family = AF_INET; soc = socket(AF_INET, SOCK_DGRAM, 0); add_socket(script_infos, soc); set_socket_source_addr(soc, 0); connect(soc, (struct sockaddr*)&soca, sizeof(soca)); retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = soc < 0 ? 0 : soc; return retc; }
tree_cell* nasl_stridx(lex_ctxt * lexic) { char *a = get_str_var_by_num(lexic, 0); int sz_a = get_var_size_by_num(lexic, 0); char *b = get_str_var_by_num(lexic, 1); int sz_b = get_var_size_by_num(lexic, 1); char *c; int start = get_int_var_by_num(lexic, 2, 0); tree_cell *retc = alloc_typed_cell(CONST_INT); retc->x.i_val = -1; if (a == NULL || b == NULL) { nasl_perror(lexic, "stridx(string, substring [, start])\n"); return retc; } if(start < 0 || start > sz_a) { nasl_perror(lexic, "stridx(string, substring [, start])\n"); return retc; } if ((sz_a == start) || (sz_b > sz_a + start)) return retc; c = (char*)memmem(a + start, sz_a - start, b, sz_b); if(c != NULL) retc->x.i_val = c - a; return retc; }
tree_cell* nasl_get_source_port(lex_ctxt* lexic) { struct sockaddr_in ia; int i, s, fd, l; tree_cell *retc; s = get_int_var_by_num(lexic, 0, -1); if (s < 0) { nasl_perror(lexic, "get_source_port: missing socket parameter\n"); return NULL; } fd = nessus_get_socket_from_connection(s); if (fd < 0) { nasl_perror(lexic, "get_source_port: invalid socket parameter %d\n", s); return NULL; } l = sizeof(ia); if (getsockname(fd, (struct sockaddr*)&ia, &l) < 0) { nasl_perror(lexic, "get_source_port: getsockname(%d): %s\n", fd, strerror(errno)); return NULL; } retc = alloc_typed_cell(CONST_INT); retc->x.i_val = ntohs(ia.sin_port); return retc; }
/*---------------------------------------------------------------------*/ tree_cell* nasl_crap(lex_ctxt* lexic) { tree_cell *retc; char *data = get_str_local_var_by_name(lexic, "data"); int data_len = -1; int len = get_int_local_var_by_name(lexic, "length", -1); int len2 = get_int_var_by_num(lexic, 0, -1); if(len < 0 && len2 < 0) { nasl_perror(lexic, "crap: invalid or missing 'length' argument\n"); return NULL; } if (len >= 0 && len2 >= 0) { nasl_perror(lexic, "crap: cannot set both unnamed and named 'length'\n"); return NULL; } if (len < 0) len = len2; if( len == 0 ) return FAKE_CELL; if (data != NULL) { data_len = get_var_size_by_name(lexic, "data"); if (data_len == 0) { nasl_perror(lexic, "crap: invalid null 'data' parameter\n"); return NULL; } } retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA /*CONST_STR*/; retc->x.str_val = emalloc(len+1); retc->size = len; if (data == NULL) memset(retc->x.str_val, 'X', len); else { int i,r; for(i = 0; i < len - data_len; i += data_len) memcpy(retc->x.str_val + i, data, data_len); if(data_len != 1) { if((r = (len % data_len)) > 0) memcpy(retc->x.str_val + (len - r), data, r); else memcpy(retc->x.str_val + (len - data_len), data, data_len); } else retc->x.str_val[ len - 1 ] = data[0]; } retc->x.str_val[len] = '\0'; return retc; }
tree_cell * nasl_open_sock_tcp_bufsz (lex_ctxt * lexic, int bufsz) { int soc = -1; struct arglist *script_infos = lexic->script_infos; int to, port; int transport = -1; const char *priority; tree_cell *retc; int type; to = get_int_local_var_by_name (lexic, "timeout", lexic->recv_timeout * 2); if (to < 0) to = 10; transport = get_int_local_var_by_name (lexic, "transport", -1); if (transport == OPENVAS_ENCAPS_TLScustom) { priority = get_str_local_var_by_name (lexic, "priority"); if (!priority) priority = NULL; type = get_local_var_type_by_name (lexic, "priority"); if (type != VAR2_STRING && type != VAR2_DATA) priority = NULL; } else priority = NULL; if (bufsz < 0) bufsz = get_int_local_var_by_name (lexic, "bufsz", 0); port = get_int_var_by_num (lexic, 0, -1); if (port < 0) return NULL; /* If "transport" has not been given, use auto detection if enabled in the KB. if "transport" has been given with a value of 0 force autodetection reagardless of what the KB tells. */ if (transport < 0) soc = open_stream_auto_encaps_ext (script_infos, port, to, 0); else if (transport == 0) soc = open_stream_auto_encaps_ext (script_infos, port, to, 1); else soc = open_stream_connection_ext (script_infos, port, transport, to, priority); if (bufsz > 0 && soc >= 0) { if (stream_set_buffer (soc, bufsz) < 0) nasl_perror (lexic, "stream_set_buffer: soc=%d,bufsz=%d\n", soc, bufsz); } retc = alloc_tree_cell (0, NULL); retc->type = CONST_INT; retc->x.i_val = soc < 0 ? 0 : soc; return retc; }
/*---------------------------------------------------------------------*/ tree_cell * nasl_close_socket (lex_ctxt * lexic) { int soc; int type; unsigned int opt_len = sizeof (type); int e; soc = get_int_var_by_num (lexic, 0, -1); /* XXX: These are thoughts expressed on the openvas-devel mailing list 2008-08-06: * * nasl_close_socket seems to be the only place in nasl/nasl_socket.c where the * value of the socket filedescriptor is checked in this way. That in itself is * strange. Why only there? Also, why can't the socket fd be less than 4? I * could sort of understand 3 (0, 1, 2 are already taken by the standard * streams) but 4? Does the openvas server and/or the NASL interpreter guarantee * that at least one other file is open? * * My guess is that the check is there to prevent NASL scripts from closing file * descriptors needed by openvas/NASL which includes the ones it uses for * accessing the knowledgebase. If that's the case, then the test has too much * knowledge of the circumstances under which the NASL interpreter runs. It * should be moved to a separate function whose behavior can be influenced by * the program embedding the NASL interpreter. Other functions should probably * also check the descriptors. * * I also wonder whether the original code (disallowing any file descriptor <= 4) * actually was correct and the real defect is that open_sock_udp actually * returned 4. Under which circumstances does it actually do that? In my brief * tests with the stand-alone nasl interpreter the smallest number it returned * was 5. */ if (soc < 4) { nasl_perror (lexic, "close(): invalid argument\n"); return NULL; } if (fd_is_stream (soc)) return close_stream_connection (soc) < 0 ? NULL : FAKE_CELL; e = getsockopt (soc, SOL_SOCKET, SO_TYPE, &type, &opt_len); if (e == 0) { if (type == SOCK_DGRAM) { rm_udp_data (lexic->script_infos, soc); return FAKE_CELL; } close (soc); return FAKE_CELL; } else nasl_perror (lexic, "close(): invalid argument\n"); return NULL; }
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_int(lex_ctxt * lexic) { int r = get_int_var_by_num(lexic, 0, 0); tree_cell * retc; retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = r; return retc; }
tree_cell* script_id(lex_ctxt * lexic) { struct arglist * script_infos = lexic->script_infos; int id; id = get_int_var_by_num(lexic, 0, -1); if(id > 0) plug_set_id(script_infos, id); return FAKE_CELL; }
tree_cell *script_timeout(lex_ctxt * lexic) { struct arglist * script_infos = lexic->script_infos; int to = get_int_var_by_num(lexic, 0, -65535); if(to == -65535) return FAKE_CELL; plug_set_timeout(script_infos, to ? to : -1 ); return FAKE_CELL; }
static tree_cell * security_something(lex_ctxt * lexic, proto_post_something_t proto_post_func, post_something_t post_func) { struct arglist * script_infos = lexic->script_infos; char* proto = get_str_local_var_by_name(lexic, "protocol"); char* data = get_str_local_var_by_name(lexic, "data"); int port = get_int_local_var_by_name(lexic, "port", -1); char * dup = NULL; if(data != NULL) { int len = get_local_var_size_by_name(lexic, "data"); int i; dup = nasl_strndup(data, len); for(i=0;i<len;i++) if(dup[i] == 0)dup[i]=' '; } /*if((arg_get_value(script_infos, "standalone")) != NULL) { if( data != NULL ) fprintf(stdout, "%s\n", dup); else fprintf(stdout, "Success\n"); }*/ if(proto == NULL) proto = get_str_local_var_by_name(lexic, "proto"); if(port < 0) port = get_int_var_by_num(lexic, 0, -1); if(dup != NULL) { if(proto == NULL) post_func(script_infos, port, dup); else proto_post_func(script_infos, port, proto, dup); efree(&dup); return FAKE_CELL; } if(proto == NULL) post_func(script_infos, port, NULL); else proto_post_func(script_infos, port, proto, NULL); return FAKE_CELL; }
tree_cell* nasl_func_has_arg(lex_ctxt* lexic) { nasl_func *f; char *s; int vt, i, flag = 0; tree_cell *retc; s = get_str_var_by_num(lexic, 0); if (s == NULL) { nasl_perror(lexic, "func_has_arg: missing parameter\n"); return NULL; } f = get_func_ref_by_name(lexic, s); if (f == NULL) { nasl_perror(lexic, "func_args: unknown function \"%s\"\n", s); return NULL; } vt = get_var_type_by_num(lexic, 1); switch(vt) { case VAR2_INT: i = get_int_var_by_num(lexic, 1, -1); if (i >= 0 && i < f->nb_unnamed_args) flag = 1; break; case VAR2_STRING: case VAR2_DATA: s = get_str_var_by_num(lexic, 1); for (i = 0; i < f->nb_named_args && ! flag; i ++) if (strcmp(s, f->args_names[i]) == 0) flag = 1; break; default: nasl_perror(lexic, "func_has_arg: string or integer expected as 2nd parameter\n"); return NULL; } retc = alloc_typed_cell(CONST_INT); retc->x.i_val = flag; return retc; }
tree_cell * script_category(lex_ctxt * lexic) { struct arglist * script_infos = lexic->script_infos; int category = get_int_var_by_num(lexic, 0, -1); if(category < 0){ nasl_perror(lexic, "Argument error in function script_category()\n"); nasl_perror(lexic, "Function usage is : script_category(<category>)\n"); return FAKE_CELL; } plug_set_category(script_infos, category); return FAKE_CELL; }
tree_cell* nasl_do_exit(lex_ctxt* lexic) { int x = get_int_var_by_num(lexic, 0, 0); tree_cell *retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = x; while (lexic != NULL) { lexic->ret_val = retc; ref_cell(retc); lexic = lexic->up_ctxt; } return retc; }
/* * Syntax: substr(s, i1) or substr(s, i1, i2) * Returns character from string s starting for position i1 till the end or * position i2 (start of string is 0) */ tree_cell* nasl_substr(lex_ctxt* lexic) { char *s1; int sz1, sz2, i1, i2, typ; tree_cell *retc; s1 = get_str_var_by_num(lexic, 0); sz1 = get_var_size_by_num(lexic, 0); typ = get_var_type_by_num(lexic, 0); i1 = get_int_var_by_num(lexic, 1, -1); #ifndef MAX_INT #define MAX_INT (~(1 << (sizeof(int) * 8 - 1))) #endif i2 = get_int_var_by_num(lexic, 2, MAX_INT); if (i2 > sz1) i2 = sz1-1; if (s1 == NULL || i1 < 0) { nasl_perror(lexic, "Usage: substr(string, idx_start [,idx_end])\n"); return NULL; } retc = alloc_tree_cell(0, NULL); retc->type = (typ == CONST_STR ? CONST_STR : CONST_DATA); if (i1 > i2) { retc->x.str_val = emalloc(0); retc->size = 0; return retc; } sz2 = i2 - i1 + 1; retc->size = sz2; retc->x.str_val = emalloc(sz2); memcpy(retc->x.str_val, s1 + i1, sz2); return retc; }
tree_cell * get_port_transport(lex_ctxt * lexic) { struct arglist * script_infos = lexic->script_infos; tree_cell *retc; int port = get_int_var_by_num(lexic, 0, -1); if(port >= 0) { int trp = plug_get_port_transport(script_infos, port); retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = trp; return retc; } return NULL; }
/* * Opening a UDP socket is a little more tricky, since * UDP works in a way which is different from TCP... * * Our goal is to hide this difference for the end-user */ tree_cell * nasl_open_sock_udp (lex_ctxt * lexic) { int soc; tree_cell *retc; int port; struct sockaddr_in soca; struct sockaddr_in6 soca6; struct arglist *script_infos = lexic->script_infos; struct in6_addr *ia; port = get_int_var_by_num (lexic, 0, -1); if (port < 0) return NULL; ia = plug_get_host_ip (script_infos); if (ia == NULL) return NULL; if (IN6_IS_ADDR_V4MAPPED (ia)) { bzero (&soca, sizeof (soca)); soca.sin_addr.s_addr = ia->s6_addr32[3]; soca.sin_port = htons (port); soca.sin_family = AF_INET; soc = socket (AF_INET, SOCK_DGRAM, 0); openvas_source_set_socket (soc, 0, AF_INET); connect (soc, (struct sockaddr *) &soca, sizeof (soca)); } else { bzero (&soca6, sizeof (soca6)); memcpy (&soca6.sin6_addr, ia, sizeof (struct in6_addr)); soca6.sin6_port = htons (port); soca6.sin6_family = AF_INET6; soc = socket (AF_INET6, SOCK_DGRAM, 0); openvas_source_set_socket (soc, 0, AF_INET6); connect (soc, (struct sockaddr *) &soca6, sizeof (soca6)); } retc = alloc_tree_cell (0, NULL); retc->type = CONST_INT; retc->x.i_val = soc < 0 ? 0 : soc; return retc; }
tree_cell * get_port_state(lex_ctxt * lexic) { int open; struct arglist * script_infos = lexic->script_infos; tree_cell * retc; int port; port = get_int_var_by_num(lexic, 0, -1); if(port < 0) return FAKE_CELL; retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; open = host_get_port_state(script_infos, port); retc->x.i_val = open; return retc; }
tree_cell* nasl_hex(lex_ctxt * lexic) { tree_cell * retc; int v = get_int_var_by_num(lexic, 0, -1); char ret[7]; if(v == -1) return NULL; snprintf(ret, sizeof(ret), "0x%02x", (unsigned char)v); retc = alloc_tree_cell(0, NULL); retc->type = CONST_STR; retc->size = strlen(ret); retc->x.str_val = estrdup(ret); return retc; }
tree_cell* nasl_localtime(lex_ctxt* lexic) { tree_cell *retc; struct tm *ptm; time_t tictac; int utc; nasl_array *a; anon_nasl_var v; tictac = get_int_var_by_num(lexic, 0, 0); if (tictac == 0) tictac = time(NULL); utc = get_int_local_var_by_name(lexic, "utc", 0); if (utc) ptm = gmtime(&tictac); else ptm = localtime(&tictac); if (ptm == NULL) { nasl_perror(lexic, "localtime(%d,utc=%d): %s\n", tictac, utc, strerror(errno)); return NULL; } retc = alloc_typed_cell(DYN_ARRAY); retc->x.ref_val = a = emalloc(sizeof(nasl_array)); memset(&v, 0, sizeof(v)); v.var_type = VAR2_INT; v.v.v_int = ptm->tm_sec; add_var_to_array(a, "sec", &v); /* seconds */ v.v.v_int = ptm->tm_min; add_var_to_array(a, "min", &v); /* minutes */ v.v.v_int = ptm->tm_hour; add_var_to_array(a, "hour", &v); /* hours */ v.v.v_int = ptm->tm_mday; add_var_to_array(a, "mday", &v); /* day of the month */ v.v.v_int = ptm->tm_mon+1; add_var_to_array(a, "mon", &v); /* month */ v.v.v_int = ptm->tm_year+1900; add_var_to_array(a, "year", &v); /* year */ v.v.v_int = ptm->tm_wday; add_var_to_array(a, "wday", &v); /* day of the week */ v.v.v_int = ptm->tm_yday+1; add_var_to_array(a, "yday", &v); /* day in the year */ v.v.v_int = ptm->tm_isdst; add_var_to_array(a, "isdst", &v); /* daylight saving time */ return retc; }
tree_cell * nasl_socket_get_error (lex_ctxt * lexic) { int soc = get_int_var_by_num (lexic, 0, -1); tree_cell *retc; int err; if (soc < 0 || !fd_is_stream (soc)) return NULL; err = stream_get_err (soc); retc = alloc_typed_cell (CONST_INT); switch (err) { case 0: retc->x.i_val = NASL_ERR_NOERR; break; case ETIMEDOUT: retc->x.i_val = NASL_ERR_ETIMEDOUT; break; case EBADF: case EPIPE: #ifdef ECONNRESET case ECONNRESET: #endif #ifdef ENOTSOCK case ENOTSOCK: #endif retc->x.i_val = NASL_ERR_ECONNRESET; break; case ENETUNREACH: case EHOSTUNREACH: retc->x.i_val = NASL_ERR_EUNREACH; break; default: log_legacy_write ("Unknown error %d %s\n", err, strerror (err)); } return retc; }
/* Fixme: Merge this into nasl_get_sock_info. */ tree_cell * nasl_get_source_port (lex_ctxt * lexic) { struct sockaddr_in ia; int s, fd; unsigned int l; tree_cell *retc; int type; unsigned int type_len = sizeof (type); s = get_int_var_by_num (lexic, 0, -1); if (s < 0) { nasl_perror (lexic, "get_source_port: missing socket parameter\n"); return NULL; } if (!fd_is_stream (s) && getsockopt (s, SOL_SOCKET, SO_TYPE, &type, &type_len) == 0 && type == SOCK_DGRAM) fd = s; else fd = openvas_get_socket_from_connection (s); if (fd < 0) { nasl_perror (lexic, "get_source_port: invalid socket parameter %d\n", s); return NULL; } l = sizeof (ia); if (getsockname (fd, (struct sockaddr *) &ia, &l) < 0) { nasl_perror (lexic, "get_source_port: getsockname(%d): %s\n", fd, strerror (errno)); return NULL; } retc = alloc_typed_cell (CONST_INT); retc->x.i_val = ntohs (ia.sin_port); return retc; }
tree_cell * nasl_scanner_get_port(lex_ctxt * lexic) { tree_cell * retc; int idx = get_int_var_by_num(lexic, 0, -1); struct arglist * script_infos = lexic->script_infos; struct arglist * prefs = arg_get_value(script_infos, "preferences"); char *prange = arg_get_value(prefs, "port_range"); static int num = 0; static u_short * ports = NULL; if (prange == NULL) return NULL; if(idx < 0) { nasl_perror(lexic, "Argument error in scanner_get_port()\n"); nasl_perror(lexic, "Correct usage is : num = scanner_get_port(<num>)\n"); nasl_perror(lexic, "Where <num> should be 0 the first time you call it\n"); return NULL; } if (ports == NULL) { ports = (u_short*)getpts(prange, &num); if (ports == NULL) { return NULL; } } if(idx >= num) { return NULL; } retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = ports[idx]; return retc; }
/** * @brief Close file */ tree_cell * nasl_file_close (lex_ctxt * lexic) { tree_cell *retc; int fd; fd = get_int_var_by_num (lexic, 0, -1); if (fd < 0) { nasl_perror (lexic, "file_close: need file pointer argument\n"); return NULL; } if (close (fd) < 0) { nasl_perror (lexic, "file_close: %s\n", strerror (errno)); return NULL; } retc = alloc_typed_cell (CONST_INT); retc->x.i_val = 0; return retc; }
tree_cell * nasl_open_sock_tcp_bufsz(lex_ctxt * lexic, int bufsz) { int soc = -1; struct arglist * script_infos = lexic->script_infos; int to, port, transport = -1; tree_cell * retc; char *host; to = get_int_local_var_by_name(lexic, "timeout", lexic->recv_timeout*2); if(to <= 0) to = 10; transport = get_int_local_var_by_name(lexic, "transport", -1); if (bufsz < 0) bufsz = get_int_local_var_by_name(lexic, "bufsz", 0); port = get_int_var_by_num(lexic, 0, -1); if(port < 0) return NULL; if(transport < 0) soc = open_stream_auto_encaps(script_infos, port, to); else soc = open_stream_connection(script_infos, port, transport, to); if (bufsz > 0 && soc >= 0 ) { if (stream_set_buffer(soc, bufsz) < 0) nasl_perror(lexic, "stream_set_buffer: soc=%d,bufsz=%d\n", soc, bufsz); } retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = soc < 0 ? 0 : soc; return retc; }
tree_cell* nasl_rawstring(lex_ctxt* lexic) { tree_cell *retc; int vi, vn, i, j, x; int sz, typ; const char *s; int total_len = 0; retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; retc->size = 0; retc->x.str_val = emalloc(RAW_STR_LEN); vn = array_max_index(&lexic->ctx_vars); for (vi = 0; vi < vn && total_len < RAW_STR_LEN-1; vi ++) { if ((typ = get_var_type_by_num(lexic, vi)) == VAR2_UNDEF) continue; sz = get_var_size_by_num(lexic, vi); if (typ == VAR2_INT) { x = get_int_var_by_num(lexic, vi, 0); retc->x.str_val[total_len ++] = x; } else { int current_len = sz; char str[RAW_STR_LEN]; s = get_str_var_by_num(lexic, vi); if (sz <= 0) sz = strlen(s); if (sz >= RAW_STR_LEN) { nasl_perror(lexic, "Error. Too long argument in raw_string()\n"); break; } /* Should we test if the variable is composed only of digits? */ if(typ == VAR2_STRING) { /* TBD:I should decide at last if we keep those "purified" * string or not, and if we do, if "CONST_STR" & "VAR2_STR" are * "not pure" strings */ for(i=0, j=0; i < sz; i++) { if(s[i]=='\\') { if (s[i+1] == 'n') { str[j++]='\n'; i++; } else if (s[i+1] == 't') { str[j++]='\t'; i++; } else if (s[i+1] == 'r') { str[j++] = '\r'; i++; } else if (s[i+1] == 'x' && isxdigit(s[i+2]) && isxdigit(s[i+3])) { x = 0; if(isdigit(s[i+2])) x = (s[i+2]-'0')*16; else x=(10+tolower(s[i+2])-'a')*16; if(isdigit(s[i+3])) x += s[i+3]-'0'; else x += tolower(s[i+3])+10-'a'; str[j++]=x; i+=3; } else if(s[i+1] == '\\') { str[j++] = s[i]; i++; } else i++; } else str[j++] = s[i]; } current_len = j; } else { memcpy(str, s, sz); str[sz] = '\0'; current_len = sz; } if(total_len + current_len > RAW_STR_LEN) { nasl_perror(lexic, "Error. Too long argument in raw_string()\n"); break; } bcopy(str, retc->x.str_val + total_len, current_len); total_len += current_len; } } retc->size = total_len; return retc; }
tree_cell * nasl_sleep(lex_ctxt * lexic) { int slp = get_int_var_by_num(lexic, 0, 0); Sleep(slp * 1000); return FAKE_CELL; }
/** * @brief Get info pertaining to a socket. * @naslfn{get_sock_info} * * This function is used to retrieve various information about an * active socket. It requires the NASL socket number and a string to * select the information to retrieve. * * Supported keywords are: * * - @a dport Return the destination port. This is an integer. NOTE: * Not yet implemented. * * - @a sport Return the source port. This is an integer. NOTE: Not * yet implemented. * * - @a encaps Return the encapsulation of the socket. Example * output: "TLScustom". * * - @a tls-proto Return a string with the actual TLS protocol in use. * n/a" is returned if no SSL/TLS session is active. Example * output: "TLSv1". * * - @a tls-kx Return a string describing the key exchange algorithm. * Example output: "RSA". * * - @a tls-certtype Return the type of the certificate in use by the * session. Example output: "X.509" * * - @a tls-cipher Return the cipher algorithm in use by the session; * Example output: "AES-256-CBC". * * - @a tls-mac Return the message authentication algorithms used by * the session. Example output: "SHA1". * * - @a tls-comp Return the compression algorithms in use by the * session. Example output: "DEFLATE". * * - @a tls-auth Return the peer's authentication type. Example * output: "CERT". * * - @a tls-cert Return the peer's certificates for an SSL or TLS * connection. This is an array of binary strings or NULL if no * certificate is known. * * @nasluparam * * - A NASL socket * * - A string keyword; see above. * * @naslnparam * * - @a asstring If true return a human readable string instead of * an integer. Used only with these keywords: encaps. * * @naslret An integer or a string or NULL on error. * * @param[in] lexic Lexical context of the NASL interpreter. * * @return A tree cell. */ tree_cell * nasl_get_sock_info (lex_ctxt * lexic) { int sock; int type; int err; const char *keyword, *s; tree_cell *retc; int as_string; int transport; gnutls_session_t tls_session; char *strval; int intval; sock = get_int_var_by_num (lexic, 0, -1); if (sock <= 0) { nasl_perror (lexic, "error: socket %d is not valid\n"); return NULL; } keyword = get_str_var_by_num (lexic, 1); if (!keyword || !((type = get_var_type_by_num (lexic, 1)) == VAR2_STRING || type == VAR2_DATA)) { nasl_perror (lexic, "error: second argument is not of type string\n"); return NULL; } as_string = !!get_int_local_var_by_name (lexic, "asstring", 0); transport = 0; strval = NULL; intval = 0; retc = FAKE_CELL; /* Dummy value to detect retc == NULL. */ { void *tmp = NULL; err = get_sock_infos (sock, &transport, &tmp); tls_session = tmp; } if (err) { nasl_perror (lexic, "error retrieving infos for socket %d: %s\n", sock, strerror (err)); retc = NULL; } else if (!strcmp (keyword, "encaps")) { if (as_string) strval = estrdup (get_encaps_name (transport)); else intval = transport; } else if (!strcmp (keyword, "tls-proto")) { if (!tls_session) s = "n/a"; else s = gnutls_protocol_get_name (gnutls_protocol_get_version (tls_session)); strval = estrdup (s?s:"[?]"); } else if (!strcmp (keyword, "tls-kx")) { if (!tls_session) s = "n/a"; else s = gnutls_kx_get_name (gnutls_kx_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-certtype")) { if (!tls_session) s = "n/a"; else s = gnutls_certificate_type_get_name (gnutls_certificate_type_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-cipher")) { if (!tls_session) s = "n/a"; else s = gnutls_cipher_get_name (gnutls_cipher_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-mac")) { if (!tls_session) s = "n/a"; else s = gnutls_mac_get_name (gnutls_mac_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-comp")) { if (!tls_session) s = "n/a"; else s = gnutls_compression_get_name (gnutls_compression_get (tls_session)); strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-auth")) { if (!tls_session) s = "n/a"; else { switch (gnutls_auth_get_type (tls_session)) { case GNUTLS_CRD_ANON: s = "ANON"; break; case GNUTLS_CRD_CERTIFICATE: s = "CERT"; break; case GNUTLS_CRD_PSK: s = "PSK"; break; case GNUTLS_CRD_SRP: s = "SRP"; break; default: s = "[?]"; break; } } strval = estrdup (s?s:""); } else if (!strcmp (keyword, "tls-cert")) { /* We only support X.509 for now. GNUTLS also allows for OpenPGP, but we are not prepared for that. */ if (!tls_session || gnutls_certificate_type_get (tls_session) != GNUTLS_CRT_X509) s = "n/a"; else { const gnutls_datum_t *list; unsigned int nlist = 0; int i; nasl_array *a; anon_nasl_var v; list = gnutls_certificate_get_peers (tls_session, &nlist); if (!list) retc = NULL; /* No certificate or other error. */ else { retc = alloc_tree_cell (0, NULL); retc->type = DYN_ARRAY; retc->x.ref_val = a = emalloc (sizeof *a); for (i=0; i < nlist; i++) { memset (&v, 0, sizeof v); v.var_type = VAR2_DATA; v.v.v_str.s_val = list[i].data; v.v.v_str.s_siz = list[i].size; add_var_to_list (a, i, &v); } } } } else { nasl_perror (lexic, "unknown keyword '%s'\n", keyword); retc = NULL; } if (!retc) ; else if (retc != FAKE_CELL) ; /* Already allocated. */ else if (strval) { retc = alloc_typed_cell (CONST_STR); retc->x.str_val = strval; retc->size = strlen (strval); } else { retc = alloc_typed_cell (CONST_INT); retc->x.i_val = intval; } return retc; }