OpenVAS Scanner  22.7.9
nasl_frame_forgery.c
Go to the documentation of this file.
1 /* SPDX-FileCopyrightText: 2023 Greenbone AG
2  *
3  * SPDX-License-Identifier: GPL-2.0-or-later
4  */
5 
11 #include "nasl_frame_forgery.h"
12 
13 #include "../misc/bpf_share.h" /* for bpf_open_live */
14 #include "../misc/pcap_openvas.h"
15 #include "../misc/pcap_openvas.h" /* for get_iface_from_ip */
16 #include "../misc/plugutils.h"
17 #include "capture_packet.h"
18 #include "nasl_debug.h"
19 
20 #include <errno.h>
21 #include <gvm/base/networking.h>
22 #include <linux/if_packet.h>
23 #include <net/ethernet.h>
24 #include <net/if.h>
25 #include <net/if_arp.h>
26 #include <netinet/ether.h>
27 #include <netinet/if_ether.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/ioctl.h>
32 #include <unistd.h>
33 
34 #undef G_LOG_DOMAIN
35 
38 #define G_LOG_DOMAIN "lib misc"
39 
41 {
42  struct arphdr arp_header;
43  u_char __ar_sha[ETH_ALEN]; /* Sender hardware address. */
44  u_char __ar_sip[4]; /* Sender IP address. */
45  u_char __ar_tha[ETH_ALEN]; /* Target hardware address. */
46  u_char __ar_tip[4]; /* Target IP address. */
47  u_char __zero_padding[18];
48 } __attribute__ ((packed));
49 
51 {
52  struct ethhdr framehdr;
53  u_char *payload;
54 } __attribute__ ((packed));
55 
62 static void
63 dump_frame (const u_char *frame, int frame_sz)
64 {
65  int f = 0;
66 
67  printf ("\nThe Frame:\n");
68  while (f < frame_sz)
69  {
70  printf ("%02x%02x ", ((u_char *) frame)[f], ((u_char *) frame)[f + 1]);
71  f += 2;
72  if (f % 16 == 0)
73  printf ("\n");
74  }
75  printf ("\n\n");
76 }
77 
84 static void
85 prepare_sockaddr_ll (struct sockaddr_ll *soc_addr_ll, int ifindex,
86  const u_char *ether_dst_addr)
87 {
88  soc_addr_ll->sll_family = AF_PACKET;
89  soc_addr_ll->sll_ifindex = ifindex;
90  soc_addr_ll->sll_halen = ETHER_ADDR_LEN;
91  soc_addr_ll->sll_protocol = htons (ETH_P_ALL);
92  memcpy (soc_addr_ll->sll_addr, ether_dst_addr, ETHER_ADDR_LEN);
93 }
94 
102 static void
103 prepare_message (u_char *msg, struct sockaddr_ll *soc_addr_ll, u_char *payload,
104  int payload_sz)
105 {
106  struct iovec iov;
107  struct msghdr *message;
108 
109  iov.iov_base = payload;
110  iov.iov_len = payload_sz;
111 
112  message = g_malloc0 (sizeof (struct msghdr) + payload_sz);
113 
114  message->msg_name = soc_addr_ll;
115  message->msg_namelen = sizeof (struct sockaddr_ll);
116  message->msg_iov = &iov;
117  message->msg_iovlen = 1;
118  message->msg_control = 0;
119  message->msg_controllen = 0;
120 
121  memcpy (msg, (u_char *) message, sizeof (struct msghdr) + payload_sz);
122  g_free (message);
123 }
124 
140 static int
141 send_frame (const u_char *frame, int frame_sz, int use_pcap, int timeout,
142  char *filter, struct in6_addr *ipaddr, u_char **answer)
143 {
144  int soc;
145  u_char *message;
146  int ifindex;
147  int bpf = -1;
148  int frame_and_payload = 0;
149  int answer_sz = -1;
150 
151  // Create the raw socket
152  soc = socket (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
153  if (soc == -1)
154  {
155  g_debug ("%s: %s", __func__, strerror (errno));
156  return -1;
157  }
158 
159  // We will need the eth index. We get it depending on the target's IP..
160  if (get_iface_index (ipaddr, &ifindex) < 0)
161  {
162  g_message ("%s: Missing interface index\n", __func__);
163  return -1;
164  }
165 
166  // Prepare sockaddr_ll. This is necessary for further captures
167  u_char dst_haddr[ETHER_ADDR_LEN];
168  memcpy (&dst_haddr, (struct pseudo_frame *) frame, ETHER_ADDR_LEN);
169 
170  struct sockaddr_ll soc_addr;
171  memset (&soc_addr, '\0', sizeof (struct sockaddr_ll));
172  prepare_sockaddr_ll (&soc_addr, ifindex, dst_haddr);
173 
174  /* Init capture */
175  if (use_pcap != 0 && bpf < 0)
176  {
177  if (IN6_IS_ADDR_V4MAPPED (ipaddr))
178  {
179  struct in_addr sin, this_host;
180  memset (&sin, '\0', sizeof (struct in_addr));
181  memset (&this_host, '\0', sizeof (struct in_addr));
182  sin.s_addr = ipaddr->s6_addr32[3];
183  bpf = init_capture_device (sin, this_host, filter);
184  }
185  else
186  {
187  struct in6_addr this_host;
188  memset (&this_host, '\0', sizeof (struct in6_addr));
189  bpf = init_v6_capture_device (*ipaddr, this_host, filter);
190  }
191  }
192 
193  // Prepare the message and send it
194  message = g_malloc0 (sizeof (struct msghdr) + frame_sz);
195  prepare_message (message, &soc_addr, (u_char *) frame, frame_sz);
196 
197  int b = sendmsg (soc, (struct msghdr *) message, 0);
198  g_free (message);
199  if (b == -1)
200  {
201  g_message ("%s: Error sending message: %s", __func__, strerror (errno));
202  return -2;
203  }
204  if (bpf >= 0)
205  {
206  *answer = (u_char *) capture_next_frame (bpf, timeout, &answer_sz,
207  frame_and_payload);
208  bpf_close (bpf);
209  close (soc);
210  return answer_sz;
211  }
212 
213  close (soc);
214  return 0;
215 }
216 
229 static int
230 forge_frame (const u_char *ether_src_addr, const u_char *ether_dst_addr,
231  int ether_proto, u_char *payload, int payload_sz,
232  struct pseudo_frame **frame)
233 {
234  int frame_sz;
235 
236  *frame = (struct pseudo_frame *) g_malloc0 (sizeof (struct pseudo_frame)
237  + payload_sz);
238 
239  memcpy ((*frame)->framehdr.h_dest, ether_dst_addr, ETHER_ADDR_LEN);
240  memcpy ((*frame)->framehdr.h_source, ether_src_addr, ETHER_ADDR_LEN);
241  (*frame)->framehdr.h_proto = htons (ether_proto);
242  (*frame)->payload = payload;
243 
244  frame_sz = ETH_HLEN + payload_sz;
245  memcpy ((char *) *frame + ETH_HLEN, payload, payload_sz);
246 
247  return frame_sz;
248 }
249 
267 tree_cell *
269 {
270  tree_cell *retc;
271  struct pseudo_frame *frame;
272  int frame_sz;
273  u_char *payload = (u_char *) get_str_var_by_name (lexic, "payload");
274  int payload_sz = get_var_size_by_name (lexic, "payload");
275  char *ether_src_addr = get_str_var_by_name (lexic, "src_haddr");
276  char *ether_dst_addr = get_str_var_by_name (lexic, "dst_haddr");
277  int ether_proto = get_int_var_by_name (lexic, "ether_proto", 0x0800);
278 
279  if (ether_src_addr == NULL || ether_dst_addr == NULL || payload == NULL)
280  {
281  nasl_perror (lexic,
282  "%s usage: payload, src_haddr and dst_haddr are mandatory "
283  "parameters.\n",
284  __func__);
285  return NULL;
286  }
287 
288  frame_sz = forge_frame ((u_char *) ether_src_addr, (u_char *) ether_dst_addr,
289  ether_proto, payload, payload_sz, &frame);
290 
291  retc = alloc_typed_cell (CONST_DATA);
292  retc->x.str_val = (char *) frame;
293  retc->size = frame_sz;
294  return retc;
295 }
296 
313 tree_cell *
315 {
316  tree_cell *retc = NULL;
317  struct script_infos *script_infos = lexic->script_infos;
318  struct in6_addr *ipaddr = plug_get_host_ip (script_infos);
319  u_char *frame = (u_char *) get_str_var_by_name (lexic, "frame");
320  int frame_sz = get_var_size_by_name (lexic, "frame");
321  int use_pcap = get_int_var_by_name (lexic, "pcap_active", 1);
322  int to = get_int_var_by_name (lexic, "pcap_timeout", 5);
323  char *filter = get_str_var_by_name (lexic, "pcap_filter");
324  u_char *answer = NULL;
325  int answer_sz;
326 
327  if (frame == NULL || frame_sz <= 0)
328  {
329  nasl_perror (lexic, "%s usage: frame is a mandatory parameters.\n",
330  __func__);
331  return NULL;
332  }
333 
334  answer_sz =
335  send_frame (frame, frame_sz, use_pcap, to, filter, ipaddr, &answer);
336  if (answer_sz == -2)
337  {
338  g_message ("%s: Not possible to send the frame", __func__);
339  return NULL;
340  }
341 
342  if (answer && answer_sz > -1)
343  {
344  retc = alloc_typed_cell (CONST_DATA);
345  retc->x.str_val = (char *) answer;
346  retc->size = answer_sz;
347  }
348 
349  return retc;
350 }
351 
362 tree_cell *
364 {
365  u_char *frame = (u_char *) get_str_var_by_name (lexic, "frame");
366  int frame_sz = get_var_size_by_name (lexic, "frame");
367 
368  if (frame == NULL || frame_sz <= 0)
369  {
370  nasl_perror (lexic, "%s usage: frame is a mandatory parameters.\n",
371  __func__);
372  return NULL;
373  }
374 
375  dump_frame (frame, frame_sz);
376  return NULL;
377 }
378 
388 static int
389 get_local_mac_address_from_ip (char *ip_address, u_char *mac)
390 {
391  struct ifreq ifr;
392  int sock;
393  char *if_name = NULL;
394 
395  if_name = get_iface_from_ip (ip_address);
396  if (!if_name)
397  {
398  g_debug ("%s: Missing interface name", __func__);
399  return -1;
400  }
401 
402  strncpy (ifr.ifr_name, if_name, sizeof (ifr.ifr_name) - 1);
403  g_free (if_name);
404  ifr.ifr_name[sizeof (ifr.ifr_name) - 1] = '\0';
405 
406  sock = socket (PF_INET, SOCK_STREAM, 0);
407  if (-1 == sock)
408  {
409  perror ("socket() ");
410  return -1;
411  }
412 
413  if (-1 == ioctl (sock, SIOCGIFHWADDR, &ifr))
414  {
415  g_debug ("%s: ioctl(SIOCGIFHWADDR)", __func__);
416  return -1;
417  }
418 
419  memcpy (mac, (u_char *) ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
420  close (sock);
421 
422  return 0;
423 }
424 
437 tree_cell *
439 {
440  tree_cell *retc = NULL;
441  char *buffer = NULL;
442  u_char *mac;
443 
444  char *ip_address = get_str_var_by_num (lexic, 0);
445 
446  mac = g_malloc0 (sizeof (u_char) * ETHER_ADDR_LEN);
447  get_local_mac_address_from_ip (ip_address, mac);
448  if (mac != NULL)
449  {
450  buffer = g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1],
451  mac[2], mac[3], mac[4], mac[5]);
452  g_free (mac);
453  retc = alloc_typed_cell (CONST_DATA);
454  retc->x.str_val = buffer;
455  retc->size = 17;
456  }
457 
458  return retc;
459 }
460 
470 tree_cell *
472 {
473  tree_cell *retc = NULL;
474  struct in6_addr src, *dst = plug_get_host_ip (lexic->script_infos);
475  struct in_addr dst_inaddr, src_inaddr;
476  struct pseudo_eth_arp eth_arp;
477  struct pseudo_frame *frame;
478  int frame_sz;
479  char ip_src_str[INET6_ADDRSTRLEN];
480  u_char mac_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
481  u_char mac[6], *mac_aux;
482  char filter[255];
483  u_char *answer = NULL;
484  int answer_sz;
485  int to = get_int_var_by_name (lexic, "pcap_timeout", 5);
486 
487  /* Get source IP address via routethrough. We need it to find our mac address.
488  */
489  if (dst == NULL || (IN6_IS_ADDR_V4MAPPED (dst) != 1))
490  return retc;
491 
492  memset (&dst_inaddr, '\0', sizeof (struct in_addr));
493  dst_inaddr.s_addr = dst->s6_addr32[3];
494  routethrough (&dst_inaddr, &src_inaddr);
495  ipv4_as_ipv6 (&src_inaddr, &src);
496 
497  /* Getting target IP address as string, to get the mac address */
498  addr6_to_str (&src, ip_src_str);
499 
500  mac_aux = (u_char *) g_malloc0 (sizeof (u_char) * 6);
501  get_local_mac_address_from_ip (ip_src_str, mac_aux);
502  mac[0] = mac_aux[0];
503  mac[1] = mac_aux[1];
504  mac[2] = mac_aux[2];
505  mac[3] = mac_aux[3];
506  mac[4] = mac_aux[4];
507  mac[5] = mac_aux[5];
508  g_free (mac_aux);
509 
510  /* Building ARP header */
511  memset (&eth_arp, '\0', sizeof (struct pseudo_eth_arp));
512  eth_arp.arp_header.ar_hrd = htons (ARPHRD_ETHER);
513  eth_arp.arp_header.ar_pro = htons (ETHERTYPE_IP);
514  eth_arp.arp_header.ar_hln = ETH_ALEN;
515  eth_arp.arp_header.ar_pln = 4;
516  eth_arp.arp_header.ar_op = htons (ARPOP_REQUEST);
517 
518  memcpy (&(eth_arp.__ar_sha), mac, ETH_ALEN);
519  memcpy (&(eth_arp.__ar_sip), &src_inaddr, 4);
520  memcpy (&(eth_arp.__ar_tha), mac_broadcast_addr, ETH_ALEN);
521  memcpy (&(eth_arp.__ar_tip), &dst_inaddr, 4);
522 
523  frame_sz =
524  forge_frame (mac, mac_broadcast_addr, ETH_P_ARP, (u_char *) &eth_arp,
525  sizeof (struct pseudo_eth_arp), &frame);
526 
527  /* Prepare filter */
528  snprintf (filter, sizeof (filter), "arp and src host %s",
529  inet_ntoa (dst_inaddr));
530 
531  answer_sz =
532  send_frame ((const u_char *) frame, frame_sz, 1, to, filter, dst, &answer);
533  g_free (frame);
534  if (answer_sz == -2)
535  {
536  g_message ("%s: Not possible to send the frame", __func__);
537  return NULL;
538  }
539 
540  if (answer && answer_sz > -1)
541  {
542  char *daddr;
543  struct ether_header *answer_aux;
544 
545  answer_aux = (struct ether_header *) answer;
546  daddr = g_strdup_printf (
547  "%02x:%02x:%02x:%02x:%02x:%02x", (u_int) answer_aux->ether_shost[0],
548  (u_int) answer_aux->ether_shost[1], (u_int) answer_aux->ether_shost[2],
549  (u_int) answer_aux->ether_shost[3], (u_int) answer_aux->ether_shost[4],
550  (u_int) answer_aux->ether_shost[5]);
551 
552  retc = alloc_typed_cell (CONST_DATA);
553  retc->x.str_val = daddr;
554  retc->size = strlen (daddr);
555  }
556  else
557  g_debug ("%s: No answer received.", __func__);
558 
559  return retc;
560 }
daddr
struct in_addr daddr
Definition: nasl_packet_forgery.c:1
nasl_forge_frame
tree_cell * nasl_forge_frame(lex_ctxt *lexic)
Forge a datalink layer frame.
Definition: nasl_frame_forgery.c:268
script_infos
Definition: scanneraux.h:29
prepare_sockaddr_ll
static void prepare_sockaddr_ll(struct sockaddr_ll *soc_addr_ll, int ifindex, const u_char *ether_dst_addr)
Prepare message header to be sent with sendmsg().
Definition: nasl_frame_forgery.c:85
CONST_DATA
@ CONST_DATA
Definition: nasl_tree.h:82
capture_next_frame
char * capture_next_frame(int bpf, int timeout, int *sz, int dl_layer_only)
Capture a link layer frame.
Definition: capture_packet.c:96
get_var_size_by_name
int get_var_size_by_name(lex_ctxt *, const char *)
Definition: nasl_var.c:1138
pseudo_eth_arp::__ar_sha
u_char __ar_sha[ETH_ALEN]
Definition: nasl_frame_forgery.c:43
plug_get_host_ip
struct in6_addr * plug_get_host_ip(struct script_infos *args)
Definition: plugutils.c:316
get_local_mac_address_from_ip
static int get_local_mac_address_from_ip(char *ip_address, u_char *mac)
Get the MAC address of host.
Definition: nasl_frame_forgery.c:389
pseudo_frame::payload
u_char * payload
Definition: nasl_frame_forgery.c:53
TC::str_val
char * str_val
Definition: nasl_tree.h:103
capture_packet.h
payload
u_char * payload
Definition: nasl_frame_forgery.c:1
pseudo_eth_arp::arp_header
struct arphdr arp_header
Definition: nasl_frame_forgery.c:42
nasl_send_arp_request
tree_cell * nasl_send_arp_request(lex_ctxt *lexic)
Send an arp request to an IP host.
Definition: nasl_frame_forgery.c:471
pseudo_eth_arp::__ar_sip
u_char __ar_sip[4]
Definition: nasl_frame_forgery.c:44
TC::x
union TC::@5 x
pseudo_eth_arp
Definition: nasl_frame_forgery.c:41
forge_frame
static int forge_frame(const u_char *ether_src_addr, const u_char *ether_dst_addr, int ether_proto, u_char *payload, int payload_sz, struct pseudo_frame **frame)
Forge a datalink layer frame.
Definition: nasl_frame_forgery.c:230
get_str_var_by_name
char * get_str_var_by_name(lex_ctxt *, const char *)
Definition: nasl_var.c:1118
bpf_close
void bpf_close(int bpf)
Definition: bpf_share.c:164
dump_frame
static void dump_frame(const u_char *frame, int frame_sz)
Dump a datalink layer frame.
Definition: nasl_frame_forgery.c:63
nasl_send_frame
tree_cell * nasl_send_frame(lex_ctxt *lexic)
Send a frame and listen to the answer.
Definition: nasl_frame_forgery.c:314
get_iface_from_ip
char * get_iface_from_ip(const char *local_ip)
Given an IP address, determines which interface belongs to.
Definition: pcap.c:1270
nasl_get_local_mac_address_from_ip
tree_cell * nasl_get_local_mac_address_from_ip(lex_ctxt *lexic)
Get the MAC address of host.
Definition: nasl_frame_forgery.c:438
init_capture_device
int init_capture_device(struct in_addr src, struct in_addr dest, char *filter)
Set up the pcap filter, and select the correct interface.
Definition: capture_packet.c:31
nasl_debug.h
prepare_message
static void prepare_message(u_char *msg, struct sockaddr_ll *soc_addr_ll, u_char *payload, int payload_sz)
Prepare message header to be sent with sendmsg().
Definition: nasl_frame_forgery.c:103
nasl_perror
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition: nasl_debug.c:111
get_iface_index
int get_iface_index(struct in6_addr *ipaddr, int *ifindex)
Get the interface index depending on the target's IP.
Definition: pcap.c:1324
TC::size
int size
Definition: nasl_tree.h:99
get_int_var_by_name
long int get_int_var_by_name(lex_ctxt *, const char *, int)
Definition: nasl_var.c:1104
nasl_dump_frame
tree_cell * nasl_dump_frame(lex_ctxt *lexic)
Dump a datalink layer frame.
Definition: nasl_frame_forgery.c:363
get_str_var_by_num
char * get_str_var_by_num(lex_ctxt *, int)
Definition: nasl_var.c:1111
pseudo_eth_arp::__ar_tha
u_char __ar_tha[ETH_ALEN]
Definition: nasl_frame_forgery.c:45
nasl_frame_forgery.h
Header file for module nasl_frame_forgery.
mac
gpg_err_code_t mac(const char *key, const size_t key_len, const char *data, const size_t data_len, const char *iv, const size_t iv_len, int algo, int flags, char **out, size_t *out_len)
Definition: nasl_crypt_helper.c:97
struct_lex_ctxt::script_infos
struct script_infos * script_infos
Definition: nasl_lex_ctxt.h:30
TC
Definition: nasl_tree.h:94
struct_lex_ctxt
Definition: nasl_lex_ctxt.h:23
send_frame
static int send_frame(const u_char *frame, int frame_sz, int use_pcap, int timeout, char *filter, struct in6_addr *ipaddr, u_char **answer)
Send a frame and listen to the answer.
Definition: nasl_frame_forgery.c:141
pseudo_eth_arp::__ar_tip
u_char __ar_tip[4]
Definition: nasl_frame_forgery.c:46
pseudo_frame::framehdr
struct ethhdr framehdr
Definition: nasl_frame_forgery.c:52
__attribute__
struct pseudo_eth_arp __attribute__((packed))
pseudo_frame
Definition: nasl_frame_forgery.c:51
alloc_typed_cell
tree_cell * alloc_typed_cell(int typ)
Definition: nasl_tree.c:28
routethrough
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:1060
init_v6_capture_device
int init_v6_capture_device(struct in6_addr src, struct in6_addr dest, char *filter)
Definition: capture_packet.c:215
pseudo_eth_arp::__zero_padding
u_char __zero_padding[18]
Definition: nasl_frame_forgery.c:47