/* * 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_islocalnet(lex_ctxt * lexic) { struct arglist * script_infos = lexic->script_infos; struct in_addr * ip = plug_get_host_ip(script_infos); tree_cell * retc; retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = is_local_ip(*ip); return retc; }
tree_cell * nasl_this_host(lex_ctxt * lexic) { struct arglist * script_infos = lexic->script_infos; tree_cell * retc; struct in_addr addr; char hostname[255]; char * ret; struct in_addr * ia = plug_get_host_ip(script_infos); struct in_addr src; retc = alloc_tree_cell(0, NULL); retc->type = CONST_DATA; addr = socket_get_next_source_addr(arg_get_value(script_infos, "globals")); if ( addr.s_addr != INADDR_ANY ) { retc->x.str_val = estrdup(inet_ntoa(addr)); retc->size = strlen(retc->x.str_val); return retc; } src.s_addr = 0; if(ia) { if(islocalhost(ia)) src.s_addr = ia->s_addr; else (void)routethrough(ia, &src); if(src.s_addr) { char * ret; ret = estrdup(inet_ntoa(src)); retc->x.str_val = ret; retc->size = strlen(ret); return retc; } hostname[sizeof(hostname) - 1] = '\0'; gethostname(hostname, sizeof(hostname) - 1); addr = nn_resolve(hostname); ret = estrdup(inet_ntoa(addr)); retc->x.str_val = ret; retc->size = strlen(ret); } return retc; }
/* * 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_host_ip(lex_ctxt * lexic) { struct arglist * script_infos = lexic->script_infos; struct in_addr * ip = plug_get_host_ip(script_infos); char * txt_ip; tree_cell * retc; if(ip == NULL) /* WTF ? */ { return FAKE_CELL; } retc = alloc_tree_cell(0, NULL); retc->type = CONST_STR; txt_ip = inet_ntoa(*ip); retc->x.str_val = estrdup(txt_ip); retc->size = strlen(retc->x.str_val); return retc; }
static tree_cell * nasl_open_privileged_socket(lex_ctxt * lexic, int proto) { struct arglist * script_infos = lexic->script_infos; int sport, current_sport = -1; int dport; int sock; int e, err; struct sockaddr_in addr, daddr; struct in_addr * p; int to = get_int_local_var_by_name(lexic, "timeout", lexic->recv_timeout); tree_cell * retc; struct timeval tv; fd_set rd; int opt, opt_sz; sport = get_int_local_var_by_name(lexic, "sport", -1); dport = get_int_local_var_by_name(lexic, "dport", -1); if(dport <= 0) { nasl_perror(lexic, "open_private_socket: missing or undefined parameter dport!\n"); return NULL; } if(sport < 0) current_sport = 1023; restart: bzero(&addr, sizeof(addr)); if(proto == IPPROTO_TCP) sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); else sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* * We will bind to a privileged port. Let's declare * our socket ready for reuse */ if(sock < 0) return NULL; add_socket(script_infos, sock); tryagain : if ( current_sport < 128 ) return NULL; e = set_socket_source_addr(sock, sport > 0 ? sport : current_sport--); /* * bind() failed - try again on a lower port */ if(e < 0) { closesocket ( sock ); if(sport > 0) return NULL; else goto tryagain; } /* * Connect to the other end */ p = plug_get_host_ip(script_infos); bzero(&daddr, sizeof(daddr)); daddr.sin_addr = *p; daddr.sin_port = htons(dport); daddr.sin_family = AF_INET; unblock_socket(sock); e = connect(sock, (struct sockaddr*)&daddr, sizeof(daddr)); if ( e < 0 ) { err = WSAGetLastError(); if ( err == WSAEADDRINUSE || err == WSAEADDRNOTAVAIL ) { closesocket(sock); if ( sport < 0 ) goto restart; else return NULL; } } do { tv.tv_sec = to; tv.tv_usec = 0; FD_ZERO(&rd); FD_SET(sock, &rd); e = select(sock + 1, NULL, &rd, NULL, to > 0 ? &tv:NULL); err = WSAGetLastError(); } while ( e < 0 && err == WSAEINTR ); block_socket(sock); opt_sz = sizeof(opt); if ( getsockopt(sock, SOL_SOCKET, SO_ERROR, &opt, &opt_sz) < 0 ) { fprintf(stderr, "[%d] open_priv_sock()->getsockopt() failed : %s\n", getpid(), strerror(errno)); closesocket(sock); return NULL; } switch ( opt ) { case WSAEADDRINUSE: case WSAEADDRNOTAVAIL: closesocket ( sock ); if ( sport < 0 ) goto restart; else return FAKE_CELL; case 0: break; default: closesocket ( sock ); return FAKE_CELL; break; } if(proto == IPPROTO_TCP) sock = nessus_register_connection(sock, NULL); retc = alloc_tree_cell(0, NULL); retc->type = CONST_INT; retc->x.i_val = sock < 0 ? 0 : sock; return retc; }
PlugExport int plugin_run(struct arglist * env) { int soc; struct sockaddr_in addr; struct in_addr *p = plug_get_host_ip(env); struct tftp_header * packet; char * p_packet; char * test_file = get_preference(env, "test_file"); char * read_timeout = get_preference(env, "checks_read_timeout"); char * file = NULL; char * test_file_with_header; int b; fd_set read_set; char * report; int flaw = 0; int len = sizeof(struct sockaddr_in); struct timeval timeout = {0,0}; int flag; if(read_timeout != NULL) { timeout.tv_sec = atoi(read_timeout); } if(timeout.tv_sec <= 0) timeout.tv_sec = 5; flag = (int)plug_get_key(env, "tftp/get_file"); if(flag)return(0); if ( test_file == NULL ) test_file = strdup("/etc/passwd"); p_packet = emalloc(512 + strlen(test_file)); packet = (struct tftp_header *)p_packet; packet->th_opcode=htons(RRQ); test_file_with_header = emalloc(strlen(test_file)+20); sprintf(test_file_with_header, "..%s", test_file); sprintf(packet->th_stuff, test_file_with_header); sprintf(packet->th_stuff+strlen(test_file_with_header)+1,"octet"); soc = socket(AF_INET, SOCK_DGRAM, 0); set_socket_source_addr( soc, 0 ); addr.sin_family = AF_INET; addr.sin_addr = *p; addr.sin_port = htons(69); connect(soc,( struct sockaddr*) &addr, sizeof(addr)); b = send(soc, packet, 22, 0); addr.sin_addr = *p; addr.sin_port = 0; b=512; while(b==512) { unsigned short block; addr.sin_addr = *p; addr.sin_port = 0; bzero(packet, 512); FD_ZERO(&read_set); FD_SET(soc, &read_set); select(soc+1, &read_set, NULL, NULL, &timeout); if(!FD_ISSET(soc, &read_set))break; b = recv(soc,packet, 512, 0); if ( b <= sizeof(struct tftp_header)) exit(0); if(ntohs(packet->th_opcode)==3) { /* We receive some data : there is a flaw */ char tmp[512]; char * tmp2; flaw++; snprintf(tmp, sizeof(tmp), "%s", packet->th_msg); if( file == NULL ) tmp2 = emalloc(sizeof(tmp)+1); else tmp2 = emalloc(strlen(file)+sizeof(tmp)+1); if( file == NULL ) strncpy(tmp2, tmp, strlen(tmp)); else snprintf(tmp2, sizeof(tmp) + 1, "%s%s", file,tmp); if(file != NULL ) efree(&file); file = emalloc(strlen(tmp2) + 1); strncpy(file, tmp2, strlen(tmp2)); efree(&tmp2); } else break; block = ntohs(packet->th_block); bzero(packet, 512); packet->th_opcode = htons(04); packet->th_block = htons(block); send(soc, packet, 4, 0); } efree(&test_file_with_header); if(flaw) { report = emalloc(255 + strlen(file) + strlen(test_file)); sprintf(report, "It was possible to retrieve the file %s\n\ through tftp by appending '..' in front of its name.\n\ Here is what we could grab : \n%s\n\n\ Solution : upgrade your tftpd", test_file, file); efree(&file); post_hole_udp(env, 69,report); } return(0); }
static tree_cell * nasl_open_privileged_socket (lex_ctxt * lexic, int proto) { struct arglist *script_infos = lexic->script_infos; int sport, current_sport = -1; int dport; int sock; int e; struct sockaddr_in addr, daddr; struct sockaddr_in6 addr6, daddr6; struct in6_addr *p; int to = get_int_local_var_by_name (lexic, "timeout", lexic->recv_timeout); tree_cell *retc; struct timeval tv; fd_set rd; int opt; unsigned int opt_sz; int family; sport = get_int_local_var_by_name (lexic, "sport", -1); dport = get_int_local_var_by_name (lexic, "dport", -1); if (dport <= 0) { nasl_perror (lexic, "open_private_socket: missing or undefined parameter dport!\n"); return NULL; } if (sport < 0) current_sport = 1023; restart: p = plug_get_host_ip (script_infos); if (IN6_IS_ADDR_V4MAPPED (p)) { family = AF_INET; bzero (&addr, sizeof (addr)); if (proto == IPPROTO_TCP) sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); else sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); } else { family = AF_INET6; bzero (&addr6, sizeof (addr6)); if (proto == IPPROTO_TCP) sock = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP); else sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP); } /* * We will bind to a privileged port. Let's declare * our socket ready for reuse */ if (sock < 0) return NULL; tryagain: if (current_sport < 128 && sport < 0) return NULL; e = openvas_source_set_socket (sock, sport > 0 ? sport : current_sport--, family); /* * bind() failed - try again on a lower port */ if (e < 0) { close (sock); if (sport > 0) return NULL; else goto tryagain; } /* * Connect to the other end */ p = plug_get_host_ip (script_infos); if (IN6_IS_ADDR_V4MAPPED (p)) { bzero (&daddr, sizeof (daddr)); daddr.sin_addr.s_addr = p->s6_addr32[3]; daddr.sin_family = AF_INET; daddr.sin_port = htons (dport); unblock_socket (sock); e = connect (sock, (struct sockaddr *) &daddr, sizeof (daddr)); } else { bzero (&daddr6, sizeof (daddr6)); memcpy (&daddr6.sin6_addr, p, sizeof (struct in6_addr)); daddr6.sin6_family = AF_INET6; daddr6.sin6_port = htons (dport); unblock_socket (sock); e = connect (sock, (struct sockaddr *) &daddr6, sizeof (daddr6)); } if (e < 0) { if (errno == EADDRINUSE || errno == EADDRNOTAVAIL) { close (sock); if (sport < 0) goto restart; else return NULL; } else if (errno != EINPROGRESS) { close (sock); return NULL; } } do { tv.tv_sec = to; tv.tv_usec = 0; FD_ZERO (&rd); FD_SET (sock, &rd); e = select (sock + 1, NULL, &rd, NULL, to > 0 ? &tv : NULL); } while (e < 0 && errno == EINTR); if (e <= 0) { close (sock); return FAKE_CELL; } block_socket (sock); opt_sz = sizeof (opt); if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &opt, &opt_sz) < 0) { log_legacy_write ("[%d] open_priv_sock()->getsockopt() failed : %s\n", getpid (), strerror (errno)); close (sock); return NULL; } switch (opt) { case EADDRINUSE: case EADDRNOTAVAIL: close (sock); if (sport < 0) goto restart; else return FAKE_CELL; case 0: break; default: close (sock); return FAKE_CELL; break; } if (proto == IPPROTO_TCP) sock = openvas_register_connection (sock, NULL, NULL, OPENVAS_ENCAPS_TLScustom); retc = alloc_tree_cell (0, NULL); retc->type = CONST_INT; retc->x.i_val = sock < 0 ? 0 : sock; return retc; }