static inline void
write_packet(HANDLE_OR_FILEPTR file,
	     u32 timestamp_hi,
	     u32 timestamp_lo,
	     u16 tag,
	     void *payload,
	     int length,
	     int format)
{
  u32 total_length;

  switch (format) {
  case PCAP_CLASSIC:
    write_classic_packet_header(file, timestamp_hi, timestamp_lo, length);
    checked_fwrite(payload, length, file);
    break;

  case PCAP_NG:
    total_length = write_ng_packet_header(file, timestamp_hi,
					  timestamp_lo, tag, length);
    checked_fwrite(payload, round_up_32_bit(length), file);
    checked_fwrite(&total_length, sizeof total_length, file);
    break;

  default:
    die("internal error");
  }
}
static void
write_pcap_ng_shb(HANDLE_OR_FILEPTR file)
{
  PCap_NG_shb shb;
  u32 btl;
  PCap_NG_option userappl = {4, 0};        // 4 = user application name
  PCap_NG_option end_of_options = {0, 0};
  userappl.length = strlen(hw_description);

  btl = sizeof(PCap_NG_shb)
    + sizeof(userappl) + round_up_32_bit(userappl.length)
    + sizeof(end_of_options)
    + sizeof(shb.block_total_length);

  shb.type                  = 0x0A0D0D0A;
  shb.block_total_length    = btl;
  shb.byte_order_magic      = 0x1A2B3C4D;
  shb.major_version         = 1;
  shb.minor_version         = 0;
  shb.section_length        = 0xffffffffFFFFFFFFULL; // "unknown"

  checked_fwrite((void*)&shb, sizeof shb, file);
  checked_fwrite((void*)&userappl, sizeof userappl, file);
  checked_fwrite((void*)hw_description, round_up_32_bit(userappl.length), file);
  checked_fwrite((void*)&end_of_options, sizeof end_of_options, file);
  checked_fwrite((void*)&btl, sizeof(btl), file);

  return;
}
static void
write_pcap_classic_header(HANDLE_OR_FILEPTR file)
{
	PCap_classic_global_header header;

	// The pcap file is native-endian, i.e. wireshark uses the magic value
	// to figure out if it was created on a little-endian or big-endian machine.
	/*
	TIMESTAMP PRECISION NOTICE:
	using 0xa1b2c3d4, the application informs readers that the timestamp precision is set to MICROseconds.
	using 0xa1b2c34d, the application informs readers that the timestamp precision is set to NANOseconds.
	if the magic number is changed, the code should be checked for other "TIMESTAMP PRECISION NOTICE"s to ensure their sanity.
	*/
	header.magic = 0xa1b2c3d4;
	header.major_version = 2;
	header.minor_version = 4;
	header.GMT_to_localtime = 0;
	header.sigfigs = 0;
	header.snaplen = 65535;
	header.network = LINK_TYPE_MTP2;

	checked_fwrite((void*)&header, sizeof header, file);

	return;
}
// Having both if_description and if_name causes Wireshark 1.10.3 to
// display only if_description. So we only have if_name.
static void
write_pcap_idbs(HANDLE_OR_FILEPTR file, Channel_t *c, int n)
{
	int x;
	PCap_NG_option end_of_options = { 0, 0 };

	for (x = 0; x < n; x++) {
		PCap_NG_idb idb;
		PCap_NG_option if_name;
		char idb_if_name[MAX_IF_NAME];
		PCap_NG_option if_tsresol;
		/*
		TIMESTAMP PRECISION NOTICE:
		Precision is set to MILLIseconds (10^-3 seconds)
		*/
		char tsresol[4] = { 3, 0, 0, 0 }; // 10^-3 resolution, three padding bytes

		u32 block_total_length;

		if_name.code = 2;    // if_name
		if_name.length = snprintf(idb_if_name, MAX_IF_NAME, "%s:%d",
			c[x].span, c[x].timeslots[0]);
		if (if_name.length < 0 || if_name.length >= MAX_IF_NAME)
			die("interface name is too long");

		block_total_length = sizeof(idb)
			+ sizeof(PCap_NG_option) + round_up_32_bit(if_name.length)
			+ sizeof(PCap_NG_option) + sizeof(tsresol)
			+ sizeof(PCap_NG_option)
			+ sizeof(block_total_length);

		idb.type = 1;
		idb.block_total_length = block_total_length;
		idb.link_type = LINK_TYPE_MTP2;
		idb.reserved = 0;
		idb.snaplen = 279;

		if_tsresol.code = 9; // tsresol
		if_tsresol.length = 1;

		checked_fwrite((void*)&idb, sizeof(idb), file);

		checked_fwrite((void*)&if_name, sizeof(if_name), file);
		checked_fwrite((void*)&idb_if_name, round_up_32_bit(if_name.length), file);

		checked_fwrite((void*)&if_tsresol, sizeof(if_tsresol), file);
		checked_fwrite((void*)&tsresol, sizeof(tsresol), file);

		checked_fwrite((void*)&end_of_options, sizeof(end_of_options), file);

		checked_fwrite((void*)&block_total_length, sizeof block_total_length, file);
	}
}
static void
write_pcap_classic_header(HANDLE_OR_FILEPTR file)
{
  PCap_classic_global_header header;

  // The pcap file is native-endian, i.e. wireshark uses the magic value
  // to figure out if it was created on a little-endian or big-endian machine.
  header.magic = 0xa1b2c3d4;
  header.major_version = 2;
  header.minor_version = 4;
  header.GMT_to_localtime = 0;
  header.sigfigs = 0;
  header.snaplen = 65535;
  header.network = LINK_TYPE_MTP2;

  checked_fwrite((void*)&header, sizeof header, file);

  return;
}
static u32
write_ng_packet_header(HANDLE_OR_FILEPTR file,
		       u32 timestamp_hi,
		       u32 timestamp_lo,
		       u16 tag,
		       int length)
{
  PCap_NG_epb epb;

  epb.type = 6;
  epb.block_total_length = sizeof(epb)
    + round_up_32_bit(length)
    + sizeof(epb.block_total_length);
  epb.interface_id = tag;
  epb.timestamp_hi = timestamp_hi;
  epb.timestamp_lo = timestamp_lo;
  epb.captured_len = length;
  epb.packet_len = length;

  checked_fwrite(&epb, sizeof epb, file);

  return epb.block_total_length;
}
Example #7
0
static void
do_fprintf (struct format_val *dest,
            struct segment *segment,
            const char *pathname,
            const struct stat *stat_buf)
{
  char hbuf[LONGEST_HUMAN_READABLE + 1];
  const char *cp;

  switch (segment->segkind)
    {
    case KIND_PLAIN:    /* Plain text string (no % conversion). */
      /* trusted */
      checked_fwrite(segment->text, 1, segment->text_len, dest);
      break;

    case KIND_STOP:             /* Terminate argument and flush output. */
      /* trusted */
      checked_fwrite (segment->text, 1, segment->text_len, dest);
      checked_fflush (dest);
      break;

    case KIND_FORMAT:
      switch (segment->format_char[0])
        {
        case 'a':               /* atime in `ctime' format. */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text, ctime_format (get_stat_atime (stat_buf)));
          break;
        case 'b':               /* size in 512-byte blocks */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text,
                           human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
                                           hbuf, human_ceiling,
                                           ST_NBLOCKSIZE, 512));
          break;
        case 'c':               /* ctime in `ctime' format */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text, ctime_format (get_stat_ctime (stat_buf)));
          break;
        case 'd':               /* depth in search tree */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text, state.curdepth);
          break;
        case 'D':               /* Device on which file exists (stat.st_dev) */
          /* trusted */
          checked_fprintf (dest, segment->text,
                           human_readable ((uintmax_t) stat_buf->st_dev, hbuf,
                                           human_ceiling, 1, 1));
          break;
        case 'f':               /* base name of path */
          /* sanitised */
          {
            char *base = base_name (pathname);
            checked_print_quoted (dest, segment->text, base);
            free (base);
          }
          break;
        case 'F':               /* file system type */
          /* trusted */
          checked_print_quoted (dest, segment->text, filesystem_type (stat_buf, pathname));
          break;
        case 'g':               /* group name */
          /* trusted */
          /* (well, the actual group is selected by the user but
           * its name was selected by the system administrator)
           */
          {
            struct group *g;

            g = getgrgid (stat_buf->st_gid);
            if (g)
              {
                segment->text[segment->text_len] = 's';
                checked_fprintf (dest, segment->text, g->gr_name);
                break;
              }
            else
              {
                /* Do nothing. */
                /*FALLTHROUGH*/
              }
          }
          /*FALLTHROUGH*/ /*...sometimes, so 'G' case.*/

        case 'G':               /* GID number */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text,
                           human_readable ((uintmax_t) stat_buf->st_gid, hbuf,
                                           human_ceiling, 1, 1));
          break;
        case 'h':               /* leading directories part of path */
          /* sanitised */
          {
            cp = strrchr (pathname, '/');
            if (cp == NULL)     /* No leading directories. */
              {
                /* If there is no slash in the pathname, we still
                 * print the string because it contains characters
                 * other than just '%s'.  The %h expands to ".".
                 */
                checked_print_quoted (dest, segment->text, ".");
              }
            else
              {
                char *s = strdup (pathname);
                s[cp - pathname] = 0;
                checked_print_quoted (dest, segment->text, s);
                free (s);
              }
          }
          break;

        case 'H':               /* ARGV element file was found under */
          /* trusted */
          {
            char *s = xmalloc (state.starting_path_length+1);
            memcpy (s, pathname, state.starting_path_length);
            s[state.starting_path_length] = 0;
            checked_fprintf (dest, segment->text, s);
            free (s);
          }
          break;

        case 'i':               /* inode number */
          /* UNTRUSTED, but not exploitable I think */
          /* POSIX does not guarantee that ino_t is unsigned or even
           * integral (except as an XSI extension), but we'll work on
           * fixing that if we ever get a report of a system where
           * ino_t is indeed a signed integral type or a non-integral
           * arithmetic type. */
          checked_fprintf (dest, segment->text,
                           human_readable ((uintmax_t) stat_buf->st_ino, hbuf,
                                           human_ceiling,
                                           1, 1));
          break;
        case 'k':               /* size in 1K blocks */
          /* UNTRUSTED, but not exploitable I think */
          checked_fprintf (dest, segment->text,
                           human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
                                           hbuf, human_ceiling,
                                           ST_NBLOCKSIZE, 1024));
          break;
        case 'l':               /* object of symlink */
          /* sanitised */
#ifdef S_ISLNK
          {
            char *linkname = 0;

            if (S_ISLNK (stat_buf->st_mode))
              {
                linkname = areadlinkat (state.cwd_dir_fd, state.rel_pathname);
                if (linkname == NULL)
                  {
                    nonfatal_target_file_error (errno, pathname);
                    state.exit_status = 1;
                  }
              }
            if (linkname)
              {
                checked_print_quoted (dest, segment->text, linkname);
              }
            else
              {
                /* We still need to honour the field width etc., so this is
                 * not a no-op.
                 */
                checked_print_quoted (dest, segment->text, "");
              }
            free (linkname);
          }
#endif                          /* S_ISLNK */
          break;

        case 'M':               /* mode as 10 chars (eg., "-rwxr-x--x" */
          /* UNTRUSTED, probably unexploitable */
          {
            char modestring[16] ;
            filemodestring (stat_buf, modestring);
            modestring[10] = '\0';
            checked_fprintf (dest, segment->text, modestring);
          }
          break;

        case 'm':               /* mode as octal number (perms only) */
          /* UNTRUSTED, probably unexploitable */
          {
            /* Output the mode portably using the traditional numbers,
               even if the host unwisely uses some other numbering
               scheme.  But help the compiler in the common case where
               the host uses the traditional numbering scheme.  */
            mode_t m = stat_buf->st_mode;
            bool traditional_numbering_scheme =
              (S_ISUID == 04000 && S_ISGID == 02000 && S_ISVTX == 01000
               && S_IRUSR == 00400 && S_IWUSR == 00200 && S_IXUSR == 00100
               && S_IRGRP == 00040 && S_IWGRP == 00020 && S_IXGRP == 00010
               && S_IROTH == 00004 && S_IWOTH == 00002 && S_IXOTH == 00001);
            checked_fprintf (dest, segment->text,
                     (traditional_numbering_scheme
                      ? m & MODE_ALL
                      : ((m & S_ISUID ? 04000 : 0)
                         | (m & S_ISGID ? 02000 : 0)
                         | (m & S_ISVTX ? 01000 : 0)
                         | (m & S_IRUSR ? 00400 : 0)
                         | (m & S_IWUSR ? 00200 : 0)
                         | (m & S_IXUSR ? 00100 : 0)
                         | (m & S_IRGRP ? 00040 : 0)
                         | (m & S_IWGRP ? 00020 : 0)
                         | (m & S_IXGRP ? 00010 : 0)
                         | (m & S_IROTH ? 00004 : 0)
                         | (m & S_IWOTH ? 00002 : 0)
                         | (m & S_IXOTH ? 00001 : 0))));
          }
          break;

        case 'n':               /* number of links */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text,
                   human_readable ((uintmax_t) stat_buf->st_nlink,
                                   hbuf,
                                   human_ceiling,
                                   1, 1));
          break;

        case 'p':               /* pathname */
          /* sanitised */
          checked_print_quoted (dest, segment->text, pathname);
          break;

        case 'P':               /* pathname with ARGV element stripped */
          /* sanitised */
          if (state.curdepth > 0)
            {
              cp = pathname + state.starting_path_length;
              if (*cp == '/')
                /* Move past the slash between the ARGV element
                   and the rest of the pathname.  But if the ARGV element
                   ends in a slash, we didn't add another, so we've
                   already skipped past it.  */
                cp++;
            }
          else
            {
              cp = "";
            }
          checked_print_quoted (dest, segment->text, cp);
          break;

        case 's':               /* size in bytes */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text,
                   human_readable ((uintmax_t) stat_buf->st_size,
                                   hbuf, human_ceiling, 1, 1));
          break;

        case 'S':               /* sparseness */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text, file_sparseness (stat_buf));
          break;

        case 't':               /* mtime in `ctime' format */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text,
                           ctime_format (get_stat_mtime (stat_buf)));
          break;

        case 'u':               /* user name */
          /* trusted */
          /* (well, the actual user is selected by the user on systems
           * where chown is not restricted, but the user name was
           * selected by the system administrator)
           */
          {
            struct passwd *p;

            p = getpwuid (stat_buf->st_uid);
            if (p)
              {
                segment->text[segment->text_len] = 's';
                checked_fprintf (dest, segment->text, p->pw_name);
                break;
              }
            /* else fallthru */
          }
          /* FALLTHROUGH*/ /* .. to case U */

        case 'U':               /* UID number */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text,
                           human_readable ((uintmax_t) stat_buf->st_uid, hbuf,
                                           human_ceiling, 1, 1));
          break;

          /* %Y: type of file system entry like `ls -l`:
           *     (d,-,l,s,p,b,c,n) n=nonexistent (symlink)
           */
        case 'Y':               /* in case of symlink */
          /* trusted */
          {
#ifdef S_ISLNK
            if (S_ISLNK (stat_buf->st_mode))
              {
                struct stat sbuf;
                /* If we would normally follow links, do not do so.
                 * If we would normally not follow links, do so.
                 */
                if ((following_links () ? optionp_stat : optionl_stat)
                    (state.rel_pathname, &sbuf) != 0)
                  {
                    if ( errno == ENOENT )
                      {
                        checked_fprintf (dest, segment->text, "N");
                        break;
                      }
                    else if ( errno == ELOOP )
                      {
                        checked_fprintf (dest, segment->text, "L");
                        break;
                      }
                    else
                      {
                        checked_fprintf (dest, segment->text, "?");
                        error (0, errno, "%s",
                               safely_quote_err_filename (0, pathname));
                        /* exit_status = 1;
                           return ; */
                        break;
                      }
                  }
                checked_fprintf (dest, segment->text,
                                 mode_to_filetype (sbuf.st_mode & S_IFMT));
              }
#endif /* S_ISLNK */
            else
              {
                checked_fprintf (dest, segment->text,
                                 mode_to_filetype (stat_buf->st_mode & S_IFMT));
              }
          }
          break;

        case 'y':
          /* trusted */
          {
            checked_fprintf (dest, segment->text,
                             mode_to_filetype (stat_buf->st_mode & S_IFMT));
          }
          break;

        case 'Z':               /* SELinux security context */
          {
            security_context_t scontext;
            int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname,
                                              &scontext);
            if (rv < 0)
              {
                /* If getfilecon fails, there will in the general case
                   still be some text to print.   We just make %Z expand
                   to an empty string. */
                checked_fprintf (dest, segment->text, "");

                error (0, errno, _("getfilecon failed: %s"),
                    safely_quote_err_filename (0, pathname));
                state.exit_status = 1;
              }
            else
              {
                checked_fprintf (dest, segment->text, scontext);
                freecon (scontext);
              }
          }
          break;

        case 0:
        case '%':
          checked_fprintf (dest, segment->text);
          break;
        }
      /* end of KIND_FORMAT case */
      break;
    }
}