OpenVAS Scanner 23.40.3
nasl_packet_forgery.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Greenbone AG
2 * SPDX-FileCopyrightText: 2002-2004 Tenable Network Security
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
8
9#include "../misc/bpf_share.h" /* for bpf_open_live */
10#include "../misc/pcap_openvas.h" /* for routethrough */
11#include "../misc/plugutils.h" /* plug_get_host_ip */
12#include "capture_packet.h"
13#include "exec.h"
14#include "nasl_debug.h"
15#include "nasl_func.h"
16#include "nasl_global_ctxt.h"
17#include "nasl_lex_ctxt.h"
19#include "nasl_raw.h"
20#include "nasl_socket.h"
21#include "nasl_tree.h"
22#include "nasl_var.h"
23
24#include <arpa/inet.h> /* for inet_aton */
25#include <ctype.h> /* for isprint */
26#include <errno.h> /* for errno */
27#include <pcap.h> /* for PCAP_ERRBUF_SIZE */
28#include <stddef.h>
29#include <stdlib.h> /* for rand */
30#include <string.h> /* for bcopy */
31#include <sys/time.h> /* for gettimeofday */
32#include <unistd.h> /* for close */
33
36#ifdef BSD_BYTE_ORDERING
37#define FIX(n) (n)
38#define UNFIX(n) (n)
39#else
40#define FIX(n) htons (n)
41#define UNFIX(n) ntohs (n)
42#endif
43
44/*--------------[ cksum ]-----------------------------------------*/
45
46/*
47 * Checksum routine for Internet Protocol family headers (C Version)
48 * From ping examples in W.Richard Stevens "UNIX NETWORK PROGRAMMING" book.
49 */
50static int
52u_short *p;
53
54int n;
55{
56 register u_short answer;
57 register long sum = 0;
58 u_short odd_byte = 0;
59
60 while (n > 1)
61 {
62 sum += *p++;
63 n -= 2;
64 }
65
66 /* mop up an odd byte, if necessary */
67 if (n == 1)
68 {
69 *(u_char *) (&odd_byte) = *(u_char *) p;
70 sum += odd_byte;
71 }
72
73 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
74 sum += (sum >> 16); /* add carry */
75 answer = (int) ~sum; /* ones-complement, truncate */
76 return (answer);
77}
78
79/*--------------[ IP ]--------------------------------------------*/
80
104tree_cell *
106{
107 tree_cell *retc;
108 struct ip *pkt;
109 char *s;
110 struct script_infos *script_infos = lexic->script_infos;
111 struct in6_addr *dst_addr;
112 char *data;
113 size_t data_len;
114
115 dst_addr = plug_get_host_ip (script_infos);
116
117 if (dst_addr == NULL || (IN6_IS_ADDR_V4MAPPED (dst_addr) != 1))
118 {
119 nasl_perror (lexic, "forge_ip_packet: No valid dst_addr could be "
120 "determined via call to plug_get_host_ip().\n");
121 return NULL;
122 }
123
124 data = get_str_var_by_name (lexic, "data");
125 data_len = get_var_size_by_name (lexic, "data");
126
128 retc->size = sizeof (struct ip) + data_len;
129
130 pkt = (struct ip *) g_malloc0 (sizeof (struct ip) + data_len);
131 retc->x.str_val = (char *) pkt;
132
133 pkt->ip_hl = get_int_var_by_name (lexic, "ip_hl", 5);
134 pkt->ip_v = get_int_var_by_name (lexic, "ip_v", 4);
135 pkt->ip_tos = get_int_var_by_name (lexic, "ip_tos", 0);
136 /* pkt->ip_len = FIX(get_int_var_by_name(lexic, "ip_len", 20 + data_len)); */
137
138 pkt->ip_len = FIX (20 + data_len);
139
140 pkt->ip_id = htons (get_int_var_by_name (lexic, "ip_id", rand ()));
141 pkt->ip_off = get_int_var_by_name (lexic, "ip_off", 0);
142 pkt->ip_off = FIX (pkt->ip_off);
143 pkt->ip_ttl = get_int_var_by_name (lexic, "ip_ttl", 64);
144 pkt->ip_p = get_int_var_by_name (lexic, "ip_p", 0);
145 pkt->ip_sum = htons (get_int_var_by_name (lexic, "ip_sum", 0));
146 /* source */
147 s = get_str_var_by_name (lexic, "ip_src");
148 if (s != NULL)
149 inet_aton (s, &pkt->ip_src);
150 /* else this host address? */
151
152 /* I know that this feature looks dangerous, but anybody can edit an IP
153 * packet with the string functions */
154 s = get_str_var_by_name (lexic, "ip_dst");
155 if (s != NULL)
156 inet_aton (s, &pkt->ip_dst);
157 else
158 pkt->ip_dst.s_addr = dst_addr->s6_addr32[3];
159
160 if (data != NULL)
161 {
162 bcopy (data, retc->x.str_val + sizeof (struct ip), data_len);
163 }
164
165 if (!pkt->ip_sum)
166 {
167 if (get_int_var_by_name (lexic, "ip_sum", -1) < 0)
168 pkt->ip_sum = np_in_cksum ((u_short *) pkt, sizeof (struct ip));
169 }
170
171 return retc;
172}
173
183tree_cell *
185{
186 tree_cell *retc;
187 struct ip *ip = (struct ip *) get_str_var_by_name (lexic, "ip");
188 char *element = get_str_var_by_name (lexic, "element");
189 char ret_ascii[32];
190 int ret_int = 0;
191 int flag = 0;
192
193 if (ip == NULL)
194 {
195 nasl_perror (lexic, "get_ip_element: no valid 'ip' argument\n");
196 return NULL;
197 }
198
199 if (element == NULL)
200 {
201 nasl_perror (lexic, "get_ip_element: no valid 'element' argument\n");
202 return NULL;
203 }
204
205 if (!strcmp (element, "ip_v"))
206 {
207 ret_int = ip->ip_v;
208 flag++;
209 }
210 else if (!strcmp (element, "ip_id"))
211 {
212 ret_int = UNFIX (ip->ip_id);
213 flag++;
214 }
215 else if (!strcmp (element, "ip_hl"))
216 {
217 ret_int = ip->ip_hl;
218 flag++;
219 }
220 else if (!strcmp (element, "ip_tos"))
221 {
222 ret_int = ip->ip_tos;
223 flag++;
224 }
225 else if (!strcmp (element, "ip_len"))
226 {
227 ret_int = UNFIX (ip->ip_len);
228 flag++;
229 }
230 else if (!strcmp (element, "ip_off"))
231 {
232 ret_int = UNFIX (ip->ip_off);
233 flag++;
234 }
235 else if (!strcmp (element, "ip_ttl"))
236 {
237 ret_int = ip->ip_ttl;
238 flag++;
239 }
240 else if (!strcmp (element, "ip_p"))
241 {
242 ret_int = ip->ip_p;
243 flag++;
244 }
245 else if (!strcmp (element, "ip_sum"))
246 {
247 ret_int = UNFIX (ip->ip_sum);
248 flag++;
249 }
250
251 if (flag != 0)
252 {
254 retc->x.i_val = ret_int;
255 return retc;
256 }
257
258 if (!strcmp (element, "ip_src"))
259 {
260 snprintf (ret_ascii, sizeof (ret_ascii), "%s", inet_ntoa (ip->ip_src));
261 flag++;
262 }
263 else if (!strcmp (element, "ip_dst"))
264 {
265 snprintf (ret_ascii, sizeof (ret_ascii), "%s", inet_ntoa (ip->ip_dst));
266 flag++;
267 }
268
269 if (flag == 0)
270 {
271 nasl_perror (lexic, "%s: unknown element '%s'\n", __func__, element);
272 return NULL;
273 }
274
276 retc->size = strlen (ret_ascii);
277 retc->x.str_val = g_strdup (ret_ascii);
278
279 return retc;
280}
281
302tree_cell *
304{
305 struct ip *o_pkt = (struct ip *) get_str_var_by_name (lexic, "ip");
306 size_t size = get_var_size_by_name (lexic, "ip");
307 tree_cell *retc;
308 struct ip *pkt;
309 char *s;
310
311 if (o_pkt == NULL)
312 {
313 nasl_perror (lexic, "set_ip_elements: missing <ip> field\n");
314 return NULL;
315 }
316
317 pkt = (struct ip *) g_malloc0 (size);
318 bcopy (o_pkt, pkt, size);
319
320 pkt->ip_hl = get_int_var_by_name (lexic, "ip_hl", pkt->ip_hl);
321 pkt->ip_v = get_int_var_by_name (lexic, "ip_v", pkt->ip_v);
322 pkt->ip_tos = get_int_var_by_name (lexic, "ip_tos", pkt->ip_tos);
323 pkt->ip_len =
324 FIX (get_int_var_by_name (lexic, "ip_len", UNFIX (pkt->ip_len)));
325 pkt->ip_id = htons (get_int_var_by_name (lexic, "ip_id", pkt->ip_id));
326 pkt->ip_off =
327 FIX (get_int_var_by_name (lexic, "ip_off", UNFIX (pkt->ip_off)));
328 pkt->ip_ttl = get_int_var_by_name (lexic, "ip_ttl", pkt->ip_ttl);
329 pkt->ip_p = get_int_var_by_name (lexic, "ip_p", pkt->ip_p);
330
331 s = get_str_var_by_name (lexic, "ip_src");
332 if (s != NULL)
333 inet_aton (s, &pkt->ip_src);
334
335 pkt->ip_sum = htons (get_int_var_by_name (lexic, "ip_sum", 0));
336 if (pkt->ip_sum == 0)
337 pkt->ip_sum = np_in_cksum ((u_short *) pkt, sizeof (struct ip));
338
340 retc->size = size;
341 retc->x.str_val = (char *) pkt;
342
343 return retc;
344}
345
357tree_cell *
359{
360 struct ip *ip = (struct ip *) get_str_var_by_name (lexic, "ip");
361 int code = get_int_var_by_name (lexic, "code", 0);
362 int len = get_int_var_by_name (lexic, "length", 0);
363 char *value = get_str_var_by_name (lexic, "value");
364 size_t value_size = get_var_size_by_name (lexic, "value");
365 tree_cell *retc;
366 struct ip *new_packet;
367 char *p;
368 size_t size = get_var_size_by_name (lexic, "ip");
369 u_char uc_code, uc_len;
370 int pad_len;
371 char zero = '0';
372 int i;
373 int hl;
374
375 if (ip == NULL)
376 {
377 nasl_perror (lexic, "Usage : insert_ip_options(ip:<ip>, code:<code>, "
378 "length:<len>, value:<value>\n");
379 return NULL;
380 }
381
382 pad_len = 4 - ((sizeof (uc_code) + sizeof (uc_len) + value_size) % 4);
383 if (pad_len == 4)
384 pad_len = 0;
385
386 hl = ip->ip_hl * 4 < UNFIX (ip->ip_len) ? ip->ip_hl * 4 : UNFIX (ip->ip_len);
387 new_packet = g_malloc0 (size + 4 + value_size + pad_len);
388 bcopy (ip, new_packet, hl);
389
390 uc_code = (u_char) code;
391 uc_len = (u_char) len;
392
393 p = (char *) new_packet;
394 bcopy (&uc_code, p + hl, sizeof (uc_code));
395 bcopy (&uc_len, p + hl + sizeof (uc_code), sizeof (uc_len));
396 bcopy (value, p + hl + sizeof (uc_code) + sizeof (uc_len), value_size);
397
398 zero = 0;
399 for (i = 0; i < pad_len; i++)
400 {
401 bcopy (&zero,
402 p + hl + sizeof (uc_code) + sizeof (uc_len) + value_size + i, 1);
403 }
404
405 p = (char *) ip;
406 bcopy (p + hl,
407 new_packet
408 + (sizeof (uc_code) + sizeof (uc_len) + value_size + pad_len) + hl,
409 size - hl);
410
411 new_packet->ip_hl =
412 (hl + (sizeof (uc_code) + sizeof (uc_len) + value_size + pad_len)) / 4;
413 new_packet->ip_len =
414 FIX (size + sizeof (uc_code) + sizeof (uc_len) + value_size + pad_len);
415 new_packet->ip_sum = 0;
416 new_packet->ip_sum = np_in_cksum (
417 (u_short *) new_packet, new_packet->ip_hl * 4 > UNFIX (new_packet->ip_len)
418 ? UNFIX (new_packet->ip_len)
419 : new_packet->ip_hl * 4);
420
422 retc->size = size + value_size + sizeof (uc_code) + sizeof (uc_len) + pad_len;
423 retc->x.str_val = (char *) new_packet;
424
425 return retc;
426}
427
434tree_cell *
436{
437 int i;
438
439 for (i = 0;; i++)
440 {
441 struct ip *ip = (struct ip *) get_str_var_by_num (lexic, i);
442 if (ip == NULL)
443 break;
444 else
445 {
446 printf ("------\n");
447 printf ("\tip_hl : %d\n", ip->ip_hl);
448 printf ("\tip_v : %d\n", ip->ip_v);
449 printf ("\tip_tos : %d\n", ip->ip_tos);
450 printf ("\tip_len : %d\n", UNFIX (ip->ip_len));
451 printf ("\tip_id : %d\n", ntohs (ip->ip_id));
452 printf ("\tip_off : %d\n", UNFIX (ip->ip_off));
453 printf ("\tip_ttl : %d\n", ip->ip_ttl);
454 switch (ip->ip_p)
455 {
456 case IPPROTO_TCP:
457 printf ("\tip_p : IPPROTO_TCP (%d)\n", ip->ip_p);
458 break;
459 case IPPROTO_UDP:
460 printf ("\tip_p : IPPROTO_UDP (%d)\n", ip->ip_p);
461 break;
462 case IPPROTO_ICMP:
463 printf ("\tip_p : IPPROTO_ICMP (%d)\n", ip->ip_p);
464 break;
465 default:
466 printf ("\tip_p : %d\n", ip->ip_p);
467 break;
468 }
469 printf ("\tip_sum : 0x%x\n", ntohs (ip->ip_sum));
470 printf ("\tip_src : %s\n", inet_ntoa (ip->ip_src));
471 printf ("\tip_dst : %s\n", inet_ntoa (ip->ip_dst));
472 printf ("\n");
473 }
474 }
475
476 return FAKE_CELL;
477}
478
479/*--------------[ TCP ]--------------------------------------------*/
480
481struct pseudohdr
482{
483 struct in_addr saddr;
484 struct in_addr daddr;
485 u_char zero;
486 u_char protocol;
487 u_short length;
488 struct tcphdr tcpheader;
489} __attribute__ ((packed));
490
491// TCP options
493{
494 uint8_t kind; // 2
495 uint8_t len; // 4
496 uint16_t mss;
497} __attribute__ ((packed));
498
500{
501 uint8_t kind; // 3
502 uint8_t len; // 3
503 uint8_t wscale;
504} __attribute__ ((packed));
505
507{
508 uint8_t kind; // 4
509 uint8_t len; // 2
510} __attribute__ ((packed));
511
513{
514 uint8_t kind; // 8
515 uint8_t len; // 10
516 uint32_t tstamp;
517 uint32_t e_tstamp;
518} __attribute__ ((packed));
519
527
555tree_cell *
557{
558 tree_cell *retc;
559 char *data;
560 size_t len;
561 struct ip *ip, *tcp_packet;
562 struct tcphdr *tcp;
563 size_t ipsz;
564
565 ip = (struct ip *) get_str_var_by_name (lexic, "ip");
566 if (ip == NULL)
567 {
568 nasl_perror (lexic,
569 "forge_tcp_packet: You must supply the 'ip' argument\n");
570 return NULL;
571 }
572
573 ipsz = get_var_size_by_name (lexic, "ip");
574 if (ipsz > ip->ip_hl * 4)
575 ipsz = ip->ip_hl * 4;
576
577 data = get_str_var_by_name (lexic, "data");
578 len = data == NULL ? 0 : get_var_size_by_name (lexic, "data");
579
581 tcp_packet = (struct ip *) g_malloc0 (ipsz + sizeof (struct tcphdr) + len);
582 retc->x.str_val = (char *) tcp_packet;
583
584 bcopy (ip, tcp_packet, ipsz);
585 /* recompute the ip checksum, because the ip length changed */
586 if (UNFIX (tcp_packet->ip_len) <= tcp_packet->ip_hl * 4)
587 {
588 if (get_int_var_by_name (lexic, "update_ip_len", 1))
589 {
590 tcp_packet->ip_len =
591 FIX (tcp_packet->ip_hl * 4 + sizeof (struct tcphdr) + len);
592 tcp_packet->ip_sum = 0;
593 tcp_packet->ip_sum =
594 np_in_cksum ((u_short *) tcp_packet, sizeof (struct ip));
595 }
596 }
597 tcp = (struct tcphdr *) ((char *) tcp_packet + tcp_packet->ip_hl * 4);
598
599 tcp->th_sport = ntohs (get_int_var_by_name (lexic, "th_sport", 0));
600 tcp->th_dport = ntohs (get_int_var_by_name (lexic, "th_dport", 0));
601 tcp->th_seq = htonl (get_int_var_by_name (lexic, "th_seq", rand ()));
602 tcp->th_ack = htonl (get_int_var_by_name (lexic, "th_ack", 0));
603 tcp->th_x2 = get_int_var_by_name (lexic, "th_x2", 0);
604 tcp->th_off = get_int_var_by_name (lexic, "th_off", 5);
605 tcp->th_flags = get_int_var_by_name (lexic, "th_flags", 0);
606 tcp->th_win = htons (get_int_var_by_name (lexic, "th_win", 0));
607 tcp->th_sum = get_int_var_by_name (lexic, "th_sum", 0);
608 tcp->th_urp = get_int_var_by_name (lexic, "th_urp", 0);
609
610 if (data != NULL)
611 bcopy (data, (char *) tcp + sizeof (struct tcphdr), len);
612
613 if (!tcp->th_sum)
614 {
615 struct pseudohdr pseudoheader;
616 char *tcpsumdata = g_malloc0 (sizeof (struct pseudohdr) + len + 1);
617 struct in_addr source, dest;
618
619 source.s_addr = ip->ip_src.s_addr;
620 dest.s_addr = ip->ip_dst.s_addr;
621
622 bzero (&pseudoheader, 12 + sizeof (struct tcphdr));
623 pseudoheader.saddr.s_addr = source.s_addr;
624 pseudoheader.daddr.s_addr = dest.s_addr;
625
626 pseudoheader.protocol = IPPROTO_TCP;
627 pseudoheader.length = htons (sizeof (struct tcphdr) + len);
628 bcopy ((char *) tcp, (char *) &pseudoheader.tcpheader,
629 sizeof (struct tcphdr));
630 /* fill tcpsumdata with data to checksum */
631 bcopy ((char *) &pseudoheader, tcpsumdata, sizeof (struct pseudohdr));
632 if (data != NULL)
633 bcopy ((char *) data, tcpsumdata + sizeof (struct pseudohdr), len);
634 tcp->th_sum = np_in_cksum ((unsigned short *) tcpsumdata,
635 12 + sizeof (struct tcphdr) + len);
636 g_free (tcpsumdata);
637 }
638
639 retc->size = ipsz + sizeof (struct tcphdr) + len;
640 return retc;
641}
642
652tree_cell *
654{
655 u_char *packet = (u_char *) get_str_var_by_name (lexic, "tcp");
656 struct ip *ip;
657 size_t ipsz;
658 struct tcphdr *tcp;
659 char *element;
660 int ret;
661 tree_cell *retc;
662
663 ipsz = get_var_size_by_name (lexic, "tcp");
664
665 if (packet == NULL)
666 {
667 nasl_perror (lexic, "get_tcp_element: No valid 'tcp' argument\n");
668 return NULL;
669 }
670
671 ip = (struct ip *) packet;
672
673 if (ip->ip_hl * 4 > ipsz)
674 return NULL; /* Invalid packet */
675
676 if (UNFIX (ip->ip_len) > ipsz)
677 return NULL; /* Invalid packet */
678
679 tcp = (struct tcphdr *) (packet + ip->ip_hl * 4);
680
681 element = get_str_var_by_name (lexic, "element");
682 if (!element)
683 {
684 nasl_perror (lexic, "get_tcp_element: No valid 'element' argument\n");
685 return NULL;
686 }
687
688 if (!strcmp (element, "th_sport"))
689 ret = ntohs (tcp->th_sport);
690 else if (!strcmp (element, "th_dsport"))
691 ret = ntohs (tcp->th_dport);
692 else if (!strcmp (element, "th_seq"))
693 ret = ntohl (tcp->th_seq);
694 else if (!strcmp (element, "th_ack"))
695 ret = ntohl (tcp->th_ack);
696 else if (!strcmp (element, "th_x2"))
697 ret = tcp->th_x2;
698 else if (!strcmp (element, "th_off"))
699 ret = tcp->th_off;
700 else if (!strcmp (element, "th_flags"))
701 ret = tcp->th_flags;
702 else if (!strcmp (element, "th_win"))
703 ret = ntohs (tcp->th_win);
704 else if (!strcmp (element, "th_sum"))
705 ret = tcp->th_sum;
706 else if (!strcmp (element, "th_urp"))
707 ret = tcp->th_urp;
708 else if (!strcmp (element, "data"))
709 {
711 retc->size = UNFIX (ip->ip_len) - (tcp->th_off + ip->ip_hl) * 4;
712 retc->x.str_val = g_malloc0 (retc->size);
713 bcopy ((char *) tcp + tcp->th_off * 4, retc->x.str_val, retc->size);
714 return retc;
715 }
716 else
717 {
718 nasl_perror (lexic, "get_tcp_element: Unknown tcp field %s\n", element);
719 return NULL;
720 }
721
723 retc->x.i_val = ret;
724 return retc;
725}
726
733static void
734get_tcp_options (char *options, struct tcp_options *tcp_all_options)
735{
736 uint8_t *opt_kind;
737 if (options == NULL)
738 return;
739
740 opt_kind = (uint8_t *) options;
741
742 while (*opt_kind != 0)
743 {
744 switch (*opt_kind)
745 {
746 case TCPOPT_MAXSEG:
747 tcp_all_options->mss.kind = *opt_kind;
748 tcp_all_options->mss.len = *(opt_kind + 1);
749 tcp_all_options->mss.mss = *((uint16_t *) (opt_kind + 2));
750 opt_kind = opt_kind + *(opt_kind + 1);
751 break;
752 case TCPOPT_WINDOW:
753 tcp_all_options->wscale.kind = *opt_kind;
754 tcp_all_options->wscale.len = *(opt_kind + 1);
755 tcp_all_options->wscale.wscale = (uint8_t) * (opt_kind + 2);
756 opt_kind = opt_kind + *(opt_kind + 1);
757 break;
758 case TCPOPT_SACK_PERMITTED:
759 tcp_all_options->sack_perm.kind = *opt_kind;
760 tcp_all_options->sack_perm.len = *(opt_kind + 1);
761 opt_kind = opt_kind + *(opt_kind + 1);
762 break;
763 case TCPOPT_TIMESTAMP:
764 tcp_all_options->tstamp.kind = *opt_kind;
765 tcp_all_options->tstamp.len = *(opt_kind + 1);
766 tcp_all_options->tstamp.tstamp = *((uint32_t *) (opt_kind + 2));
767 tcp_all_options->tstamp.e_tstamp = *((uint32_t *) (opt_kind + 6));
768 opt_kind = opt_kind + *(opt_kind + 1);
769 break;
770 case TCPOPT_EOL:
771 case TCPOPT_NOP:
772 opt_kind++;
773 break;
774 case TCPOPT_SACK: // Not supported
775 opt_kind = opt_kind + *(opt_kind + 1);
776 break;
777 default:
778 g_debug ("%s: Unsupported %u TCP option. "
779 "Not all options are returned.",
780 __func__, *opt_kind);
781 *opt_kind = 0;
782 break;
783 }
784 }
785}
786
802tree_cell *
804{
805 u_char *packet = (u_char *) get_str_var_by_name (lexic, "tcp");
806 struct ip *ip;
807 int ipsz;
808 struct tcphdr *tcp;
809 char *options;
810 int opt;
811 tree_cell *retc;
812 nasl_array *arr;
814
815 struct tcp_options *tcp_all_options = NULL;
816
817 if (packet == NULL)
818 {
819 nasl_perror (lexic, "%s: No valid 'tcp' argument passed.\n", __func__);
820 return NULL;
821 }
822
823 opt = get_int_var_by_name (lexic, "option", -1);
824 if (opt < 0)
825 {
826 nasl_perror (lexic,
827 "%s: No options\n."
828 "Usage: %s(tcp:<tcp>, option:<TCPOPT>)",
829 __func__, __func__);
830 return NULL;
831 }
832
833 ip = (struct ip *) packet;
834
835 ipsz = get_var_size_by_name (lexic, "tcp");
836 if (ip->ip_hl * 4 > ipsz)
837 return NULL; /* Invalid packet */
838
839 if (UNFIX (ip->ip_len) > ipsz)
840 return NULL; /* Invalid packet */
841
842 tcp = (struct tcphdr *) (packet + ip->ip_hl * 4);
843
844 if (tcp->th_off <= 5)
845 return NULL;
846
847 // Get options from the segment
848 options = (char *) g_malloc0 (sizeof (uint8_t) * 4 * (tcp->th_off - 5));
849 memcpy (options, (char *) tcp + 20, (tcp->th_off - 5) * 4);
850
851 tcp_all_options = g_malloc0 (sizeof (struct tcp_options));
852 get_tcp_options (options, tcp_all_options);
853 if (tcp_all_options == NULL)
854 {
855 nasl_perror (lexic, "%s: No TCP options found in passed TCP packet.\n",
856 __func__);
857
858 g_free (options);
859 return NULL;
860 }
861
862 opt = get_int_var_by_name (lexic, "option", -1);
863 retc = NULL;
864 switch (opt)
865 {
866 case TCPOPT_MAXSEG:
868 retc->x.i_val = ntohs ((uint16_t) tcp_all_options->mss.mss);
869 break;
870 case TCPOPT_WINDOW:
872 retc->x.i_val = tcp_all_options->wscale.wscale;
873 break;
874 case TCPOPT_SACK_PERMITTED:
876 retc->x.i_val = tcp_all_options->sack_perm.kind ? 1 : 0;
877 break;
878 case TCPOPT_TIMESTAMP:
880 retc->x.ref_val = arr = g_malloc0 (sizeof (nasl_array));
881
882 memset (&v, 0, sizeof (v));
883 v.var_type = VAR2_INT;
884 v.v.v_int = ntohl ((uint32_t) tcp_all_options->tstamp.tstamp);
885 add_var_to_array (arr, "timestamp", &v);
886
887 memset (&v, 0, sizeof (v));
888 v.var_type = VAR2_INT;
889 v.v.v_int = ntohl ((uint32_t) tcp_all_options->tstamp.e_tstamp);
890 add_var_to_array (arr, "echo_timestamp", &v);
891 break;
892 default:
893 nasl_perror (lexic, "%s: Invalid TCP option passed.\n", __func__);
894 break;
895 }
896
897 g_free (tcp_all_options);
898 g_free (options);
899 return retc;
900}
901
929tree_cell *
931{
932 char *pkt = get_str_var_by_name (lexic, "tcp");
933 struct ip *ip = (struct ip *) pkt;
934 size_t pktsz = get_var_size_by_name (lexic, "tcp");
935 struct tcphdr *tcp;
936 tree_cell *retc;
937 char *data = get_str_var_by_name (lexic, "data");
938 size_t data_len = get_var_size_by_name (lexic, "data");
939 char *npkt;
940
941 if (!ip)
942 {
943 nasl_perror (lexic,
944 "set_tcp_elements: Invalid value for the argument 'tcp'\n");
945 return NULL;
946 }
947
948 if (ip->ip_hl * 4 > pktsz)
949 tcp =
950 (struct tcphdr *) (pkt
951 + 20); /* ip->ip_hl is bogus, we work around that */
952 else
953 tcp = (struct tcphdr *) (pkt + ip->ip_hl * 4);
954
955 if (pktsz < UNFIX (ip->ip_len))
956 return NULL;
957
958 if (data_len == 0)
959 {
960 data_len = UNFIX (ip->ip_len) - (ip->ip_hl * 4) - (tcp->th_off * 4);
961 data = (char *) ((char *) tcp + tcp->th_off * 4);
962 }
963
964 npkt = g_malloc0 (ip->ip_hl * 4 + tcp->th_off * 4 + data_len);
965 bcopy (pkt, npkt, UNFIX (ip->ip_len));
966
967 ip = (struct ip *) (npkt);
968 tcp = (struct tcphdr *) (npkt + ip->ip_hl * 4);
969
970 tcp->th_sport =
971 htons (get_int_var_by_name (lexic, "th_sport", ntohs (tcp->th_sport)));
972 tcp->th_dport =
973 htons (get_int_var_by_name (lexic, "th_dport", ntohs (tcp->th_dport)));
974 tcp->th_seq =
975 htonl (get_int_var_by_name (lexic, "th_seq", ntohl (tcp->th_seq)));
976 tcp->th_ack =
977 htonl (get_int_var_by_name (lexic, "th_ack", ntohl (tcp->th_ack)));
978 tcp->th_x2 = get_int_var_by_name (lexic, "th_x2", tcp->th_x2);
979 tcp->th_off = get_int_var_by_name (lexic, "th_off", tcp->th_off);
980 tcp->th_flags = get_int_var_by_name (lexic, "th_flags", tcp->th_flags);
981 tcp->th_win =
982 htons (get_int_var_by_name (lexic, "th_win", ntohs (tcp->th_win)));
983 tcp->th_sum = get_int_var_by_name (lexic, "th_sum", 0);
984 tcp->th_urp = get_int_var_by_name (lexic, "th_urp", tcp->th_urp);
985 bcopy (data, (char *) tcp + tcp->th_off * 4, data_len);
986
987 if (get_int_var_by_name (lexic, "update_ip_len", 1) != 0)
988 {
989 ip->ip_len = ip->ip_hl * 4 + tcp->th_off * 4 + data_len;
990 ip->ip_sum = 0;
991 ip->ip_sum = np_in_cksum ((u_short *) pkt, ip->ip_hl * 4);
992 }
993
994 if (tcp->th_sum == 0)
995 {
996 struct pseudohdr pseudoheader;
997 char *tcpsumdata = g_malloc0 (sizeof (struct pseudohdr) + data_len + 1);
998 struct in_addr source, dest;
999
1000 source.s_addr = ip->ip_src.s_addr;
1001 dest.s_addr = ip->ip_dst.s_addr;
1002
1003 bzero (&pseudoheader, sizeof (pseudoheader));
1004 pseudoheader.saddr.s_addr = source.s_addr;
1005 pseudoheader.daddr.s_addr = dest.s_addr;
1006
1007 pseudoheader.protocol = IPPROTO_TCP;
1008 pseudoheader.length = htons (sizeof (struct tcphdr) + data_len);
1009 bcopy ((char *) tcp, (char *) &pseudoheader.tcpheader,
1010 sizeof (struct tcphdr));
1011 /* fill tcpsumdata with data to checksum */
1012 bcopy ((char *) &pseudoheader, tcpsumdata, sizeof (struct pseudohdr));
1013 bcopy ((char *) data, tcpsumdata + sizeof (struct pseudohdr), data_len);
1014 tcp->th_sum = np_in_cksum ((unsigned short *) tcpsumdata,
1015 sizeof (pseudoheader) + data_len);
1016 g_free (tcpsumdata);
1017 }
1018
1020 retc->size = (ip->ip_hl * 4) + (tcp->th_off * 4) + data_len;
1021 retc->x.str_val = npkt;
1022 return retc;
1023}
1024
1042tree_cell *
1044{
1045 char *pkt = get_str_var_by_name (lexic, "tcp");
1046 struct ip *ip = (struct ip *) pkt;
1047 size_t pktsz = get_var_size_by_name (lexic, "tcp");
1048 struct tcphdr *tcp;
1049 tree_cell *retc;
1050 char *data = get_str_var_by_name (lexic, "data");
1051 size_t data_len = get_var_size_by_name (lexic, "data");
1052 char *npkt;
1053 int tcp_opt, tcp_opt_val, tcp_opt_val2;
1054 int current_opt_len, total_opt_len, opt_size_allocated;
1055 char *opts, *ptr_opts_pos;
1056 uint8_t eol, nop;
1057 int i;
1058
1059 struct tcp_opt_mss *opt_mss;
1060 struct tcp_opt_wscale *opt_wscale;
1061 struct tcp_opt_sack_perm *opt_sack_perm;
1062 struct tcp_opt_tstamp *opt_tstamp;
1063
1064 if (!ip)
1065 {
1066 nasl_perror (lexic, "%s: Invalid value for the argument 'tcp'\n",
1067 __func__);
1068 return NULL;
1069 }
1070
1071 opts = g_malloc0 (sizeof (char) * 4);
1072 ptr_opts_pos = opts;
1073 opt_size_allocated = 4; // 4 bytes
1074 total_opt_len = 0;
1075 for (i = 0;; i++)
1076 {
1077 tcp_opt = get_int_var_by_num (lexic, i, -1);
1078 current_opt_len = total_opt_len;
1079
1080 if (tcp_opt == -1)
1081 break;
1082
1083 switch (tcp_opt)
1084 {
1085 case TCPOPT_MAXSEG:
1086 tcp_opt_val = get_int_var_by_num (lexic, i + 1, -1);
1087 i++;
1088 if (tcp_opt_val < (int) TCP_MSS_DEFAULT || tcp_opt_val > 65535)
1089 {
1090 nasl_perror (lexic, "%s: Invalid value for TCP option MSS\n",
1091 __func__);
1092 break;
1093 }
1094 opt_mss = g_malloc0 (sizeof (struct tcp_opt_mss));
1095 total_opt_len += TCPOLEN_MAXSEG;
1096 opt_mss->kind = TCPOPT_MAXSEG;
1097 opt_mss->len = TCPOLEN_MAXSEG;
1098 opt_mss->mss = FIX (tcp_opt_val);
1099
1100 // Need reallocated memory because options requires it.
1101 if (total_opt_len > opt_size_allocated)
1102 {
1103 opt_size_allocated = ((total_opt_len / 4) + 1) * 4;
1104 opts = g_realloc (opts, sizeof (char) * opt_size_allocated);
1105 ptr_opts_pos = opts + current_opt_len;
1106 }
1107
1108 memcpy (ptr_opts_pos, (u_char *) opt_mss,
1109 sizeof (struct tcp_opt_mss));
1110 ptr_opts_pos = ptr_opts_pos + sizeof (struct tcp_opt_mss);
1111 g_free (opt_mss);
1112 break;
1113 case TCPOPT_WINDOW:
1114 tcp_opt_val = get_int_var_by_num (lexic, i + 1, -1);
1115 i++;
1116 if (tcp_opt_val < 0 || tcp_opt_val > 14)
1117 {
1118 nasl_perror (lexic, "%s: Invalid value for TCP option WScale\n",
1119 __func__);
1120 break;
1121 }
1122 opt_wscale = g_malloc0 (sizeof (struct tcp_opt_wscale));
1123 total_opt_len += TCPOLEN_WINDOW;
1124 opt_wscale->kind = TCPOPT_WINDOW;
1125 opt_wscale->len = TCPOLEN_WINDOW;
1126 opt_wscale->wscale = tcp_opt_val;
1127
1128 // Need reallocated memory because options requires it.
1129 if (total_opt_len > opt_size_allocated)
1130 {
1131 opt_size_allocated = ((total_opt_len / 4) + 1) * 4;
1132 opts = g_realloc (opts, sizeof (char) * opt_size_allocated);
1133 ptr_opts_pos = opts + current_opt_len;
1134 }
1135
1136 memcpy (ptr_opts_pos, (u_char *) opt_wscale,
1137 sizeof (struct tcp_opt_wscale));
1138 ptr_opts_pos = ptr_opts_pos + sizeof (struct tcp_opt_wscale);
1139 g_free (opt_wscale);
1140 break;
1141 case TCPOPT_SACK_PERMITTED:
1142 opt_sack_perm = g_malloc0 (sizeof (struct tcp_opt_sack_perm));
1143 total_opt_len += TCPOLEN_SACK_PERMITTED;
1144 opt_sack_perm->kind = TCPOPT_SACK_PERMITTED;
1145 opt_sack_perm->len = TCPOLEN_SACK_PERMITTED;
1146
1147 // Need reallocated memory because options requires it.
1148 if (total_opt_len > opt_size_allocated)
1149 {
1150 opt_size_allocated = ((total_opt_len / 4) + 1) * 4;
1151 opts = g_realloc (opts, sizeof (char) * opt_size_allocated);
1152 ptr_opts_pos = opts + current_opt_len;
1153 }
1154
1155 memcpy (ptr_opts_pos, (u_char *) opt_sack_perm,
1156 sizeof (struct tcp_opt_sack_perm));
1157 ptr_opts_pos = ptr_opts_pos + sizeof (struct tcp_opt_sack_perm);
1158 g_free (opt_sack_perm);
1159 break;
1160 case TCPOPT_TIMESTAMP:
1161 tcp_opt_val = get_int_var_by_num (lexic, i + 1, -1);
1162 tcp_opt_val2 = get_int_var_by_num (lexic, i + 2, -1);
1163 i = i + 2;
1164 if (tcp_opt_val < 0)
1165 nasl_perror (lexic, "%s: Invalid value for TCP option Timestamp\n",
1166 __func__);
1167 opt_tstamp = g_malloc0 (sizeof (struct tcp_opt_tstamp));
1168 total_opt_len += TCPOLEN_TIMESTAMP;
1169 opt_tstamp->kind = TCPOPT_TIMESTAMP;
1170 opt_tstamp->len = TCPOLEN_TIMESTAMP;
1171 opt_tstamp->tstamp = htonl (tcp_opt_val);
1172 opt_tstamp->e_tstamp = htonl (tcp_opt_val2);
1173
1174 // Need reallocated memory because options requires it.
1175 if (total_opt_len > opt_size_allocated)
1176 {
1177 opt_size_allocated = ((total_opt_len / 4) + 1) * 4;
1178 opts = g_realloc (opts, sizeof (char) * opt_size_allocated);
1179 ptr_opts_pos = opts + current_opt_len;
1180 }
1181
1182 memcpy (ptr_opts_pos, (u_char *) opt_tstamp,
1183 sizeof (struct tcp_opt_tstamp));
1184 ptr_opts_pos = ptr_opts_pos + sizeof (struct tcp_opt_tstamp);
1185 g_free (opt_tstamp);
1186 break;
1187 case TCPOPT_NOP:
1188 case TCPOPT_EOL:
1189 case TCPOPT_SACK: /* Experimental, not supported */
1190 default:
1191 nasl_perror (lexic, "%s: TCP option %d not supported\n", __func__,
1192 tcp_opt);
1193 break;
1194 }
1195 }
1196
1197 // Add NOP padding and End Of Option list kinds.
1198 current_opt_len = total_opt_len;
1199 eol = TCPOPT_EOL;
1200 nop = TCPOPT_NOP;
1201 if (total_opt_len % 4 == 0)
1202 {
1203 opt_size_allocated = opt_size_allocated + 4;
1204 opts = g_realloc (opts, sizeof (char) * opt_size_allocated);
1205 ptr_opts_pos = opts + total_opt_len;
1206 }
1207 if (current_opt_len < opt_size_allocated - 1)
1208 {
1209 // Add NOPs
1210 for (i = current_opt_len; i < opt_size_allocated - 1; i++)
1211 {
1212 memcpy (ptr_opts_pos, &nop, 1);
1213 total_opt_len++;
1214 ptr_opts_pos++;
1215 }
1216 }
1217 // Add EOL
1218 memcpy (ptr_opts_pos, &eol, 1);
1219
1220 if (ip->ip_hl * 4 > pktsz)
1221 // ip->ip_hl is bogus, we work around that
1222 tcp = (struct tcphdr *) (pkt + 20);
1223 else
1224 tcp = (struct tcphdr *) (pkt + ip->ip_hl * 4);
1225
1226 if (pktsz < UNFIX (ip->ip_len))
1227 {
1228 g_free (opts);
1229 return NULL;
1230 }
1231
1232 if (data_len == 0)
1233 {
1234 data_len = UNFIX (ip->ip_len) - (ip->ip_hl * 4) - (tcp->th_off * 4);
1235 data = (char *) ((char *) tcp + tcp->th_off * 4);
1236 }
1237
1238 // Alloc enough memory to hold the options
1239 npkt =
1240 g_malloc0 (ip->ip_hl * 4 + tcp->th_off * 4 + opt_size_allocated + data_len);
1241 memcpy (npkt, pkt, UNFIX (ip->ip_len));
1242 ip = (struct ip *) (npkt);
1243 tcp = (struct tcphdr *) (npkt + ip->ip_hl * 4);
1244
1245 // copy options
1246 memcpy ((char *) tcp + tcp->th_off * 4, opts, opt_size_allocated);
1247
1248 tcp->th_off = tcp->th_off + (opt_size_allocated / 4);
1249 memcpy ((char *) tcp + tcp->th_off * 4, data, data_len);
1250
1251 // Update ip_len and calculate ip checksum
1252 ip->ip_len = FIX (ip->ip_hl * 4 + tcp->th_off * 4 + data_len);
1253 ip->ip_sum = 0;
1254 ip->ip_sum = np_in_cksum ((u_short *) npkt, ip->ip_hl * 4);
1255
1256 // Calculate tcp header with options checksum
1257 struct pseudohdr pseudoheader;
1258 char *tcpsumdata =
1259 g_malloc0 (sizeof (struct pseudohdr) + opt_size_allocated + data_len + 1);
1260 struct in_addr source, dest;
1261
1262 source.s_addr = ip->ip_src.s_addr;
1263 dest.s_addr = ip->ip_dst.s_addr;
1264
1265 memset (&pseudoheader, 0, sizeof (struct pseudohdr));
1266 pseudoheader.saddr.s_addr = source.s_addr;
1267 pseudoheader.daddr.s_addr = dest.s_addr;
1268
1269 pseudoheader.protocol = IPPROTO_TCP;
1270 // TCP length is tcpheader + options + data
1271 pseudoheader.length =
1272 htons (sizeof (struct tcphdr) + opt_size_allocated + data_len);
1273
1274 // Set th_sum to Zero, necessary for the new checksum calculation
1275 tcp->th_sum = 0;
1276
1277 memcpy ((char *) &pseudoheader.tcpheader, (char *) tcp,
1278 sizeof (struct tcphdr));
1279
1280 /* fill tcpsumdata with data to checksum */
1281 memcpy (tcpsumdata, (char *) &pseudoheader, sizeof (struct pseudohdr));
1282 memcpy (tcpsumdata + sizeof (struct pseudohdr), (char *) opts,
1283 opt_size_allocated);
1284 memcpy (tcpsumdata + sizeof (struct pseudohdr) + opt_size_allocated,
1285 (char *) data, data_len);
1286 tcp->th_sum =
1287 np_in_cksum ((unsigned short *) tcpsumdata,
1288 sizeof (struct pseudohdr) + opt_size_allocated + data_len);
1289 g_free (opts);
1290 g_free (tcpsumdata);
1291
1293 retc->size = (ip->ip_hl * 4) + (tcp->th_off * 4) + data_len;
1294 retc->x.str_val = npkt;
1295 return retc;
1296}
1297
1304tree_cell *
1306{
1307 int i = 0;
1308 u_char *pkt;
1309 while ((pkt = (u_char *) get_str_var_by_num (lexic, i++)) != NULL)
1310 {
1311 int a = 0;
1312 struct ip *ip = (struct ip *) pkt;
1313 struct tcphdr *tcp = (struct tcphdr *) (pkt + ip->ip_hl * 4);
1314 unsigned int j;
1315 unsigned int limit;
1316 char *c;
1317 limit = get_var_size_by_num (lexic, i - 1);
1318 printf ("------\n");
1319 printf ("\tth_sport : %d\n", ntohs (tcp->th_sport));
1320 printf ("\tth_dport : %d\n", ntohs (tcp->th_dport));
1321 printf ("\tth_seq : %u\n", (unsigned int) ntohl (tcp->th_seq));
1322 printf ("\tth_ack : %u\n", (unsigned int) ntohl (tcp->th_ack));
1323 printf ("\tth_x2 : %d\n", tcp->th_x2);
1324 printf ("\tth_off : %d\n", tcp->th_off);
1325 printf ("\tth_flags : ");
1326 if (tcp->th_flags & TH_FIN)
1327 {
1328 printf ("TH_FIN");
1329 a++;
1330 }
1331 if (tcp->th_flags & TH_SYN)
1332 {
1333 if (a)
1334 printf ("|");
1335 printf ("TH_SYN");
1336 a++;
1337 }
1338 if (tcp->th_flags & TH_RST)
1339 {
1340 if (a)
1341 printf ("|");
1342 printf ("TH_RST");
1343 a++;
1344 }
1345 if (tcp->th_flags & TH_PUSH)
1346 {
1347 if (a)
1348 printf ("|");
1349 printf ("TH_PUSH");
1350 a++;
1351 }
1352 if (tcp->th_flags & TH_ACK)
1353 {
1354 if (a)
1355 printf ("|");
1356 printf ("TH_ACK");
1357 a++;
1358 }
1359 if (tcp->th_flags & TH_URG)
1360 {
1361 if (a)
1362 printf ("|");
1363 printf ("TH_URG");
1364 a++;
1365 }
1366 if (!a)
1367 printf ("0");
1368 else
1369 printf (" (%d)", tcp->th_flags);
1370 printf ("\n");
1371 printf ("\tth_win : %d\n", ntohs (tcp->th_win));
1372 printf ("\tth_sum : 0x%x\n", ntohs (tcp->th_sum));
1373 printf ("\tth_urp : %d\n", ntohs (tcp->th_urp));
1374
1375 if (tcp->th_off > 5) // Options present
1376 {
1377 char *options;
1378 struct tcp_options *tcp_all_options;
1379
1380 options =
1381 (char *) g_malloc0 (sizeof (uint8_t) * 4 * (tcp->th_off - 5));
1382 memcpy (options, (char *) tcp + 20, (tcp->th_off - 5) * 4);
1383
1384 tcp_all_options = g_malloc0 (sizeof (struct tcp_options));
1385 get_tcp_options (options, tcp_all_options);
1386 if (tcp_all_options != NULL)
1387 {
1388 printf ("\tTCP Options:\n");
1389 printf ("\t\tTCPOPT_MAXSEG: %u\n",
1390 ntohs ((uint16_t) tcp_all_options->mss.mss));
1391 printf ("\t\tTCPOPT_WINDOW: %u\n",
1392 tcp_all_options->wscale.wscale);
1393 printf ("\t\tTCPOPT_SACK_PERMITTED: %u\n",
1394 tcp_all_options->sack_perm.kind ? 1 : 0);
1395 printf ("\t\tTCPOPT_TIMESTAMP TSval: %u\n",
1396 ntohl ((uint32_t) tcp_all_options->tstamp.tstamp));
1397 printf ("\t\tTCPOPT_TIMESTAMP TSecr: %u\n",
1398 ntohl ((uint32_t) tcp_all_options->tstamp.e_tstamp));
1399 }
1400 g_free (options);
1401 g_free (tcp_all_options);
1402 }
1403
1404 printf ("\n\tData : ");
1405 c = (char *) ((char *) tcp + sizeof (struct tcphdr)
1406 + sizeof (uint8_t) * 4 * (tcp->th_off - 5));
1407 if (UNFIX (ip->ip_len) > (sizeof (struct ip) + sizeof (struct tcphdr)))
1408 for (j = 0; j < UNFIX (ip->ip_len) - sizeof (struct ip)
1409 - sizeof (struct tcphdr)
1410 - sizeof (uint8_t) * 4 * (tcp->th_off - 5)
1411 && j < limit;
1412 j++)
1413 printf ("%c", isprint (c[j]) ? c[j] : '.');
1414 printf ("\n");
1415
1416 printf ("\n");
1417 }
1418 return NULL;
1419}
1420
1421/*--------------[ UDP ]--------------------------------------------*/
1423{
1424 struct in_addr saddr;
1425 struct in_addr daddr;
1426 char zero;
1427 char proto;
1428 unsigned short len;
1429 struct udphdr udpheader;
1431
1451tree_cell *
1453{
1454 tree_cell *retc;
1455 struct ip *ip = (struct ip *) get_str_var_by_name (lexic, "ip");
1456
1457 if (ip != NULL)
1458 {
1459 char *data = get_str_var_by_name (lexic, "data");
1460 size_t data_len = get_var_size_by_name (lexic, "data");
1461 u_char *pkt;
1462 struct ip *udp_packet;
1463 struct udphdr *udp;
1464
1465 pkt = g_malloc0 (sizeof (struct udphdr) + ip->ip_hl * 4
1466 + sizeof (struct udphdr) + data_len);
1467
1468 udp_packet = (struct ip *) pkt;
1469 udp = (struct udphdr *) (pkt + ip->ip_hl * 4);
1470
1471 udp->uh_sport = htons (get_int_var_by_name (lexic, "uh_sport", 0));
1472 udp->uh_dport = htons (get_int_var_by_name (lexic, "uh_dport", 0));
1473 udp->uh_ulen = htons (get_int_var_by_name (
1474 lexic, "uh_ulen", data_len + sizeof (struct udphdr)));
1475
1476 /* printf("len : %d %s\n", len, data); */
1477 if (data_len != 0 && data != NULL)
1478 bcopy (data, (pkt + ip->ip_hl * 4 + sizeof (struct udphdr)), data_len);
1479
1480 udp->uh_sum = get_int_var_by_name (lexic, "uh_sum", 0);
1481 bcopy ((char *) ip, pkt, ip->ip_hl * 4);
1482 if (udp->uh_sum == 0)
1483 {
1485 struct in_addr source, dest;
1486 char *udpsumdata =
1487 g_malloc0 (sizeof (struct pseudo_udp_hdr) + data_len + 1);
1488
1489 source.s_addr = ip->ip_src.s_addr;
1490 dest.s_addr = ip->ip_dst.s_addr;
1491
1492 bzero (&pseudohdr, sizeof (struct pseudo_udp_hdr));
1493 pseudohdr.saddr.s_addr = source.s_addr;
1494 pseudohdr.daddr.s_addr = dest.s_addr;
1495
1496 pseudohdr.proto = IPPROTO_UDP;
1497 pseudohdr.len = htons (sizeof (struct udphdr) + data_len);
1498 bcopy ((char *) udp, (char *) &pseudohdr.udpheader,
1499 sizeof (struct udphdr));
1500 bcopy ((char *) &pseudohdr, udpsumdata, sizeof (pseudohdr));
1501 if (data != NULL)
1502 {
1503 bcopy ((char *) data, udpsumdata + sizeof (pseudohdr), data_len);
1504 }
1505 udp->uh_sum = np_in_cksum ((unsigned short *) udpsumdata,
1506 12 + sizeof (struct udphdr) + data_len);
1507 g_free (udpsumdata);
1508 }
1509
1510 if (UNFIX (udp_packet->ip_len) <= udp_packet->ip_hl * 4)
1511 {
1512 int v = get_int_var_by_name (lexic, "update_ip_len", 1);
1513 if (v != 0)
1514 {
1515 udp_packet->ip_len =
1516 FIX (ntohs (udp->uh_ulen) + (udp_packet->ip_hl * 4));
1517 udp_packet->ip_sum = 0;
1518 udp_packet->ip_sum =
1519 np_in_cksum ((u_short *) udp_packet, udp_packet->ip_hl * 4);
1520 }
1521 }
1522
1524 retc->x.str_val = (char *) pkt;
1525 retc->size = 8 + ip->ip_hl * 4 + data_len;
1526 return retc;
1527 }
1528 else
1529 nasl_perror (lexic,
1530 "forge_udp_packet: Invalid value for the argument 'ip'\n");
1531
1532 return NULL;
1533}
1534
1544tree_cell *
1546{
1547 tree_cell *retc;
1548 char *udp;
1549 char *element;
1550 struct ip *ip;
1551 unsigned int ipsz;
1552 struct udphdr *udphdr;
1553 int ret;
1554
1555 udp = get_str_var_by_name (lexic, "udp");
1556 ipsz = get_var_size_by_name (lexic, "udp");
1557
1558 element = get_str_var_by_name (lexic, "element");
1559 if (udp == NULL || element == NULL)
1560 {
1561 nasl_perror (lexic, "get_udp_element: usage :\nelement = "
1562 "get_udp_element(udp:<udp>,element:<element>\n");
1563 return NULL;
1564 }
1565 ip = (struct ip *) udp;
1566
1567 if (ip->ip_hl * 4 + sizeof (struct udphdr) > ipsz)
1568 return NULL;
1569
1570 udphdr = (struct udphdr *) (udp + ip->ip_hl * 4);
1571 if (!strcmp (element, "uh_sport"))
1572 ret = ntohs (udphdr->uh_sport);
1573 else if (!strcmp (element, "uh_dport"))
1574 ret = ntohs (udphdr->uh_dport);
1575 else if (!strcmp (element, "uh_ulen"))
1576 ret = ntohs (udphdr->uh_ulen);
1577 else if (!strcmp (element, "uh_sum"))
1578 ret = ntohs (udphdr->uh_sum);
1579 else if (!strcmp (element, "data"))
1580 {
1581 int sz;
1583 sz = ntohs (udphdr->uh_ulen) - sizeof (struct udphdr);
1584
1585 if (ntohs (udphdr->uh_ulen) - ip->ip_hl * 4 - sizeof (struct udphdr)
1586 > ipsz)
1587 sz = ipsz - ip->ip_hl * 4 - sizeof (struct udphdr);
1588
1589 retc->x.str_val = g_malloc0 (sz);
1590 retc->size = sz;
1591 bcopy (udp + ip->ip_hl * 4 + sizeof (struct udphdr), retc->x.str_val, sz);
1592 return retc;
1593 }
1594 else
1595 {
1596 nasl_perror (lexic, "%s: '%s' is not a value of a udp packet\n", __func__,
1597 element);
1598 return NULL;
1599 }
1600
1601 retc = alloc_typed_cell (CONST_INT);
1602 retc->x.i_val = ret;
1603 return retc;
1604}
1605
1620tree_cell *
1622{
1623 struct ip *ip = (struct ip *) get_str_var_by_name (lexic, "udp");
1624 unsigned int sz = get_var_size_by_name (lexic, "udp");
1625 char *data = get_str_var_by_name (lexic, "data");
1626 size_t data_len = get_var_size_by_name (lexic, "data");
1627
1628 if (ip != NULL)
1629 {
1630 char *pkt;
1631 struct udphdr *udp;
1632 tree_cell *retc;
1633 int old_len;
1634
1635 if (ip->ip_hl * 4 + sizeof (struct udphdr) > sz)
1636 return NULL;
1637
1638 if (data != NULL)
1639 {
1640 sz = ip->ip_hl * 4 + sizeof (struct udphdr) + data_len;
1641 pkt = g_malloc0 (sz);
1642 bcopy (ip, pkt, ip->ip_hl * 4 + sizeof (struct udphdr));
1643 }
1644 else
1645 {
1646 pkt = g_malloc0 (sz);
1647 bcopy (ip, pkt, sz);
1648 }
1649
1650 ip = (struct ip *) pkt;
1651 if (data != NULL)
1652 {
1653 ip->ip_len = FIX (sz);
1654 ip->ip_sum = 0;
1655 ip->ip_sum = np_in_cksum ((u_short *) ip, ip->ip_hl * 4);
1656 }
1657 udp = (struct udphdr *) (pkt + ip->ip_hl * 4);
1658
1659 udp->uh_sport =
1660 htons (get_int_var_by_name (lexic, "uh_sport", ntohs (udp->uh_sport)));
1661 udp->uh_dport =
1662 htons (get_int_var_by_name (lexic, "uh_dport", ntohs (udp->uh_dport)));
1663 old_len = ntohs (udp->uh_ulen);
1664 udp->uh_ulen =
1665 htons (get_int_var_by_name (lexic, "uh_ulen", ntohs (udp->uh_ulen)));
1666 udp->uh_sum = get_int_var_by_name (lexic, "uh_sum", 0);
1667
1668 if (data != NULL)
1669 {
1670 bcopy (data, pkt + ip->ip_hl * 4 + sizeof (struct udphdr), data_len);
1671 udp->uh_ulen = htons (sizeof (struct udphdr) + data_len);
1672 }
1673
1674 if (udp->uh_sum == 0)
1675 {
1677 struct in_addr source, dest;
1678 int len = old_len - sizeof (struct udphdr);
1679 char *udpsumdata;
1680 char *ptr = NULL;
1681
1682 if (data != NULL)
1683 {
1684 len = data_len;
1685 }
1686
1687 if (len > 0)
1688 {
1689 ptr = (char *) udp + sizeof (struct udphdr);
1690 }
1691
1692 udpsumdata = g_malloc0 (sizeof (struct pseudo_udp_hdr) + len + 1);
1693
1694 source.s_addr = ip->ip_src.s_addr;
1695 dest.s_addr = ip->ip_dst.s_addr;
1696
1697 bzero (&pseudohdr, sizeof (struct pseudo_udp_hdr));
1698 pseudohdr.saddr.s_addr = source.s_addr;
1699 pseudohdr.daddr.s_addr = dest.s_addr;
1700
1701 pseudohdr.proto = IPPROTO_UDP;
1702 pseudohdr.len = htons (sizeof (struct udphdr) + len);
1703 bcopy ((char *) udp, (char *) &pseudohdr.udpheader,
1704 sizeof (struct udphdr));
1705 bcopy ((char *) &pseudohdr, udpsumdata, sizeof (pseudohdr));
1706 if (ptr != NULL)
1707 {
1708 bcopy ((char *) ptr, udpsumdata + sizeof (pseudohdr), len);
1709 }
1710 udp->uh_sum = np_in_cksum ((unsigned short *) udpsumdata,
1711 12 + sizeof (struct udphdr) + len);
1712 g_free (udpsumdata);
1713 }
1715 retc->size = sz;
1716 retc->x.str_val = pkt;
1717 return retc;
1718 }
1719 else
1720 nasl_perror (lexic,
1721 "set_udp_elements: Invalid value for the argument 'udp'.");
1722
1723 return NULL;
1724}
1725
1732tree_cell *
1734{
1735 int i = 0;
1736 u_char *pkt;
1737 while ((pkt = (u_char *) get_str_var_by_num (lexic, i++)) != NULL)
1738 {
1739 struct udphdr *udp = (struct udphdr *) (pkt + sizeof (struct ip));
1740 unsigned int j;
1741 char *c;
1742 unsigned int limit = get_var_size_by_num (lexic, i - 1);
1743 printf ("------\n");
1744 printf ("\tuh_sport : %d\n", ntohs (udp->uh_sport));
1745 printf ("\tuh_dport : %d\n", ntohs (udp->uh_dport));
1746 printf ("\tuh_sum : 0x%x\n", udp->uh_sum);
1747 printf ("\tuh_ulen : %d\n", ntohs (udp->uh_ulen));
1748 printf ("\tdata : ");
1749 c = (char *) udp;
1750 if (udp->uh_ulen > sizeof (struct udphdr))
1751 for (j = sizeof (struct udphdr);
1752 j < (ntohs (udp->uh_ulen)) && j < limit; j++)
1753 printf ("%c", isprint (c[j]) ? c[j] : '.');
1754
1755 printf ("\n");
1756 }
1757 return NULL;
1758}
1759
1760/*--------------[ ICMP ]--------------------------------------------*/
1761
1778tree_cell *
1780{
1781 tree_cell *retc = NULL;
1782 struct ip *ip;
1783 struct ip *ip_icmp;
1784 size_t ip_sz;
1785 struct icmp *icmp;
1786 char *data, *p;
1787 size_t len;
1788 u_char *pkt;
1789 int t;
1790
1791 ip = (struct ip *) get_str_var_by_name (lexic, "ip");
1792 ip_sz = get_var_size_by_name (lexic, "ip");
1793 if (ip != NULL)
1794 {
1795 data = get_str_var_by_name (lexic, "data");
1796 len = data == NULL ? 0 : get_var_size_by_name (lexic, "data");
1797
1798 t = get_int_var_by_name (lexic, "icmp_type", 0);
1799 if (t == 13 || t == 14)
1800 len += 3 * sizeof (time_t);
1801
1802 if (ip->ip_hl * 4 > ip_sz)
1803 return NULL;
1804
1805 pkt = g_malloc0 (sizeof (struct icmp) + ip_sz + len);
1806 ip_icmp = (struct ip *) pkt;
1807
1808 bcopy (ip, ip_icmp, ip_sz);
1809 if (UNFIX (ip_icmp->ip_len) <= (ip_icmp->ip_hl * 4))
1810 {
1811 if (get_int_var_by_name (lexic, "update_ip_len", 1) != 0)
1812 {
1813 ip_icmp->ip_len = FIX (ip->ip_hl * 4 + 8 + len);
1814 ip_icmp->ip_sum = 0;
1815 ip_icmp->ip_sum =
1816 np_in_cksum ((u_short *) ip_icmp, ip->ip_hl * 4);
1817 }
1818 }
1819 p = (char *) (pkt + (ip->ip_hl * 4));
1820 icmp = (struct icmp *) p;
1821
1822 icmp->icmp_code = get_int_var_by_name (lexic, "icmp_code", 0);
1823 icmp->icmp_type = t;
1824 icmp->icmp_seq = htons (get_int_var_by_name (lexic, "icmp_seq", 0));
1825 icmp->icmp_id = htons (get_int_var_by_name (lexic, "icmp_id", 0));
1826
1827 if (data != NULL)
1828 bcopy (data, &(p[8]), len);
1829
1830 if (get_int_var_by_name (lexic, "icmp_cksum", -1) == -1)
1831 icmp->icmp_cksum = np_in_cksum ((u_short *) icmp, len + 8);
1832 else
1833 icmp->icmp_cksum = htons (get_int_var_by_name (lexic, "icmp_cksum", 0));
1834
1836 retc->x.str_val = (char *) pkt;
1837 retc->size = ip_sz + len + 8;
1838 }
1839 else
1840 nasl_perror (lexic, "forge_icmp_packet: missing 'ip' parameter\n");
1841
1842 return retc;
1843}
1844
1854tree_cell *
1856{
1857 struct icmp *icmp;
1858 char *p;
1859
1860 if ((p = get_str_var_by_name (lexic, "icmp")) != NULL)
1861 {
1862 char *elem = get_str_var_by_name (lexic, "element");
1863 int value;
1864 struct ip *ip = (struct ip *) p;
1865 tree_cell *retc;
1866
1867 icmp = (struct icmp *) (p + ip->ip_hl * 4);
1868
1869 if (elem == NULL)
1870 {
1871 nasl_perror (lexic,
1872 "get_icmp_element: missing 'element' parameter\n");
1873 return NULL;
1874 }
1875
1876 if (!strcmp (elem, "icmp_id"))
1877 value = ntohs (icmp->icmp_id);
1878 else if (!strcmp (elem, "icmp_code"))
1879 value = icmp->icmp_code;
1880 else if (!strcmp (elem, "icmp_type"))
1881 value = icmp->icmp_type;
1882 else if (!strcmp (elem, "icmp_seq"))
1883 value = ntohs (icmp->icmp_seq);
1884 else if (!strcmp (elem, "icmp_cksum"))
1885 value = ntohs (icmp->icmp_cksum);
1886 else if (!strcmp (elem, "data"))
1887 {
1889 retc->size =
1890 get_var_size_by_name (lexic, "icmp") - (ip->ip_hl * 4) - 8;
1891 if (retc->size > 0)
1892 {
1893 retc->x.str_val = g_malloc0 (retc->size + 1);
1894 memcpy (retc->x.str_val, &(p[ip->ip_hl * 4 + 8]), retc->size + 1);
1895 }
1896 else
1897 {
1898 retc->x.str_val = NULL;
1899 retc->size = 0;
1900 }
1901 return retc;
1902 }
1903 else
1904 {
1905 nasl_perror (
1906 lexic,
1907 "get_icmp_element: Element '%s' is not a valid element to get.\n",
1908 elem);
1909 return NULL;
1910 }
1911
1912 retc = alloc_typed_cell (CONST_INT);
1913 retc->x.i_val = value;
1914 return retc;
1915 }
1916 else
1917 nasl_perror (lexic, "get_icmp_element: missing 'icmp' parameter\n");
1918
1919 return NULL;
1920}
1921
1928tree_cell *
1930{
1931 int i = 0;
1932 u_char *pkt;
1933 while ((pkt = (u_char *) get_str_var_by_num (lexic, i++)) != NULL)
1934 {
1935 struct ip *ip = (struct ip *) pkt;
1936 struct icmp *icmp;
1937 icmp = (struct icmp *) (pkt + ip->ip_hl * 4);
1938 printf ("------\n");
1939 printf ("\ticmp_id : %d\n", ntohs (icmp->icmp_id));
1940 printf ("\ticmp_code : %d\n", icmp->icmp_code);
1941 printf ("\ticmp_type : %u\n", icmp->icmp_type);
1942 printf ("\ticmp_seq : %u\n", ntohs (icmp->icmp_seq));
1943 printf ("\ticmp_cksum : %d\n", ntohs (icmp->icmp_cksum));
1944 printf ("\tData : %s\n", icmp->icmp_data);
1945 printf ("\n");
1946 }
1947 return NULL;
1948}
1949
1950/*--------------[ IGMP ]--------------------------------------------*/
1951
1952struct igmp
1953{
1954 unsigned char type;
1955 unsigned char code;
1956 unsigned short cksum;
1957 struct in_addr group;
1958};
1959
1974tree_cell *
1976{
1977 struct ip *ip = (struct ip *) get_str_var_by_name (lexic, "ip");
1978
1979 if (ip != NULL)
1980 {
1981 char *data = get_str_var_by_name (lexic, "data");
1982 size_t len = data ? get_var_size_by_name (lexic, "data") : 0;
1983 u_char *pkt = g_malloc0 (sizeof (struct igmp) + ip->ip_hl * 4 + len);
1984 struct ip *ip_igmp = (struct ip *) pkt;
1985 struct igmp *igmp;
1986 char *p;
1987 char *grp;
1988 tree_cell *retc;
1989 size_t ipsz = get_var_size_by_name (lexic, "ip");
1990
1991 bcopy (ip, ip_igmp, ipsz);
1992
1993 if (UNFIX (ip_igmp->ip_len) <= ip_igmp->ip_hl * 4)
1994 {
1995 int v = get_int_var_by_name (lexic, "update_ip_len", 1);
1996 if (v != 0)
1997 {
1998 ip_igmp->ip_len =
1999 FIX (ip->ip_hl * 4 + sizeof (struct igmp) + len);
2000 ip_igmp->ip_sum = 0;
2001 ip_igmp->ip_sum =
2002 np_in_cksum ((u_short *) ip_igmp, ip->ip_hl * 4);
2003 }
2004 }
2005 p = (char *) (pkt + ip_igmp->ip_hl * 4);
2006 igmp = (struct igmp *) p;
2007
2008 igmp->code = get_int_var_by_name (lexic, "code", 0);
2009 igmp->type = get_int_var_by_name (lexic, "type", 0);
2010 grp = get_str_var_by_name (lexic, "group");
2011
2012 if (grp != NULL)
2013 {
2014 inet_aton (grp, &igmp->group);
2015 }
2016
2017 igmp->cksum = np_in_cksum ((u_short *) igmp, sizeof (struct igmp));
2018 if (data != NULL)
2019 {
2020 char *ptmp = (char *) (pkt + ip->ip_hl * 4 + sizeof (struct igmp));
2021 bcopy (ptmp, data, len);
2022 }
2024 retc->x.str_val = (char *) pkt;
2025 retc->size = ip->ip_hl * 4 + sizeof (struct igmp) + len;
2026 return retc;
2027 }
2028 else
2029 nasl_perror (lexic, "forge_igmp_packet: missing 'ip' parameter\n");
2030
2031 return NULL;
2032}
2033
2034/*---------------------------------------------------------------------------*/
2035
2048tree_cell *
2050{
2051 struct script_infos *script_infos = lexic->script_infos;
2052 struct in6_addr *dst = plug_get_host_ip (script_infos);
2053 if (IN6_IS_ADDR_V4MAPPED (dst) != 1)
2054 {
2055 tree_cell *retc = nasl_tcp_v6_ping (lexic);
2056 return retc;
2057 }
2058 int port;
2059 u_char packet[sizeof (struct ip) + sizeof (struct tcphdr)];
2060 int soc;
2061 struct ip *ip = (struct ip *) packet;
2062 struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof (struct ip));
2063 struct in_addr src;
2064 struct sockaddr_in soca;
2065 int flag = 0;
2066 unsigned int i = 0;
2067 int bpf;
2068 char filter[255];
2069 tree_cell *retc;
2070 int opt = 1;
2071 struct timeval tv;
2072 int len;
2073#define rnd_tcp_port() (rand () % 65535 + 1024)
2074 int sports[] = {0, 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2075 0, 0, 0, 0, 0, 53, 0, 0, 20, 0, 25, 0, 0, 0};
2076 int ports[] = {139, 135, 445, 80, 22, 515, 23, 21, 6000, 1025,
2077 25, 111, 1028, 9100, 1029, 79, 497, 548, 5000, 1917,
2078 53, 161, 9001, 65535, 443, 113, 993, 8080};
2079 struct in_addr inaddr;
2080
2081 if (dst == NULL || (IN6_IS_ADDR_V4MAPPED (dst) != 1))
2082 return NULL;
2083 inaddr.s_addr = dst->s6_addr32[3];
2084 for (i = 0; i < sizeof (sports) / sizeof (int); i++)
2085 {
2086 if (sports[i] == 0)
2087 sports[i] = rnd_tcp_port ();
2088 }
2089
2090 soc = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
2091 if (soc < 0)
2092 return NULL;
2093 if (setsockopt (soc, IPPROTO_IP, IP_HDRINCL, (char *) &opt, sizeof (opt)) < 0)
2094 perror ("setsockopt ");
2095
2096 port = get_int_var_by_name (lexic, "port", -1);
2097 if (port == -1)
2099
2100 if (islocalhost (&inaddr) > 0)
2101 src.s_addr = dst->s6_addr32[3];
2102 else
2103 {
2104 bzero (&src, sizeof (src));
2105 routethrough (&inaddr, &src);
2106 }
2107
2108 snprintf (filter, sizeof (filter), "ip and src host %s", inet_ntoa (inaddr));
2109 bpf = init_capture_device (inaddr, src, filter);
2110
2111 if (islocalhost (&inaddr) != 0)
2112 flag++;
2113 else
2114 {
2115 for (i = 0; i < sizeof (sports) / sizeof (int) && !flag; i++)
2116 {
2117 bzero (packet, sizeof (packet));
2118 /* IP */
2119 ip->ip_hl = 5;
2120 ip->ip_off = FIX (0);
2121 ip->ip_v = 4;
2122 ip->ip_len = FIX (40);
2123 ip->ip_tos = 0;
2124 ip->ip_p = IPPROTO_TCP;
2125 ip->ip_id = rand ();
2126 ip->ip_ttl = 0x40;
2127 ip->ip_src = src;
2128 ip->ip_dst = inaddr;
2129 ip->ip_sum = 0;
2130 ip->ip_sum = np_in_cksum ((u_short *) ip, 20);
2131
2132 /* TCP */
2133 tcp->th_sport = port ? htons (rnd_tcp_port ()) : htons (sports[i]);
2134 tcp->th_flags = TH_SYN;
2135 tcp->th_dport = port ? htons (port) : htons (ports[i]);
2136 tcp->th_seq = rand ();
2137 tcp->th_ack = 0;
2138 tcp->th_x2 = 0;
2139 tcp->th_off = 5;
2140 tcp->th_win = 2048;
2141 tcp->th_urp = 0;
2142 tcp->th_sum = 0;
2143
2144 /* CKsum */
2145 {
2146 struct in_addr source, dest;
2147 struct pseudohdr pseudoheader;
2148 source.s_addr = ip->ip_src.s_addr;
2149 dest.s_addr = ip->ip_dst.s_addr;
2150
2151 bzero (&pseudoheader, 12 + sizeof (struct tcphdr));
2152 pseudoheader.saddr.s_addr = source.s_addr;
2153 pseudoheader.daddr.s_addr = dest.s_addr;
2154
2155 pseudoheader.protocol = 6;
2156 pseudoheader.length = htons (sizeof (struct tcphdr));
2157 bcopy ((char *) tcp, (char *) &pseudoheader.tcpheader,
2158 sizeof (struct tcphdr));
2159 tcp->th_sum = np_in_cksum ((unsigned short *) &pseudoheader,
2160 12 + sizeof (struct tcphdr));
2161 }
2162
2163 bzero (&soca, sizeof (soca));
2164 soca.sin_family = AF_INET;
2165 soca.sin_addr = ip->ip_dst;
2166 if (sendto (soc, (const void *) ip, 40, 0, (struct sockaddr *) &soca,
2167 sizeof (soca))
2168 < 0)
2169 g_warning ("sendto: %s", strerror (errno));
2170 tv.tv_sec = 0;
2171 tv.tv_usec = 100000;
2172 if (bpf >= 0 && bpf_next_tv (bpf, &len, &tv))
2173 flag++;
2174 }
2175 }
2176
2177 retc = alloc_typed_cell (CONST_INT);
2178 retc->x.i_val = flag;
2179 if (bpf >= 0)
2180 bpf_close (bpf);
2181 close (soc);
2182 return retc;
2183}
2184
2185/*---------------------------------------------------------------------------*/
2186
2202tree_cell *
2204{
2205 tree_cell *retc = FAKE_CELL;
2206 int bpf = -1;
2207 u_char *answer;
2208 int answer_sz;
2209 struct sockaddr_in sockaddr;
2210 char *ip = NULL;
2211 struct ip *sip = NULL;
2212 int vi = 0;
2213 ssize_t b;
2214 long int len = 0;
2215 int soc;
2216 int use_pcap = get_int_var_by_name (lexic, "pcap_active", 1);
2217 int to = get_int_var_by_name (lexic, "pcap_timeout", 5);
2218 char *filter = get_str_var_by_name (lexic, "pcap_filter");
2219 long int dfl_len = get_int_var_by_name (lexic, "length", -1);
2220 int opt_on = 1;
2221 struct script_infos *script_infos = lexic->script_infos;
2222 struct in6_addr *dstip = plug_get_host_ip (script_infos);
2223 struct in_addr inaddr;
2224 int allow_broadcast = 0;
2225
2226 if (dstip == NULL || (IN6_IS_ADDR_V4MAPPED (dstip) != 1))
2227 return NULL;
2228 inaddr.s_addr = dstip->s6_addr32[3];
2229 soc = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
2230 if (soc < 0)
2231 return NULL;
2232 if (setsockopt (soc, IPPROTO_IP, IP_HDRINCL, (char *) &opt_on,
2233 sizeof (opt_on))
2234 < 0)
2235 perror ("setsockopt ");
2236
2237 while ((ip = get_str_var_by_num (lexic, vi)) != NULL)
2238 {
2239 allow_broadcast = get_int_var_by_name (lexic, "allow_broadcast", 0);
2240 long int sz = get_var_size_by_num (lexic, vi);
2241 vi++;
2242
2243 if ((unsigned int) sz < sizeof (struct ip))
2244 {
2245 nasl_perror (lexic, "send_packet: packet is too short\n");
2246 continue;
2247 }
2248
2249 sip = (struct ip *) ip;
2250 if (use_pcap != 0 && bpf < 0)
2251 bpf = init_capture_device (sip->ip_dst, sip->ip_src, filter);
2252
2253 bzero (&sockaddr, sizeof (struct sockaddr_in));
2254 sockaddr.sin_family = AF_INET;
2255 sockaddr.sin_addr = sip->ip_dst;
2256
2257 if (allow_broadcast)
2258 {
2259 if (setsockopt (soc, SOL_SOCKET, SO_BROADCAST, &opt_on,
2260 sizeof (opt_on))
2261 < 0)
2262 perror ("setsockopt ");
2263 if (sockaddr.sin_addr.s_addr != INADDR_BROADCAST)
2264 allow_broadcast = 0;
2265 }
2266
2267 if (sockaddr.sin_addr.s_addr != inaddr.s_addr && !allow_broadcast)
2268 {
2269 char txt1[64], txt2[64];
2270 strncpy (txt1, inet_ntoa (sockaddr.sin_addr), sizeof (txt1));
2271 txt1[sizeof (txt1) - 1] = '\0';
2272 strncpy (txt2, inet_ntoa (inaddr), sizeof (txt2));
2273 txt2[sizeof (txt2) - 1] = '\0';
2274 nasl_perror (lexic,
2275 "send_packet: malicious or buggy script is trying to "
2276 "send packet to %s instead of designated target %s\n",
2277 txt1, txt2);
2278#if 1
2279 if (bpf >= 0)
2280 bpf_close (bpf);
2281 close (soc);
2282 return NULL;
2283#else
2284 sip->ip_dst = inaddr;
2285 sip->ip_sum = np_in_cksum ((u_short *) sip, sizeof (struct ip));
2286#endif
2287 }
2288
2289 if (dfl_len > 0 && dfl_len < sz)
2290 len = dfl_len;
2291 else
2292 len = sz;
2293
2294 b = sendto (soc, (u_char *) ip, len, 0, (struct sockaddr *) &sockaddr,
2295 sizeof (sockaddr));
2296 /* if(b < 0) perror("sendto "); */
2297 if (b >= 0 && use_pcap != 0 && bpf >= 0)
2298 {
2299 if (islocalhost (&sip->ip_dst))
2300 {
2301 answer = (u_char *) capture_next_packet (bpf, to, &answer_sz);
2302 while (answer != NULL
2303 && (!memcmp (answer, (char *) ip, sizeof (struct ip))))
2304 {
2305 g_free (answer);
2306 answer = (u_char *) capture_next_packet (bpf, to, &answer_sz);
2307 }
2308 }
2309 else
2310 answer = (u_char *) capture_next_packet (bpf, to, &answer_sz);
2311
2312 if (answer)
2313 {
2315 retc->x.str_val = (char *) answer;
2316 retc->size = answer_sz;
2317 break;
2318 }
2319 }
2320 }
2321 if (bpf >= 0)
2322 bpf_close (bpf);
2323 close (soc);
2324 return retc;
2325}
2326
2327/*---------------------------------------------------------------------------*/
2328
2340tree_cell *
2342{
2343 char *interface = get_str_var_by_name (lexic, "interface");
2344 int bpf = -1;
2345 static char errbuf[PCAP_ERRBUF_SIZE];
2346 int is_ip = 0;
2347 struct ip *ret = NULL;
2348 struct ip6_hdr *ret6 = NULL;
2349 char *filter = get_str_var_by_name (lexic, "pcap_filter");
2350 pcap_if_t *alldevsp = NULL; /* list of capture devices */
2351 int timeout = get_int_var_by_name (lexic, "timeout", 5);
2352 tree_cell *retc;
2353 int sz;
2354 struct in6_addr *dst = plug_get_host_ip (lexic->script_infos);
2355 struct in_addr inaddr;
2356
2357 if (dst == NULL)
2358 {
2359 return NULL;
2360 }
2361 int v4_addr = IN6_IS_ADDR_V4MAPPED (dst);
2362 if (interface == NULL)
2363 {
2364 if (v4_addr)
2365 {
2366 struct in_addr src;
2367 bzero (&src, sizeof (src));
2368 inaddr.s_addr = dst->s6_addr32[3];
2369 interface = routethrough (&inaddr, &src);
2370 }
2371 else
2372 {
2373 struct in6_addr src;
2374 bzero (&src, sizeof (src));
2375 interface = v6_routethrough (dst, &src);
2376 }
2377 if (interface == NULL)
2378 {
2379 if (pcap_findalldevs (&alldevsp, errbuf) < 0)
2380 g_message ("Error for pcap_findalldevs(): %s", errbuf);
2381 if (alldevsp != NULL)
2382 interface = alldevsp->name;
2383 }
2384 }
2385
2386 if (interface != NULL)
2387 {
2388 bpf = bpf_open_live (interface, filter);
2389 }
2390
2391 if (bpf < 0)
2392 {
2393 nasl_perror (lexic, "pcap_next: Could not get a bpf\n");
2394 return NULL;
2395 }
2396 else
2397 {
2398 int len;
2399 int dl_len = get_datalink_size (bpf_datalink (bpf));
2400 char *packet;
2401 struct timeval then, now;
2402
2403 gettimeofday (&then, NULL);
2404 for (;;)
2405 {
2406 packet = (char *) bpf_next (bpf, &len);
2407
2408 if (packet != NULL)
2409 break;
2410
2411 if (timeout != 0)
2412 {
2413 gettimeofday (&now, NULL);
2414 if (now.tv_sec - then.tv_sec >= timeout)
2415 {
2416 break;
2417 }
2418 }
2419 }
2420
2421 if (packet)
2422 {
2423 if (v4_addr)
2424 {
2425 struct ip *ip;
2426 ip = (struct ip *) (packet + dl_len);
2427 sz = UNFIX (ip->ip_len);
2428 ret = g_malloc0 (sz);
2429
2430 is_ip = (ip->ip_v == 4);
2431
2432 if (is_ip)
2433 {
2434 bcopy (ip, ret, sz);
2435 }
2436 else
2437 {
2438 sz = len - dl_len;
2439 bcopy (ip, ret, sz);
2440 }
2441 }
2442 else
2443 {
2444 struct ip6_hdr *ip;
2445 ip = (struct ip6_hdr *) (packet + dl_len);
2446 sz = UNFIX (ip->ip6_plen);
2447 ret6 = g_malloc0 (sz);
2448
2449 is_ip = ((ip->ip6_flow & 0x3ffff) == 96);
2450 if (is_ip)
2451 {
2452 bcopy (ip, ret6, sz);
2453 }
2454 else
2455 {
2456 sz = len - dl_len;
2457 bcopy (ip, ret6, sz);
2458 }
2459 }
2460 }
2461 else
2462 {
2463 bpf_close (bpf);
2464 return NULL;
2465 }
2466 }
2467 bpf_close (bpf);
2469 if (v4_addr)
2470 retc->x.str_val = (char *) ret;
2471 else
2472 retc->x.str_val = (char *) ret6;
2473 retc->size = sz;
2474
2475 if (alldevsp != NULL)
2476 pcap_freealldevs (alldevsp);
2477
2478 return retc;
2479}
2480
2490tree_cell *
2492{
2493 char *interface = get_str_var_by_name (lexic, "interface");
2494 int bpf = -1;
2495 static char errbuf[PCAP_ERRBUF_SIZE];
2496 int is_ip = 0;
2497 struct ip *ret = NULL;
2498 struct ip6_hdr *ret6 = NULL;
2499 char *filter = get_str_var_by_name (lexic, "pcap_filter");
2500 pcap_if_t *alldevsp = NULL; /* list of capture devices */
2501 int timeout = get_int_var_by_name (lexic, "timeout", 5);
2502 tree_cell *retc;
2503 int sz;
2504 struct in6_addr *dst = plug_get_host_ip (lexic->script_infos);
2505 struct in_addr inaddr;
2506
2507 if (dst == NULL)
2508 return NULL;
2509
2510 int v4_addr = IN6_IS_ADDR_V4MAPPED (dst);
2511 if (interface == NULL)
2512 {
2513 if (v4_addr)
2514 {
2515 struct in_addr src;
2516 bzero (&src, sizeof (src));
2517 inaddr.s_addr = dst->s6_addr32[3];
2518 interface = routethrough (&inaddr, &src);
2519 }
2520 else
2521 {
2522 struct in6_addr src;
2523 bzero (&src, sizeof (src));
2524 interface = v6_routethrough (dst, &src);
2525 }
2526 if (interface == NULL)
2527 {
2528 if (pcap_findalldevs (&alldevsp, errbuf) < 0)
2529 g_message ("Error for pcap_findalldevs(): %s", errbuf);
2530 if (alldevsp != NULL)
2531 interface = alldevsp->name;
2532 }
2533 }
2534
2535 if (interface != NULL)
2536 bpf = bpf_open_live (interface, filter);
2537
2538 if (bpf < 0)
2539 {
2540 nasl_perror (lexic, "pcap_next: Could not get a bpf\n");
2541 if (alldevsp != NULL)
2542 pcap_freealldevs (alldevsp);
2543 return NULL;
2544 }
2545 else
2546 {
2547 int len;
2548 int dl_len = get_datalink_size (bpf_datalink (bpf));
2549 char *packet;
2550 struct timeval then, now;
2551
2552 retc = nasl_send (lexic);
2553 g_free (retc);
2554
2555 gettimeofday (&then, NULL);
2556 for (;;)
2557 {
2558 packet = (char *) bpf_next (bpf, &len);
2559
2560 if (packet != NULL)
2561 break;
2562
2563 if (timeout != 0)
2564 {
2565 gettimeofday (&now, NULL);
2566 if (now.tv_sec - then.tv_sec >= timeout)
2567 break;
2568 }
2569 }
2570
2571 if (packet)
2572 {
2573 if (v4_addr)
2574 {
2575 struct ip *ip;
2576 ip = (struct ip *) (packet + dl_len);
2577 sz = UNFIX (ip->ip_len);
2578 ret = g_malloc0 (sz);
2579
2580 is_ip = (ip->ip_v == 4);
2581 if (is_ip)
2582 {
2583 bcopy (ip, ret, sz);
2584 }
2585 else
2586 {
2587 sz = len - dl_len;
2588 bcopy (ip, ret, sz);
2589 }
2590 }
2591 else
2592 {
2593 struct ip6_hdr *ip;
2594 ip = (struct ip6_hdr *) (packet + dl_len);
2595 sz = UNFIX (ip->ip6_plen);
2596 ret6 = g_malloc0 (sz);
2597 is_ip = ((ip->ip6_flow & 0x3ffff) == 96);
2598 if (is_ip)
2599 {
2600 bcopy (ip, ret6, sz);
2601 }
2602 else
2603 {
2604 sz = len - dl_len;
2605 bcopy (ip, ret6, sz);
2606 }
2607 }
2608 }
2609 else
2610 {
2611 if (alldevsp != NULL)
2612 pcap_freealldevs (alldevsp);
2613 bpf_close (bpf);
2614 return NULL;
2615 }
2616 }
2617 bpf_close (bpf);
2619 if (v4_addr)
2620 retc->x.str_val = (char *) ret;
2621 else
2622 retc->x.str_val = (char *) ret6;
2623 retc->size = sz;
2624
2625 if (alldevsp != NULL)
2626 pcap_freealldevs (alldevsp);
2627
2628 return retc;
2629}
int bpf_open_live(char *iface, char *filter)
Definition bpf_share.c:39
int bpf_datalink(int bpf)
Definition bpf_share.c:158
u_char * bpf_next_tv(int bpf, int *caplen, struct timeval *tv)
Definition bpf_share.c:119
void bpf_close(int bpf)
Definition bpf_share.c:164
u_char * bpf_next(int bpf, int *caplen)
Definition bpf_share.c:150
Header file for module bpf_share.
int init_capture_device(struct in_addr src, struct in_addr dest, char *filter)
Set up the pcap filter, and select the correct interface.
struct ip * capture_next_packet(int bpf, int timeout, int *sz)
static struct timeval timeval(unsigned long val)
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition nasl_debug.c:105
const char * name
Definition nasl_init.c:440
long int get_var_size_by_num(lex_ctxt *, int)
Definition nasl_var.c:1145
struct struct_lex_ctxt lex_ctxt
char * get_str_var_by_name(lex_ctxt *, const char *)
Definition nasl_var.c:1118
char * get_str_var_by_num(lex_ctxt *, int)
Definition nasl_var.c:1108
long int get_int_var_by_num(lex_ctxt *, int, int)
Definition nasl_var.c:1094
long int get_int_var_by_name(lex_ctxt *, const char *, int)
Definition nasl_var.c:1101
long int get_var_size_by_name(lex_ctxt *, const char *)
Definition nasl_var.c:1138
#define code
#define UNFIX(n)
tree_cell * insert_ip_options(lex_ctxt *lexic)
Add option datagram.
#define FIX(n)
tree_cell * nasl_tcp_ping(lex_ctxt *lexic)
Launches a “TCP ping” against the target host.
tree_cell * set_udp_elements(lex_ctxt *lexic)
Modify UDP fields of an IP datagram.
tree_cell * get_tcp_element(lex_ctxt *lexic)
Extracts TCP field from an IP datagram.
static int np_in_cksum(u_short *p, int n)
tree_cell * get_tcp_option(lex_ctxt *lexic)
Get a TCP option from an IP datagram if present. Possible options are: TCPOPT_MAXSEG (2),...
uint8_t len
#define rnd_tcp_port()
tree_cell * forge_ip_packet(lex_ctxt *lexic)
Forge an IP datagram.
tree_cell * dump_icmp_packet(lex_ctxt *lexic)
Dump the ICMP part of a IP Datagram.
tree_cell * set_ip_elements(lex_ctxt *lexic)
Modify the fields of a datagram.
tree_cell * dump_ip_packet(lex_ctxt *lexic)
Dump IP datagrams.
static void get_tcp_options(char *options, struct tcp_options *tcp_all_options)
Extract all TCP option from an IP datagram.
tree_cell * insert_tcp_options(lex_ctxt *lexic)
Add options to a TCP segment header. Possible options are: TCPOPT_MAXSEG (2), values between 536 and ...
tree_cell * nasl_pcap_next(lex_ctxt *lexic)
Listen to one packet and return it.
tree_cell * set_tcp_elements(lex_ctxt *lexic)
Modify the TCP fields of a datagram.
tree_cell * dump_tcp_packet(lex_ctxt *lexic)
Dump the TCP part of a IP Datagram.
tree_cell * forge_tcp_packet(lex_ctxt *lexic)
Fills an IP datagram with TCP data. Note that the ip_p field is not updated. It returns the modified ...
tree_cell * dump_udp_packet(lex_ctxt *lexic)
Dump the UDP part of a IP Datagram.
tree_cell * get_icmp_element(lex_ctxt *lexic)
Get an ICMP element from a IP datagram.
tree_cell * nasl_send_packet(lex_ctxt *lexic)
Send a list of packets (passed as unnamed arguments) and listens to the answers. It returns a block m...
tree_cell * nasl_send_capture(lex_ctxt *lexic)
Send a capture.
tree_cell * forge_icmp_packet(lex_ctxt *lexic)
Fill an IP datagram with ICMP data.
u_char zero
tree_cell * get_udp_element(lex_ctxt *lexic)
Get an UDP element from a IP datagram.
tree_cell * forge_udp_packet(lex_ctxt *lexic)
Fills an IP datagram with UDP data. Note that the ip_p field is not updated. It returns the modified ...
tree_cell * get_ip_element(lex_ctxt *lexic)
Extracts a field from an IP datagram.
struct pseudo_udp_hdr __attribute__
tree_cell * forge_igmp_packet(lex_ctxt *lexic)
Fills an IP datagram with IGMP data.
tree_cell * nasl_tcp_v6_ping(lex_ctxt *lexic)
Performs TCP Connect to test if host is alive.
tree_cell * nasl_send(lex_ctxt *lexic)
tree_cell * alloc_typed_cell(int typ)
Definition nasl_tree.c:25
@ CONST_DATA
Definition nasl_tree.h:82
@ DYN_ARRAY
Definition nasl_tree.h:90
@ CONST_INT
Definition nasl_tree.h:79
struct TC tree_cell
#define FAKE_CELL
Definition nasl_tree.h:110
int add_var_to_array(nasl_array *a, char *name, const anon_nasl_var *v)
Definition nasl_var.c:1277
struct st_a_nasl_var anon_nasl_var
struct st_nasl_array nasl_array
@ VAR2_INT
Definition nasl_var.h:16
int islocalhost(struct in_addr *addr)
Tests whether a packet sent to IP is LIKELY to route through the kernel localhost interface.
Definition pcap.c:271
char * routethrough(struct in_addr *dest, struct in_addr *source)
An awesome function to determine what interface a packet to a given destination should be routed thro...
Definition pcap.c:1070
char * v6_routethrough(struct in6_addr *dest, struct in6_addr *source)
An awesome function to determine what interface a packet to a given destination should be routed thro...
Definition pcap.c:851
int get_datalink_size(int datalink)
Definition pcap.c:298
Header file for module pcap.
unsigned int plug_get_host_open_port(struct script_infos *desc)
Definition plugutils.c:1328
struct in6_addr * plug_get_host_ip(struct script_infos *args)
Definition plugutils.c:371
Header file for module plugutils.
long int i_val
Definition nasl_tree.h:104
long int size
Definition nasl_tree.h:99
union TC::@332262321161220155002104006201360276211317150140 x
char * str_val
Definition nasl_tree.h:103
void * ref_val
Definition nasl_tree.h:105
struct in_addr group
unsigned char type
unsigned char code
unsigned short cksum
struct udphdr udpheader
struct in_addr saddr
struct in_addr daddr
struct tcphdr tcpheader
union st_a_nasl_var::@154137074032032170165360023270032033276061363156 v
long int v_int
Definition nasl_var.h:48
struct script_infos * script_infos
struct tcp_opt_wscale wscale
struct tcp_opt_mss mss
struct tcp_opt_tstamp tstamp
struct tcp_opt_sack_perm sack_perm