Index: config.guess =================================================================== --- config.guess (revision 33624) +++ config.guess (working copy) @@ -1,10 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. -timestamp='2006-07-02' +timestamp='2009-06-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -56,8 +56,8 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -139,16 +139,6 @@ UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "${UNAME_MACHINE}" in - i?86) - test -z "$VENDOR" && VENDOR=pc - ;; - *) - test -z "$VENDOR" && VENDOR=unknown - ;; -esac -test -f /etc/SuSE-release -o -f /.buildenv && VENDOR=suse - # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in @@ -171,6 +161,7 @@ arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched @@ -179,7 +170,7 @@ arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -333,14 +324,30 @@ case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize @@ -541,7 +548,7 @@ echo rs6000-ibm-aix3.2 fi exit ;; - *:AIX:*:[45]) + *:AIX:*:[456]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 @@ -649,7 +656,7 @@ # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep __LP64__ >/dev/null + grep -q __LP64__ then HP_ARCH="hppa2.0w" else @@ -790,7 +797,7 @@ i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; - i*:MINGW*:*) + *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) @@ -800,15 +807,24 @@ i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - x86:Interix*:[3456]*) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - EM64T:Interix*:[3456]*) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd | genuineintel) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we @@ -839,7 +855,14 @@ echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu @@ -851,28 +874,28 @@ echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) - echo frv-${VENDOR}-linux-gnu + echo frv-unknown-linux-gnu exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - mips:Linux:*:*) + mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU - #undef mips - #undef mipsel + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel + CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips + CPU=${UNAME_MACHINE} #else CPU= #endif @@ -883,39 +906,16 @@ s: ::g p }'`" - test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux-gnu"; exit; } + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-${VENDOR}-linux-gnu"; exit; } - ;; or32:Linux:*:*) - echo or32-${VENDOR}-linux-gnu + echo or32-unknown-linux-gnu exit ;; ppc:Linux:*:*) - echo powerpc-${VENDOR}-linux-gnu + echo powerpc-unknown-linux-gnu exit ;; ppc64:Linux:*:*) - echo powerpc64-${VENDOR}-linux-gnu + echo powerpc64-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -927,39 +927,45 @@ EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu${LIBC} + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-${VENDOR}-linux-gnu ;; - PA8*) echo hppa2.0-${VENDOR}-linux-gnu ;; - *) echo hppa-${VENDOR}-linux-gnu ;; + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; esac exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-${VENDOR}-linux-gnu + echo hppa64-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) - echo x86_64-${VENDOR}-linux-gnu + echo x86_64-unknown-linux-gnu exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent @@ -973,19 +979,8 @@ p'` case "$ld_supported_targets" in elf32-i386) - TENTATIVE="${UNAME_MACHINE}-${VENDOR}-linux-gnu" + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-${VENDOR}-linux-gnuaout" - exit ;; - coff-i386) - echo "${UNAME_MACHINE}-${VENDOR}-linux-gnucoff" - exit ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-${VENDOR}-linux-gnuoldld" - exit ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build @@ -1018,7 +1013,7 @@ p }'`" test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-${VENDOR}-linux-${LIBC}" + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit } test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } @@ -1051,7 +1046,7 @@ i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) @@ -1095,8 +1090,11 @@ pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 @@ -1134,6 +1132,16 @@ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; @@ -1146,7 +1154,7 @@ rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) @@ -1209,6 +1217,9 @@ BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; @@ -1218,6 +1229,15 @@ SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; @@ -1308,6 +1328,9 @@ i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1468,9 +1491,9 @@ the operating system you are using. It is advised that you download the most up to date version of the config scripts from - http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD and - http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD If the version you run ($0) is already up to date, please send the following data and any information you think might be Index: INSTALL =================================================================== --- INSTALL (revision 33624) +++ INSTALL (working copy) @@ -1,235 +1,365 @@ -$Id$ +Installation Instructions +************************* -NOTE: this document applies to the Wireshark source releases and -buildbot source tarballs. It does not apply to source code checked -out directly from Subversion, as files such as the configuration -script are not checked into Subversion, but need to be generated -from the autoconf and automake files. -See http://wiki.wireshark.org/Development if you would like to build -the source code checked out directly from Subversion. +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. -Installation -============ + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. -These are installation instructions for Unix and Unix-like systems -that can run the "configure" script in this same directory. These -are not the installation instructions for Windows systems; see -README.windows for those instructions. +Basic Installation +================== -0. This is software. Beware. + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. -1. If you wish to build Wireshark, make sure you have GTK+ and GLib - installed. Try running 'pkg-config glib-2.0 --modversion' to see if - you have GLib 2.x installed and, if that fails, try running - 'glib-config --version' to see if you have GLib 1.2[.x] installed. - Then try running 'pkg-config gtk+-2.0 --modversion' to see if you - have GTK+ 2.x installed and, if that fails, try running - 'gtk-config --version' to see if you have GTK+ 1.2[.x] installed. - Wireshark needs versions 1.2.0 or above of both these packages. - If you need to install or re-install GTK+ or GLIB, you can find - the packages at: + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). - http://www.gtk.org + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. - If you installed GTK+ from a binary package, you may have to - install a "development" package; there may be separate "user's" - and "developer's" packages, with the former not including - header files and the like. For example, Red Hat users will - need to install a "gtk-devel" .rpm. + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. - Note also that Wireshark configuration defaults to using GTK+ and - GLib 2.x; you need to configure with --disable-gtk2 to use GTK+ - 1.2[.x]. + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. - Please also note that GTK+ 1.2[.x] is only supported up to - Wireshark 1.0.x. From Wireshark 1.1.x onwards only GTK+ 2.x - is supported. + The simplest way to compile this package is: -2. If you wish to build TShark, the line-mode version of Wireshark, - make sure you have GLIB installed. See note #1 above for instructions - on checking if you have GLIB installed. You can download GLIB from - the same site as GTK. + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. -3. If you want to capture packets, make sure you have libpcap - installed. The latest "official" version can be found at + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. - http://www.tcpdump.org . + 2. Type `make' to compile the package. - If you've downloaded the 0.5.2 version, make sure you install - the headers ('make install-incl') when you install the library. - The CVS snapshots will install the headers if you do 'make - install', and have no 'install-incl' target. + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. - If you installed libpcap from a binary package, you may have to - install a "development" package; for example, there's - apparently a "libpcap0" Debian package, but it just includes a - shared library, a copyright notice, changelog files, and a - README file - you also need to install a "libpcap-dev" package - to get header files, a non-shared library, and the man page. - Similarly, Red Hat 5.x users will need to install a "libpcap-devel" - .rpm to go along with the "libpcap" .rpm. + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. -4. Building Wireshark requires Perl (specifically the pod2man program) - so that the documentation can be built. + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. -5. Run './configure' in the Wireshark distribution directory. - Running './configure --help' displays a complete list of options. - The file 'INSTALL.configure' contains general instructions for - using 'configure' and 'make'. Some of the Wireshark non-generic - configure options are as follows: + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. - --sysconfdir=DIR - Wireshark installs a support file (manuf) in ${PREFIX}/etc by - default, where ${PREFIX} comes from --prefix=DIR. If you do not - specify any --prefix option, ${PREFIX} is "/usr/local". - You can change the location of the manuf file with the --sysconfdir - option. + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. - --disable-usr-local - By default 'configure' will look in /usr/local/{include,lib} for - additional header files and libraries. Using this switch keeps - 'configure' from looking there + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. - --disable-wireshark - By default, if 'configure' finds the GTK+ libraries, the Makefile - builds Wireshark, the GUI packet analyzer. You can disable the - build of the GUI version of Wireshark with this switch. +Compilers and Options +===================== - --disable-gtk2 - Build Glib/Gtk+ 1.2[.x]-based wireshark. - Note: not supported from Wireshark 1.1.x onwards + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. - --disable-tshark - By default the line-mode packet analyzer, TShark, is built. - Use this switch to avoid building it. + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: - --disable-editcap - By default the capture-file editing program is built. - Use this switch to avoid building it. + ./configure CC=c99 CFLAGS=-g LIBS=-lposix - --disable-capinfos - By default the capture-file statistics reporting pogram - is built. Use this switch to avoid building it. + *Note Defining Variables::, for more details. - --disable-mergecap - By default the capture-file merging program is built. - Use this switch to avoid building it. +Compiling For Multiple Architectures +==================================== - --disable-text2pcap - By default the hex-dump-to-capture file conversion program - is built. Use this switch to avoid building it. + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. - --disable-idl2wrs - By default the IDL-to-wireshark-dissector-source-code converter - is built. Use this switch to avoid building it. + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. - --disable-dftest - By default the display-filter-compiler test program is built. - Use this switch to avoid building it. + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: - --disable-randpkt - By default the program which creates random packet-capture files - is built. Use this switch to avoid building it. + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" - --disable-dumpcap - By default the network traffic capture program is built. - Use this switch to avoid building it. + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. - --disable-rawshark - By default the program used to dump and analyze raw libpcap data - is built. Use this switch to avoid building it. +Installation Names +================== - --disable-ipv6 - If 'configure' finds support for IPv6 name resolution on - your system, the packet analyzers will make use of it. - To avoid using IPv6 name resolution if you have the support for it, - use this switch. + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. - --enable-setuid-install - Wireshark and TShark rely on dumpcap for packet capture. Setting this - flag installs dumpcap with setuid root permissions, which lets any user - on the system capture live traffic. If this is not desired, you can - restrict dumpcap's permissions so that only a single user or group can - run it. This can be used in conjunction with --with-libcap described - below. + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. - Running Wireshark or TShark as root is not recommended. + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. - --without-libcap - By default, if 'configure' finds libcap (the POSIX capabilities - library) dumpcap will be built so that if it is installed setuid - root, it will attempt to retain CAP_NET_RAW and CAP_NET_ADMIN - before dropping root privileges. Use this option to disable this - behavior. + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. - --with-libcap=DIR - Use this option to tell 'configure' where libcap is installed, - if it is installed in a non-standard location. Note that libcap - (the POSIX capabilities library, sans "p") and libpcap (the - packet capture library, avec "p") are two very different things. + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. - --without-pcap - If you choose to build a packet analyzer that can analyze - capture files but cannot capture packets on its own, but you - *do* have libpcap installed, or if you are trying to build - Wireshark on a system that doesn't have libpcap installed (in - which case you have no choice but to build a version that can - analyze capture files but cannot capture packets on its own), - use --without-pcap to avoid using libpcap. + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. - --with-pcap=DIR - Use this to tell Wireshark where you have libpcap installed, if - it is installed in a non-standard location. +Optional Features +================= - --without-zlib - By default, if 'configure' finds zlib (a.k.a, libz), the - wiretap library will be built so that it can read compressed - capture files. If you have zlib but do not wish to build - it into the wiretap library, used by Wireshark, TShark, and - the capture-file utilities that come in this package, use - this switch. + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - --with-zlib=DIR - Use this to tell Wireshark where you have zlib installed, if it - is installed in a non-standard location. + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. - --without-plugins - By default, if your system can support run-time loadable modules, - the packet analyzers are build with support for plugins. - Use this switch to build packet analyzers without plugin support. + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. - --with-plugins=DIR - By default, plugins are installed in - ${LIBDIR}/wireshark/plugins/${VERSION} + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. - ${LIBDIR} can be set with --libdir, or defaults to ${EPREFIX/lib} - ${EPREFIX} can be set with --exec-prefix, or defaults to ${PREFIX} - ${VERSION} is the Wireshark version. +Particular systems +================== - Use this switch to change the location where plugins - are installed. + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: -6. After running './configure', you will see a summary of some - of the options you chose. Ensure that the summary reflects - what you want. If it doesn't, re-run './configure' with new options. + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" -7. Run 'make'. Hopefully, you won't run into any problems. +and if that doesn't work, install pre-built binaries of GCC for HP-UX. -8. Run './wireshark' or './tshark' or ./dumpcap, and make sure things are - working. You must have root privileges in order to capture live data. + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try -9. Run 'make install'. If you're running a system that supports - the Apt, RPM, or System V Release 4 packaging systems, you can - run one of + ./configure CC="cc" - make debian-package # Builds a binary package using dpkg - make rpm-package # Builds a binary package using rpm - make srpm-package # Builds a source package using rpm - make svr4-package # Builds a source package using pkgmk - make solaris-package # Same as "make svr4-package" +and if that doesn't work, try - to make an installable package for your system. + ./configure CC="cc -nodtk" -If you have trouble with the build or installation process, you can -find assistance on the wireshark-users and wireshark-dev mailing lists. -See http://www.wireshark.org/lists/ for details. + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + Index: epan/dissectors/packet-ssl-utils.c =================================================================== --- epan/dissectors/packet-ssl-utils.c (revision 33624) +++ epan/dissectors/packet-ssl-utils.c (working copy) @@ -1297,6 +1297,7 @@ {47,KEX_RSA,SIG_RSA,ENC_AES,16,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC}, {51,KEX_DH, SIG_RSA,ENC_AES,16,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC}, {53,KEX_RSA,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC}, + {57,KEX_DH,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC}, /* for tor */ {96,KEX_RSA,SIG_RSA,ENC_RC4,1,128,56,DIG_MD5,16,1, SSL_CIPHER_MODE_STREAM}, {97,KEX_RSA,SIG_RSA,ENC_RC2,1,128,56,DIG_MD5,16,1, SSL_CIPHER_MODE_STREAM}, {98,KEX_RSA,SIG_RSA,ENC_DES,8,64,64,DIG_SHA,20,1, SSL_CIPHER_MODE_STREAM}, @@ -1648,11 +1649,13 @@ ssl_print_string("pre master secret",&ssl_session->pre_master_secret); ssl_print_string("client random",&ssl_session->client_random); ssl_print_string("server random",&ssl_session->server_random); - if (PRF(ssl_session,&ssl_session->pre_master_secret,"master secret", - &ssl_session->client_random, - &ssl_session->server_random, &ssl_session->master_secret)) { - ssl_debug_printf("ssl_generate_keyring_material can't generate master_secret\n"); - return -1; + if (!ssl_session->master_key_session) { + if (PRF(ssl_session,&ssl_session->pre_master_secret,"master secret", + &ssl_session->client_random, + &ssl_session->server_random, &ssl_session->master_secret)) { + ssl_debug_printf("ssl_generate_keyring_material can't generate master_secret\n"); + return -1; + } } ssl_print_string("master secret",&ssl_session->master_secret); @@ -2179,26 +2182,27 @@ worklen, ssl->version_netorder, ct, decoder->seq); if(ssl->version_netorder==SSLV3_VERSION){ if(ssl3_check_mac(decoder,ct,out_str->data,worklen,mac) < 0) { - ssl_debug_printf("ssl_decrypt_record: mac failed\n"); + ssl_debug_printf("sslv3_decrypt_record: mac failed\n"); return -1; } + ssl_debug_printf("sslv3_decrypt_record: mac ok\n"); } else if(ssl->version_netorder==TLSV1_VERSION || ssl->version_netorder==TLSV1DOT1_VERSION){ if(tls_check_mac(decoder,ct,ssl->version_netorder,out_str->data,worklen,mac)< 0) { - ssl_debug_printf("ssl_decrypt_record: mac failed\n"); + ssl_debug_printf("tlsv1_decrypt_record: mac failed\n"); return -1; } + ssl_debug_printf("tlsv1_decrypt_record: mac ok\n"); } else if(ssl->version_netorder==DTLSV1DOT0_VERSION || ssl->version_netorder==DTLSV1DOT0_VERSION_NOT){ /* following the openssl dtls errors the right test is: if(dtls_check_mac(decoder,ct,ssl->version_netorder,out_str->data,worklen,mac)< 0) { */ if(tls_check_mac(decoder,ct,TLSV1_VERSION,out_str->data,worklen,mac)< 0) { - ssl_debug_printf("ssl_decrypt_record: mac failed\n"); + ssl_debug_printf("dtls_decrypt_record: mac failed\n"); return -1; } } - ssl_debug_printf("ssl_decrypt_record: mac ok\n"); *outl = worklen; if (decoder->compression > 0) { @@ -2323,6 +2327,28 @@ } Ssl_private_key_t * +ssl_load_master_key(gchar *master_key) +{ + GByteArray *bytes = NULL; + gboolean res; + Ssl_private_key_t *private_key = g_malloc(sizeof(Ssl_private_key_t)); + private_key->x509_cert = 0; + private_key->x509_pkey = 0; + private_key->sexp_pkey = 0; + private_key->_master_secret = 0; + private_key->_second_master_secret = 0; + bytes = g_byte_array_new(); + res = hex_str_to_bytes(master_key, bytes,FALSE); + + if (res && bytes->len == 48) { + private_key->_master_secret=g_malloc(bytes->len); + memcpy(private_key->_master_secret,bytes->data,bytes->len); + } + g_byte_array_free(bytes, TRUE); + return private_key; +} + +Ssl_private_key_t * ssl_load_key(FILE* fp) { /* gnutls make our work much harded, since we have to work internally with @@ -2623,7 +2649,15 @@ if (!private_key) { ssl_debug_printf("ssl_find_private_key can't find any private key!\n"); } else { - ssl_session->private_key = private_key->sexp_pkey; + if (private_key->_master_secret) { + ssl_debug_printf("dissect_ssl found master_secret!\n"); + ssl_data_set(&ssl_session->primary_master_secret, private_key->_master_secret, 48); + if (private_key->_second_master_secret) + ssl_data_set(&ssl_session->secondary_master_secret, private_key->_second_master_secret, 48); + ssl_session->master_key_session=1; + }else{ + ssl_session->private_key = private_key->sexp_pkey; + } } return 0; @@ -2730,10 +2764,14 @@ (void *)ssl_session, sizeof(SslDecryptSession)); ssl_session->master_secret.data = ssl_session->_master_secret; + ssl_session->primary_master_secret.data = ssl_session->_primary_master_secret; + ssl_session->secondary_master_secret.data = ssl_session->_secondary_master_secret; ssl_session->session_id.data = ssl_session->_session_id; ssl_session->client_random.data = ssl_session->_client_random; ssl_session->server_random.data = ssl_session->_server_random; ssl_session->master_secret.data_len = 48; + ssl_session->primary_master_secret.data_len = 48; + ssl_session->secondary_master_secret.data_len = 48; ssl_session->server_data_for_iv.data_len = 0; ssl_session->server_data_for_iv.data = ssl_session->_server_data_for_iv; ssl_session->client_data_for_iv.data_len = 0; @@ -3050,13 +3088,14 @@ SslService* service; Ssl_private_key_t * private_key, *tmp_private_key; FILE* fp; + const char log_line_preamble[45] = "TLS master key (address,port,protocol,key): \0"; start = g_strdup(keys_list); tmp = start; ssl_debug_printf("ssl_init keys string:\n%s\n", start); do { int read_index, write_index; - gchar* addr, *port, *protocol, *filename, *cert_passwd; + gchar* addr, *rawaddr, *port, *protocol, *filename, *cert_passwd; addr = start; /* split ip/file couple with ';' separator*/ @@ -3066,6 +3105,16 @@ start = end+1; } + /* Remove all the leading material from addr provided by a Tor log line. + This is typically of the form: + Jan 26 21:24:43.663 [info] crypto_dump_crypto_key(): \ + TLS master key (address,port,protocol,key): */ + + if ((rawaddr = strstr(addr,log_line_preamble)) != NULL) { + rawaddr += sizeof(log_line_preamble); + addr = rawaddr; + } + /* skip comments (in file) */ if (addr[0] == '#') continue; @@ -3111,16 +3160,17 @@ service->addr.len = 4; service->addr.data = ip = ((guchar*)service) + sizeof(SslService); - /* remove all spaces in addr */ + /* remove all spaces and quotation marks in addr */ read_index = 0; write_index = 0; while(addr[read_index]) { - if (addr[read_index] != ' ') { - addr[write_index] = addr[read_index]; - write_index++; - } - read_index++; + if (addr[read_index] != ' ' && + addr[read_index] != '"') { + addr[write_index] = addr[read_index]; + write_index++; + } + read_index++; } addr[write_index] = 0; @@ -3141,34 +3191,50 @@ ssl_debug_printf("ssl_init addr '%hhu.%hhu.%hhu.%hhu' port '%d' filename '%s' password(only for p12 file) '%s'\n", ip[0], ip[1], ip[2], ip[3], service->port, filename, cert_passwd); - /* try to load pen or p12 file*/ - fp = ws_fopen(filename, "rb"); - if (!fp) { + if (strlen(filename)==96) { + ssl_debug_printf("using master secret"); + private_key = ssl_load_master_key(filename); + /* !!! */ + if (!private_key) { + fprintf(stderr,"can't load private key from %s\n", + filename); + continue; + } + }else{ + /* try to load pen or p12 file*/ + fp = ws_fopen(filename, "rb"); + if (!fp) { fprintf(stderr, "can't open file %s \n",filename); continue; - } + } - if (!cert_passwd) { + if (!cert_passwd) { private_key = ssl_load_key(fp); - } - else - { + } + else + { private_key = ssl_load_pkcs12(fp,cert_passwd); - } - /* !!! */ - if (!private_key) { + } + /* !!! */ + if (!private_key) { fprintf(stderr,"can't load private key from %s\n", - filename); + filename); continue; + } + + fclose(fp); } - - fclose(fp); - ssl_debug_printf("ssl_init private key file %s successfully loaded\n",filename); /* if item exists, remove first */ tmp_private_key = g_hash_table_lookup(key_hash, service); - if (tmp_private_key) { + if ((tmp_private_key) && (strlen(filename)==96)) { + /* if we are loading master secrets and already have this item, then + this must be a renegotiate master secret */ + tmp_private_key->_second_master_secret=g_malloc(48); + memcpy(tmp_private_key->_second_master_secret,private_key->_master_secret,48); + continue; + }else if (tmp_private_key){ g_hash_table_remove(key_hash, service); ssl_free_key(tmp_private_key); } Index: epan/dissectors/packet-ssl-utils.h =================================================================== --- epan/dissectors/packet-ssl-utils.h (revision 33624) +++ epan/dissectors/packet-ssl-utils.h (working copy) @@ -285,6 +285,8 @@ typedef struct _SslDecryptSession { guchar _master_secret[48]; + guchar _primary_master_secret[48]; + guchar _secondary_master_secret[48]; guchar _session_id[256]; guchar _client_random[32]; guchar _server_random[32]; @@ -292,6 +294,8 @@ StringInfo server_random; StringInfo client_random; StringInfo master_secret; + StringInfo primary_master_secret; + StringInfo secondary_master_secret; /* the data store for this StringInfo must be allocated explicitly with a capture lifetime scope */ StringInfo pre_master_secret; guchar _server_data_for_iv[24]; @@ -317,6 +321,8 @@ port_type srv_ptype; guint srv_port; + guint16 master_key_session; + } SslDecryptSession; typedef struct _SslAssociation { @@ -338,6 +344,8 @@ gnutls_x509_privkey_t x509_pkey; #endif SSL_PRIVATE_KEY *sexp_pkey; + gchar *_master_secret; + gchar *_second_master_secret; } Ssl_private_key_t; /** Initialize decryption engine/ssl layer. To be called once per execution */ Index: epan/dissectors/Makefile.common =================================================================== --- epan/dissectors/Makefile.common (revision 33624) +++ epan/dissectors/Makefile.common (working copy) @@ -895,6 +895,7 @@ packet-tnef.c \ packet-tns.c \ packet-tn3270.c \ + packet-tor.c \ packet-tn5250.c \ packet-tpkt.c \ packet-tpncp.c \ Index: epan/dissectors/packet-ssl.c =================================================================== --- epan/dissectors/packet-ssl.c (revision 33624) +++ epan/dissectors/packet-ssl.c (working copy) @@ -280,6 +280,7 @@ static gint ssl_decrypted_data_avail = 0; static gchar* ssl_keys_list = NULL; +static gchar* ssl_master_keys_list = NULL; static gchar* ssl_psk = NULL; #if defined(SSL_DECRYPT_DEBUG) || defined(HAVE_LIBGNUTLS) @@ -308,18 +309,45 @@ ssl_debug_flush(); } +static void +ssl_parse_keys_file(gchar* ssl_tmp_keys_list) +{ + FILE *ssl_keys_file; + struct stat statb; + size_t size; + gchar *tmp_buf; + size_t nbytes; + gboolean read_failed; + + if (file_exists(ssl_tmp_keys_list)) { + if ((ssl_keys_file = ws_fopen(ssl_tmp_keys_list, "r"))) { + read_failed = FALSE; + fstat(fileno(ssl_keys_file), &statb); + size = (size_t)statb.st_size; + tmp_buf = ep_alloc0(size + 1); + nbytes = fread(tmp_buf, 1, size, ssl_keys_file); + if (ferror(ssl_keys_file)) { + report_read_failure(ssl_tmp_keys_list, errno); + read_failed = TRUE; + } + fclose(ssl_keys_file); + tmp_buf[nbytes] = '\0'; + if (!read_failed) + ssl_parse_key_list(tmp_buf,ssl_key_hash,ssl_associations,ssl_handle,TRUE); + } else { + report_open_failure(ssl_tmp_keys_list, errno, FALSE); + } + } else { + ssl_parse_key_list(ssl_tmp_keys_list,ssl_key_hash,ssl_associations,ssl_handle,TRUE); + } + +} /* parse ssl related preferences (private keys and ports association strings) */ static void ssl_parse(void) { ep_stack_t tmp_stack; SslAssociation *tmp_assoc; - FILE *ssl_keys_file; - struct stat statb; - size_t size; - gchar *tmp_buf; - size_t nbytes; - gboolean read_failed; ssl_set_debug(ssl_debug_file_name); @@ -341,28 +369,12 @@ if (ssl_keys_list && (ssl_keys_list[0] != 0)) { - if (file_exists(ssl_keys_list)) { - if ((ssl_keys_file = ws_fopen(ssl_keys_list, "r"))) { - read_failed = FALSE; - fstat(fileno(ssl_keys_file), &statb); - size = (size_t)statb.st_size; - tmp_buf = ep_alloc0(size + 1); - nbytes = fread(tmp_buf, 1, size, ssl_keys_file); - if (ferror(ssl_keys_file)) { - report_read_failure(ssl_keys_list, errno); - read_failed = TRUE; - } - fclose(ssl_keys_file); - tmp_buf[nbytes] = '\0'; - if (!read_failed) - ssl_parse_key_list(tmp_buf,ssl_key_hash,ssl_associations,ssl_handle,TRUE); - } else { - report_open_failure(ssl_keys_list, errno, FALSE); - } - } else { - ssl_parse_key_list(ssl_keys_list,ssl_key_hash,ssl_associations,ssl_handle,TRUE); - } + ssl_parse_keys_file(ssl_keys_list); } + if (ssl_master_keys_list && (ssl_master_keys_list[0] != 0)) + { + ssl_parse_keys_file(ssl_master_keys_list); + } ssl_debug_flush(); } @@ -1491,7 +1503,6 @@ case SSL_ID_HANDSHAKE: { tvbuff_t* decrypted; - /* try to decrypt handshake record, if possible. Store decrypted * record for later usage. The offset is used as 'key' to identify * this record in the packet (we can have multiple handshake records @@ -1501,14 +1512,26 @@ ssl_add_record_info(proto_ssl, pinfo, ssl_decrypted_data.data, ssl_decrypted_data_avail, offset); + ssl_debug_printf("dissect_ssl3_record: decrypting handshake\n"); /* try to retrieve and use decrypted handshake record, if any. */ decrypted = ssl_get_record_info(proto_ssl, pinfo, offset); if (decrypted) { /* add desegmented data to the data source list */ add_new_data_source(pinfo, decrypted, "Decrypted SSL record"); + /* if we are using user-supplied master_keys we need to switch + to the renegotiated master-key now. */ + ssl_debug_printf("dissect_ssl3_record: should i change master secret?\n"); + if (ssl && &ssl->master_key_session && &ssl->secondary_master_secret) { + ssl_debug_printf("dissect_ssl3_record: using secondary master_secret!\n"); + ssl->master_secret = ssl->secondary_master_secret; + } dissect_ssl3_handshake(decrypted, pinfo, ssl_record_tree, 0, decrypted->length, conv_version, ssl, content_type); } else { + if (ssl && &ssl->master_key_session) { + ssl_debug_printf("dissect_ssl3_record: using primary master_secret!\n"); + ssl->master_secret = ssl->primary_master_secret; + } dissect_ssl3_handshake(tvb, pinfo, ssl_record_tree, offset, record_length, conv_version, ssl, content_type); } @@ -1828,6 +1851,7 @@ if (!ssl) break; + ssl_debug_printf("dissect_ssl3_handshake SSL_HND_CLIENT_KEY_EXCHG\n"); cipher_num = ssl->cipher; @@ -1928,14 +1952,17 @@ } /* go with ssl key processessing; encrypted_pre_master - * will be used for master secret store - */ - ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key); - if (ret < 0) { - ssl_debug_printf("dissect_ssl3_handshake can't decrypt pre master secret\n"); - break; - } + * will be used for master secret store*/ + if (!ssl->master_key_session) { + ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key); + if (ret < 0) { + ssl_debug_printf("dissect_ssl3_handshake can't decrypt pre master secret\n"); + break; + } + }else + ssl->state |= SSL_MASTER_SECRET; } + if (ssl_generate_keyring_material(ssl)<0) { ssl_debug_printf("dissect_ssl3_handshake can't generate keyring material\n"); break; @@ -1994,7 +2021,7 @@ session_id_length = tvb_get_guint8(tvb, offset + 32); /* check stored session id info */ - if (from_server && (session_id_length == ssl->session_id.data_len) && + if (session_id_length && from_server && (session_id_length == ssl->session_id.data_len) && (tvb_memeql(tvb, offset+33, ssl->session_id.data, session_id_length) == 0)) { /* client/server id match: try to restore a previous cached session*/ @@ -2349,6 +2376,9 @@ ssl_debug_printf("dissect_ssl3_hnd_srv_hello found CIPHER 0x%04X -> state 0x%02X\n", ssl->cipher, ssl->state); + if (ssl->master_key_session) + ssl->state |= SSL_MASTER_SECRET; + /* if we have restored a session now we can have enough material * to build session key, check it out*/ ssl_debug_printf("dissect_ssl3_hnd_srv_hello trying to generate keys\n"); @@ -4495,6 +4525,11 @@ " is the local file name of the RSA private key used by the specified server " "(or name of the file containing such a list)", (const gchar **)&ssl_keys_list); + prefs_register_string_preference(ssl_module, "master_keys_list", "SSL master keys list", + "Semicolon-separated list of private SSL/TLS master keys used for SSL decryption; " + "each list entry must be in the form of ,,,. " + " is the master key used during the TLS/SSL session", + (const gchar **)&ssl_master_keys_list); prefs_register_string_preference(ssl_module, "debug_file", "SSL debug file", "Redirect SSL debug to file name; leave empty to disable debugging, " "or use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n", Index: epan/dissectors/packet-tor.c =================================================================== --- epan/dissectors/packet-tor.c (revision 0) +++ epan/dissectors/packet-tor.c (revision 0) @@ -0,0 +1,1814 @@ +/* packet-tor.c + * Routines for tor.packet dissection + * https://svn.torproject.org/svn/tor/trunk/doc/spec/tor-spec.txt + * https://svn.torproject.org/svn/tor/trunk/doc/spec/rend-spec.txt + * Copyright 2009, Robert Hogan + * + * $Id: packet-tor.c 26356 2008-10-05 23:08:54Z wmeier $ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * Copied from packet-pop.c and packet-ssl.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * TODO: + * Call subdissectors for relay payloads + * Store the context for a decrypted payload rather than the decrypted payload itself + * Remove memleaks + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "packet-ssl.h" +#include "packet-ssl-utils.h" + +#define REVERSE 0 +#define FORWARD 1 + +#define PADDING 0x00 +#define CREATE 0x01 +#define CREATED 0x02 +#define RELAY 0x03 +#define DESTROY 0x04 +#define CREATE_FAST 0x05 +#define CREATED_FAST 0x06 +#define VERSIONS 0x07 +#define NETINFO 0x08 +#define RELAY_EARLY 0x09 + +static const value_string vals_circuit_commands[] = { + { PADDING , "(Padding)"}, + { CREATE , "(Create a circuit)"}, + { CREATED , "(Acknowledge create)"}, + { RELAY , "(End-to-end data)"}, + { DESTROY , "(Stop using a circuit)"}, + { CREATE_FAST , "(Create a circuit, no PK)"}, + { CREATED_FAST, "(Circuit created, no PK)"}, + { VERSIONS , "(Negotiate proto version)"}, + { NETINFO , "(Time and address info)"}, + { RELAY_EARLY , "(End-to-end data (Relay Early).)"}, + { 0x00, NULL } +}; + +#define NONE 0x00 +#define PROTOCOL 0x01 +#define INTERNAL 0x02 +#define REQUESTED 0x03 +#define HIBERNATING 0x04 +#define RESOURCELIMIT 0x05 +#define CONNECTFAILED 0x06 +#define OR_IDENTITY 0x07 +#define OR_CONN_CLOSED 0x08 +#define FINISHED 0x09 +#define TIMEOUT 0x0A +#define DESTROYED 0x0B +#define NOSUCHSERVICE 0x0C + +static const value_string vals_destroy_reason[] = { + { NONE , "(No reason given.)" }, + { PROTOCOL , "(Tor protocol violation.)" }, + { INTERNAL , "(Internal error.)" }, + { REQUESTED , "(A client sent a TRUNCATE command.)" }, + { HIBERNATING , "(Not currently operating; trying to save bandwidth.)" }, + { RESOURCELIMIT , "(Out of memory, sockets, or circuit IDs.)" }, + { CONNECTFAILED , "(Unable to reach server.)" }, + { OR_IDENTITY , "(Connected to server, but its OR identity was not as expected.)" }, + { OR_CONN_CLOSED, "(The OR connection that was carrying this circuit died.)" }, + { FINISHED , "(The circuit has expired for being dirty or old.)" }, + { TIMEOUT , "(Circuit construction took too long)" }, + { DESTROYED , "(The circuit was destroyed w/o client TRUNCATE)" }, + { NOSUCHSERVICE , "(Request for unknown hidden service)"}, + { 0x00, NULL } +}; + +#define RELAY_BEGIN 0x01 +#define RELAY_DATA 0x02 +#define RELAY_END 0x03 +#define RELAY_CONNECTED 0x04 +#define RELAY_SENDME 0x05 +#define RELAY_EXTEND 0x06 +#define RELAY_EXTENDED 0x07 +#define RELAY_TRUNCATE 0x08 +#define RELAY_TRUNCATED 0x09 +#define RELAY_DROP 0x0A +#define RELAY_RESOLVE 0x0B +#define RELAY_RESOLVED 0x0C +#define RELAY_BEGIN_DIR 0x0D + +#define RELAY_ESTABLISH_INTRO 0x20 +#define RELAY_ESTABLISH_RENDEZVOUS 0x21 +#define RELAY_INTRODUCE1 0x22 +#define RELAY_INTRODUCE2 0x23 +#define RELAY_RENDEZVOUS1 0x24 +#define RELAY_RENDEZVOUS2 0x25 +#define RELAY_INTRO_ESTABLISHED 0x26 +#define RELAY_RENDEZVOUS_ESTABLISHED 0x27 +#define RELAY_COMMAND_INTRODUCE_ACK 0x28 + +static const value_string vals_relay_commands[] = { + { RELAY_BEGIN , "RELAY_BEGIN"}, + { RELAY_DATA , "RELAY_DATA"}, + { RELAY_END , "RELAY_END"}, + { RELAY_CONNECTED, "RELAY_CONNECTED"}, + { RELAY_SENDME , "RELAY_SENDME"}, + { RELAY_EXTEND , "RELAY_EXTEND"}, + { RELAY_EXTENDED , "RELAY_EXTENDED"}, + { RELAY_TRUNCATE , "RELAY_TRUNCATE"}, + { RELAY_TRUNCATED, "RELAY_TRUNCATED"}, + { RELAY_DROP , "RELAY_DROP"}, + { RELAY_RESOLVE , "RELAY_RESOLVE"}, + { RELAY_RESOLVED , "RELAY_RESOLVED"}, + { RELAY_BEGIN_DIR, "RELAY_BEGIN_DIR"}, + { RELAY_ESTABLISH_INTRO , "RELAY_ESTABLISH_INTRO"}, + { RELAY_ESTABLISH_RENDEZVOUS , "RELAY_ESTABLISH_RENDEZVOUS"}, + { RELAY_INTRODUCE1 , "RELAY_INTRODUCE1"}, + { RELAY_INTRODUCE2 , "RELAY_INTRODUCE2"}, + { RELAY_RENDEZVOUS1 , "RELAY_RENDEZVOUS1"}, + { RELAY_RENDEZVOUS2 , "RELAY_RENDEZVOUS2"}, + { RELAY_INTRO_ESTABLISHED , "RELAY_INTRO_ESTABLISHED"}, + { RELAY_RENDEZVOUS_ESTABLISHED, "RELAY_RENDEZVOUS_ESTABLISHED"}, + { RELAY_COMMAND_INTRODUCE_ACK , "RELAY_COMMAND_INTRODUCE_ACK"}, + { 0x00, NULL } +}; + +#define HOSTNAME 0x00 +#define IPV4_ADDRESS 0x04 +#define IPV6_ADDRESS 0x06 +#define ERROR_TRANSIENT 0xF0 +#define ERROR_NONTRANSIENT 0xF1 + +static const value_string vals_address_types[] = { + { HOSTNAME , "HOSTNAME"}, + { IPV4_ADDRESS , "IPV4_ADDRESS"}, + { IPV6_ADDRESS , "IPV6_ADDRESS"}, + { ERROR_TRANSIENT , "ERROR_TRANSIENT"}, + { ERROR_NONTRANSIENT, "ERROR_NONTRANSIENT"}, + { 0x00, NULL } +}; + +#define REASON_MISC 0x01 +#define REASON_RESOLVEFAILED 0x02 +#define REASON_CONNECTREFUSED 0x03 +#define REASON_EXITPOLICY 0x04 +#define REASON_DESTROY 0x05 +#define REASON_DONE 0x06 +#define REASON_TIMEOUT 0x07 +#define REASON_HIBERNATING 0x09 +#define REASON_INTERNAL 0x0A +#define REASON_RESOURCELIMIT 0x0B +#define REASON_CONNRESET 0x0C +#define REASON_TORPROTOCOL 0x0D +#define REASON_NOTDIRECTORY 0x0E + +static const value_string vals_relay_end_reason[] = { + { REASON_MISC , "(catch-all for unlisted reasons)"}, + { REASON_RESOLVEFAILED , "(couldn't look up hostname)"}, + { REASON_CONNECTREFUSED , "(remote host refused connection) [*]"}, + { REASON_EXITPOLICY , "(OR refuses to connect to host or port)"}, + { REASON_DESTROY , "(Circuit is being destroyed)"}, + { REASON_DONE , "(Anonymized TCP connection was closed)"}, + { REASON_TIMEOUT , "(Connection timed out, or OR timed out while connecting)"}, + { REASON_HIBERNATING , "(OR is temporarily hibernating)"}, + { REASON_INTERNAL , "(Internal error at the OR)"}, + { REASON_RESOURCELIMIT , "(OR has no resources to fulfill request)"}, + { REASON_CONNRESET , "(Connection was unexpectedly reset)"}, + { REASON_TORPROTOCOL , "(Sent when closing connection because of Tor protocol violations.)"}, + { REASON_NOTDIRECTORY , "(Client sent RELAY_BEGIN_DIR to a non-directory server.)"}, + { 0x00, NULL } +}; + +#define CELL_LEN 512 +#define PAYLOAD_LEN 509 +#define RELAY_DATA_LEN PAYLOAD_LEN - 11 +#define HASH_LEN 20 +#define DH_LEN 128 +#define MAX_BLOCKSIZE 16 + +#define TCP_PORT_SSL_TOR 9001 + +static int proto_tor = -1; + +static int hf_tor_circid = -1; +static int hf_tor_command = -1; +static int hf_tor_payload = -1; +static int hf_tor_length = -1; +static int hf_tor_timestamp = -1; +static int hf_tor_other_or_address = -1; +static int hf_tor_other_or_address_ipv6 = -1; +static int hf_tor_number_of_addresses = -1; +static int hf_tor_this_or_address = -1; +static int hf_tor_this_or_address_ipv6 = -1; +static int hf_tor_address_type = -1; +static int hf_tor_address_length = -1; +static int hf_tor_hostname = -1; +static int hf_tor_ttl = -1; +static int hf_tor_key_material_y = -1; +static int hf_tor_key_material_x = -1; +static int hf_tor_dh_data = -1; +static int hf_tor_derivative_key_data = -1; +static int hf_tor_create = -1; +static int hf_tor_destroy_reason = -1; +static int hf_tor_relay_command = -1; +static int hf_tor_relay_data = -1; +static int hf_tor_relay_data_length = -1; +static int hf_tor_relay_digest = -1; +static int hf_tor_streamid = -1; +static int hf_tor_recognized = -1; +static int hf_tor_padding = -1; +static int hf_tor_encrypted_cell = -1; +static int hf_tor_relay_connected_ip = -1; +static int hf_tor_relay_connected_ttl = -1; +static int hf_tor_relay_end_reason = -1; +static int hf_tor_relay_end_ip = -1; +static int hf_tor_relay_end_ipv6 = -1; +static int hf_tor_relay_end_ttl = -1; +static int hf_tor_resolved_status = -1; +static int hf_tor_resolve_address = -1; +static int hf_tor_resolve_port = -1; +static int hf_tor_establish_intro_hs = -1; +static int hf_tor_establish_intro_kl = -1; +static int hf_tor_establish_intro_pk = -1; +static int hf_tor_establish_intro_sig = -1; +static int hf_tor_establish_rendezvous_cookie = -1; +static int hf_tor_introduce_encrypted_payload = -1; +static int hf_tor_introduce_pk_id = -1; +static int hf_tor_rendezvous_cookie = -1; +static int hf_tor_rendezvous_dh = -1; +static int hf_tor_rendezvous_hd = -1; + +static gint ett_tor = -1; + +static dissector_handle_t data_handle, http_handle; + +static gchar* cell_keys_list = NULL; +static GHashTable *tor_key_hash = NULL; +static GHashTable *tor_relay_data_hash = NULL; + +typedef struct _tor_cipher_hd_t +{ + + unsigned char ctr[MAX_BLOCKSIZE]; /* For Counter (CTR) mode. */ + + /*This is the context's current position in ctrbuf. Where the number + of bytes encrypted are not a multiple of c->cipher_block_size this + stores the position of the next byte in the keystream to be xor'd + by do_encrypt_ctr. ctr gets incremented every time ctrpos reaches + c->cipher_block_size. */ + unsigned int ctrpos; /* For Counter (CTR) mode. */ + + /* This contains the context's current keystream. ctrpos stores the + next position to be xor'd in ctrbuf when do_ctr_encrypt is called. + The contents of ctr are encrypted every time ctrpos reaches + zero in do_ctr_encrypt, and the result is stored in ctrbuf. */ + char ctrbuf[MAX_BLOCKSIZE]; /* For Counter (CTR) mode. */ + +} tor_cipher_hd_t; + + +typedef struct _cell_key { + gchar *key; + gint no_of_hops; + tor_cipher_hd_t ctr_data; + gcry_md_hd_t digest_hd; + guint hop; + struct _cell_key *next; +} cell_key_t; + +typedef struct _TorService { + guint16 circid; + guint8 source[4]; + guint direction; +} TorService; + +void proto_reg_handoff_tor(void); + +static void +tor_add_cell_key(cell_key_t *key, cell_key_t *newkey) +{ + cell_key_t *first_key = key; + + newkey->hop++; + while (key->next) { + newkey->hop++; + key = key->next; + } + key->next = newkey; + first_key->no_of_hops = newkey->hop; + +} + +static cell_key_t * +tor_get_cell_key(cell_key_t *rec, guint hop) +{ + while (rec) { + if (rec->hop == hop) return rec; + rec = rec->next; + } + return NULL; +} + +/* store master secret into session data cache */ +void +tor_save_decrypted(StringInfo* data_key, const guint8 *decrypted) +{ + /* allocate stringinfo chunks for session id and master secret data*/ + StringInfo* decrypted_data; + decrypted_data = se_alloc0(PAYLOAD_LEN + sizeof(StringInfo)); + + decrypted_data->data = ((guchar*)decrypted_data+sizeof(StringInfo)); + + /* ssl_hash() depends on data_key->data being aligned for guint access + * so be careful in changing how it is allocated. + */ + memcpy(decrypted_data->data, decrypted, PAYLOAD_LEN); + decrypted_data->data_len = PAYLOAD_LEN; + + g_hash_table_insert(tor_relay_data_hash, data_key, decrypted_data); +} + +static gint +tor_relay_data_equal (gconstpointer v, gconstpointer v2) +{ + const StringInfo *val1; + const StringInfo *val2; + val1 = (const StringInfo *)v; + val2 = (const StringInfo *)v2; + + if (val1->data_len == val2->data_len && + !memcmp(val1->data, val2->data, val2->data_len)) { + return 1; + } + return 0; +} + +static guint +tor_relay_data_key_hash (gconstpointer v) +{ + guint l,hash; + const StringInfo* id; + const guint* cur; + hash = 0; + id = (const StringInfo*) v; + + cur = (const guint*)(void*) id->data; + + for (l=4; (l < id->data_len); l+=4, cur++) + hash = hash ^ (*cur); + + return hash; +} + +static void +tor_relay_data_free(gpointer id, gpointer key, gpointer dummy _U_) +{ + g_free(id); + g_free((StringInfo *)key); +} + +static gint +tor_key_equal (gconstpointer v, gconstpointer v2) +{ + const TorService *val1; + const TorService *val2; + val1 = (const TorService *)v; + val2 = (const TorService *)v2; + + if ((val1->circid == val2->circid) && + (val1->direction == val2->direction) && + !memcmp(val1->source, val2->source, 4)) { + return 1; + } + return 0; +} + +static guint +tor_cell_key_hash (gconstpointer v) +{ + const TorService *key; + const guint* cr; + guint hash; + key = (const TorService *)v; + hash = key->circid; + hash = hash ^ key->direction; + cr = (const guint*) key->source; + hash = hash ^ (*cr); + return hash; +} + +static void +tor_key_free(gpointer id, gpointer key, gpointer dummy _U_) +{ + g_free(id); + g_free((cell_key_t*)key); +} + +static gint +tor_cipher_init(gcry_cipher_hd_t *cipher, guchar* sk) +{ + gint err; + + err = gcry_cipher_open(cipher, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0); + if (err !=0) + return -1; + err = gcry_cipher_setkey(*(cipher), sk, gcry_cipher_get_algo_blklen (GCRY_CIPHER_AES128)); + if (err != 0) + return -1; + gcry_cipher_setiv(*(cipher), NULL, 0); + if (err != 0) + return -1; + return 0; +} + +/* Initialize AES-CTR wrapper for libgcrypt */ +static gint +tor_ctr_init(tor_cipher_hd_t *c) +{ + + memset (c->ctr, 0, MAX_BLOCKSIZE); + memset (c->ctrbuf, 0, MAX_BLOCKSIZE); + c->ctrpos=0; + return 0; +} + +/* AES-CTR wrapper for libgcrypt */ +static void +tor_do_ctr_encrypt( tor_cipher_hd_t *c, guchar *sk, char *inbuf, unsigned int nbytes ) +{ + unsigned int n, i; + gcry_cipher_hd_t cipher; + tor_cipher_init(&cipher, sk); + + for (n = 0; n < nbytes;) + { + if (c->ctrpos == 0) { + gcry_cipher_encrypt ( cipher, c->ctrbuf, MAX_BLOCKSIZE, + c->ctr, MAX_BLOCKSIZE); + } + for (i = c->ctrpos; i < MAX_BLOCKSIZE; i++, n++) + { + if (n == nbytes) { c->ctrpos = i; return; } + inbuf[n] ^= c->ctrbuf[i]; + } + for (i = MAX_BLOCKSIZE; i > 0; i--) + { + c->ctr[i-1]++; + if (c->ctr[i-1] != 0) + break; + } + c->ctrpos = 0; + } + gcry_cipher_close(cipher); + + return; +} + +static void +tor_decrypt_cell(guint8 *encrypted_data, cell_key_t *cell_key) +{ + + if (!cell_key->ctr_data.ctr) { + tor_ctr_init(&cell_key->ctr_data); + } + + tor_do_ctr_encrypt(&cell_key->ctr_data, cell_key->key, encrypted_data, PAYLOAD_LEN); + +} + +static cell_key_t * +tor_load_cell_key(gchar *key, gchar *digest) +{ + GByteArray *bytes = NULL; + GByteArray *dbytes = NULL; + gboolean res; + cell_key_t *cell_key = g_malloc(sizeof(cell_key_t)); + cell_key->key = 0; + cell_key->hop=1; + cell_key->no_of_hops=1; + cell_key->next = NULL; + bytes = g_byte_array_new(); + res = hex_str_to_bytes(key, bytes,FALSE); + + /* Save the circuit key */ + if (res && bytes->len == 16) { + cell_key->key=g_malloc(bytes->len); + memcpy(cell_key->key,bytes->data,bytes->len); + } + + /* Set up the AES_CTR wrapper */ + tor_ctr_init(&cell_key->ctr_data); + + /* Seed the circuit digest */ + dbytes = g_byte_array_new(); + res = hex_str_to_bytes(digest, dbytes, FALSE); + gcry_md_open (&cell_key->digest_hd, GCRY_MD_SHA1, 0); + gcry_md_write (cell_key->digest_hd, dbytes->data, dbytes->len); + + g_byte_array_free(bytes, TRUE); + g_byte_array_free(dbytes, TRUE); + return cell_key; +} + +/* parse tor related preferences (cell keys and ports association strings) */ +static void +tor_parse_key_list(const gchar * keys_list, GHashTable *key_hash) +{ + gchar* end; + gchar* start; + gchar* tmp; + TorService* service; + cell_key_t *cell_key=NULL, *tmp_cell_key=NULL; + char log_line_preamble[60] = "Circuit key (address,port," + "circid,direction,digest,crypto): \0"; + + start = g_strdup(keys_list); + tmp = start; + ssl_debug_printf("tor_init keys string:\n%s\n", start); + do { + int read_index, write_index; + gchar *address, *port = 0, *circid = 0, *direction, *key, *digest; + + address = start; + /* split ip/file couple with ';' separator*/ + end = strpbrk(start, ";\n\r"); + if (end) { + *end = 0; + start = end+1; + } + + /* Remove all the leading material from addr provided by a Tor log line. + This is typically of the form: + Jan 26 21:24:43.663 [info] crypto_dump_crypto_key(): \ + Circuit key (address,port,circid,direction,digest,crypto): */ + + if ((address = strstr(address,log_line_preamble)) == NULL) { + ssl_debug_printf("tor_init entry malformed can't find address in %s\n", address); + continue; + } + address += sizeof(log_line_preamble); + + /* skip comments (in file) */ + if (address[0] == '#') continue; + + + ssl_debug_printf("tor_init found port entry %s\n", port); + port = strchr(address, ','); + if (!port) + { + ssl_debug_printf("tor_init entry malformed can't find port in '%s'\n", address); + continue; + } + *port = 0; + port++; + + ssl_debug_printf("tor_init found circid entry %s\n", circid); + circid = strchr(port, ','); + if (!circid) + { + ssl_debug_printf("tor_init entry malformed can't find circid in '%s'\n", port); + continue; + } + *circid = 0; + circid++; + + ssl_debug_printf("tor_init found circid entry %s\n", circid); + direction = strchr(circid, ','); + if (!direction || (strncmp(",forward", direction,8) + && (strncmp(",reverse", direction,8)))) + { + ssl_debug_printf("tor_init entry malformed can't find direction in '%s'\n", circid); + continue; + } + *direction = 0; + direction++; + + digest = strchr(direction,','); + if (!digest) + { + ssl_debug_printf("tor_init entry malformed can't find digest in %s\n", direction); + continue; + } + *digest=0; + digest++; + + key = strchr(digest,','); + if (!key) + { + ssl_debug_printf("tor_init entry malformed can't find key in %s\n", digest); + continue; + } + *key=0; + key++; + + + /* remove all spaces and quotation marks in addr */ + read_index = 0; + write_index = 0; + + while(address[read_index]) { + if (address[read_index] != ' ' && + address[read_index] != '"') { + address[write_index] = address[read_index]; + write_index++; + } + read_index++; + } + address[write_index] = 0; + + /* Load the cell key information for look-up when dissecting */ + service = g_malloc(sizeof(TorService) + 8); + service->circid = atoi(circid); + if(!strcmp("forward", direction)) { + service->direction = FORWARD; + }else{ + service->direction = REVERSE; + } + + memset(service->source,0,4); + if (strlen(key)==32) { + cell_key = tor_load_cell_key(key, digest); + /* !!! */ + if (!cell_key) { + ssl_debug_printf("can't load cell key from %s\n", key); + continue; + } + } + ssl_debug_printf("tor_init cell key file %s successfully loaded\n",key); + + /* if item exists, remove first */ + tmp_cell_key = g_hash_table_lookup(key_hash, service); + if (tmp_cell_key){ + tor_add_cell_key(tmp_cell_key, cell_key); + } else { + g_hash_table_insert(key_hash, service, cell_key); + } + + } while (end != NULL); + g_free(tmp); +} + +static void +tor_parse_keys_file(gchar* tor_tmp_keys_list) +{ + FILE *tor_keys_file; + struct stat statb; + size_t size; + gchar *tmp_buf; + size_t nbytes; + gboolean read_failed; + + if (file_exists(tor_tmp_keys_list)) { + if ((tor_keys_file = ws_fopen(tor_tmp_keys_list, "r"))) { + read_failed = FALSE; + fstat(fileno(tor_keys_file), &statb); + size = statb.st_size; + tmp_buf = ep_alloc0(size + 1); + nbytes = fread(tmp_buf, 1, size, tor_keys_file); + if (ferror(tor_keys_file)) { + report_read_failure(tor_tmp_keys_list, errno); + read_failed = TRUE; + } + fclose(tor_keys_file); + tmp_buf[nbytes] = '\0'; + if (!read_failed) + tor_parse_key_list(tmp_buf,tor_key_hash); + } else { + report_open_failure(tor_tmp_keys_list, errno, FALSE); + } + } else { + tor_parse_key_list(tor_tmp_keys_list,tor_key_hash); + } + +} + +/* parse tor related preferences (cell keys and ports association strings) */ +static void +tor_parse(void) +{ + if (tor_key_hash) + { + g_hash_table_foreach(tor_key_hash, tor_key_free, NULL); + g_hash_table_destroy(tor_key_hash); + } + + /* parse cell keys string, load available keys and put them in key hash*/ + tor_key_hash = g_hash_table_new(tor_cell_key_hash,tor_key_equal); + + if (tor_relay_data_hash) + { + g_hash_table_foreach(tor_relay_data_hash, tor_relay_data_free, NULL); + g_hash_table_destroy(tor_relay_data_hash); + } + + /* parse cell relay_datas string, load available relay_datas and put them in relay_data hash*/ + tor_relay_data_hash = g_hash_table_new(tor_relay_data_key_hash,tor_relay_data_equal); + + if (cell_keys_list && (cell_keys_list[0] != 0)) + { + tor_parse_keys_file(cell_keys_list); + } +} + +static gint +add_tor_address(proto_tree *payload_tree, tvbuff_t *tvb, gint offset, gboolean other) +{ + gint address_type, address_length, start; + struct e_in6_addr address_ipv6; + + start=offset; + + address_type=tvb_get_guint8(tvb, offset); + proto_tree_add_item(payload_tree, + hf_tor_address_type, + tvb, offset, + 1, + FALSE); + offset+=1; + + address_length=tvb_get_guint8(tvb, offset); + proto_tree_add_item(payload_tree, + hf_tor_address_length, + tvb, offset, + 1, + FALSE); + offset+=1; + + switch(address_type) { + case HOSTNAME: + proto_tree_add_item(payload_tree, + hf_tor_hostname, + tvb, offset, + address_length, + FALSE); + break; + case IPV4_ADDRESS: + proto_tree_add_ipv4(payload_tree, + (other)?hf_tor_other_or_address:hf_tor_this_or_address, + tvb, offset, + address_length, + tvb_get_ipv4(tvb,offset)); + break; + case IPV6_ADDRESS: + tvb_get_ipv6(tvb, offset, &address_ipv6); + proto_tree_add_ipv6(payload_tree, + (other)?hf_tor_other_or_address_ipv6:hf_tor_this_or_address_ipv6, + tvb, offset, + 16, (guint8 *)&address_ipv6); + break; + default: + proto_tree_add_item(payload_tree, + hf_tor_hostname, + tvb, offset, + address_length, + FALSE); + } + offset+=address_length; + return (offset-start); +} + +static gint +dissect_relay_resolved_payload(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + gint start=offset; + + while (tvb_offset_exists(tvb, offset) && tvb_get_guint8(tvb, offset)) { + offset+=add_tor_address(payload_tree, tvb, offset, FALSE); + proto_tree_add_item(payload_tree, + hf_tor_ttl, + tvb, offset, + 1, + FALSE); + offset+=1; + } + return (offset-start); +} + +static gint +dissect_relay_end_payload(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + int end_reason, used = 0, is_ipv6 = 0; + + end_reason = tvb_get_guint8(tvb, offset); + proto_tree_add_item(payload_tree, + hf_tor_relay_end_reason, + tvb, offset, + 1, + FALSE); + used+=1; + + if (end_reason == REASON_EXITPOLICY) { + is_ipv6 = tvb_get_guint8(tvb, offset+5); + if (is_ipv6) { + proto_tree_add_item(payload_tree, + hf_tor_relay_end_ipv6, + tvb, offset + used, + 16, + FALSE); + used+=16; + } else { + proto_tree_add_item(payload_tree, + hf_tor_relay_end_ip, + tvb, offset + used, + 4, + FALSE); + used+=4; + } + proto_tree_add_item(payload_tree, + hf_tor_relay_end_ttl, + tvb, offset + used, + 4, + FALSE); + used+=4; + } + + return used; +} + +static gint +dissect_relay_connected_payload(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + int start=offset; + proto_tree_add_item(payload_tree, + hf_tor_relay_connected_ip, + tvb, offset, + 4, + FALSE); + offset+=4; + proto_tree_add_item(payload_tree, + hf_tor_relay_connected_ttl, + tvb, offset, + 4, + FALSE); + offset+=4; + return (offset-start); +} + +static gint +dissect_relay_introduce_payload(proto_tree *payload_tree, tvbuff_t *tvb, + gint offset) +{ + + proto_tree_add_item(payload_tree, + hf_tor_introduce_pk_id, + tvb, offset, + 20, + FALSE); + offset+=20; + + proto_tree_add_item(payload_tree, + hf_tor_introduce_encrypted_payload, + tvb, offset, + RELAY_DATA_LEN - 20, + FALSE); + + return RELAY_DATA_LEN; +} + +static gint +dissect_relay_rendezvous_payload(proto_tree *payload_tree, tvbuff_t *tvb, + gint offset, gboolean one) +{ + int start=offset; + + if (one) { + proto_tree_add_item(payload_tree, + hf_tor_rendezvous_cookie, + tvb, offset, + 20, + FALSE); + offset+=20; + } + + proto_tree_add_item(payload_tree, + hf_tor_rendezvous_dh, + tvb, offset, + DH_LEN, + FALSE); + offset+=DH_LEN; + + proto_tree_add_item(payload_tree, + hf_tor_rendezvous_hd, + tvb, offset, + 20, + FALSE); + offset+=20; + return (offset - start); +} + +static gint +dissect_relay_establish_rendezvous_payload(proto_tree *payload_tree, tvbuff_t *tvb, + gint offset) +{ + int start=offset; + + proto_tree_add_item(payload_tree, + hf_tor_establish_rendezvous_cookie, + tvb, offset, + 20, + FALSE); + offset+=20; + + return (offset - start); +} + +static gint +dissect_relay_establish_intro_payload(proto_tree *payload_tree, tvbuff_t *tvb, + gint offset) +{ + gint used = 0; + guint key_length; + + key_length = (guint)tvb_get_ntohs(tvb, offset); + proto_tree_add_item(payload_tree, + hf_tor_establish_intro_kl, + tvb, offset, + 2, + FALSE); + used+=2; + + proto_tree_add_item(payload_tree, + hf_tor_establish_intro_pk, + tvb, offset + used, + key_length, + FALSE); + used+=key_length; + + proto_tree_add_item(payload_tree, + hf_tor_establish_intro_hs, + tvb, offset + used, + 20, + FALSE); + used+=20; + + proto_tree_add_item(payload_tree, + hf_tor_establish_intro_sig, + tvb, offset + used, + (RELAY_DATA_LEN - used), + FALSE); + + return RELAY_DATA_LEN; +} + +static gint +dissect_relay_resolve_payload(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + const guint8 *resolve_address; + + resolve_address = tvb_get_ephemeral_string(tvb, offset, RELAY_DATA_LEN); + + if (!resolve_address) + return 0; + + proto_tree_add_item(payload_tree, + hf_tor_resolve_address, + tvb, offset, + strlen(resolve_address), + FALSE); + + return strlen(resolve_address); +} + +static gint +dissect_destroy_cell(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + gint start=offset; + + proto_tree_add_item(payload_tree, + hf_tor_destroy_reason, + tvb, offset, + 1, + FALSE); + offset+=1; + + return (offset-start); +} + +static gint +tor_add_padding(proto_tree *tree, tvbuff_t *tvb, gint offset) +{ + /*Add any Padding*/ + gint t_offset = offset; + while (tvb_offset_exists(tvb, t_offset) && !tvb_get_guint8(tvb, t_offset)) + ++t_offset; + if (t_offset - offset > 2) { + proto_tree_add_item(tree, + hf_tor_padding, + tvb, offset, + t_offset - offset, + FALSE); + return (t_offset - offset); + } + return 0; +} + +/* Check the four byte digest in the relay cell payload */ +static gint +check_relay_digest(gcry_md_hd_t *digest_hd, char *data, char *relay_digest) +{ + gcry_md_hd_t digest_hd_pre, digest_hd_post; + char *current_digest; + char *digest_data; + int ret = 1; + + /* Set the four byte digest in the payload to zero when calculating the + digest */ + digest_data = (guint8 *) g_malloc ((PAYLOAD_LEN) * sizeof(guint8)); + memset(digest_data,0,PAYLOAD_LEN); + memcpy(digest_data, data, PAYLOAD_LEN); + memset(digest_data + 5, 0, 4); + + /* Take a copy of the SHA1 context before and after hashing */ + gcry_md_copy (&digest_hd_pre, *(digest_hd)); + gcry_md_write (*(digest_hd), digest_data, PAYLOAD_LEN); + gcry_md_copy (&digest_hd_post, *(digest_hd)); + + + /* If the first four bytes of the calculated digest match the four + in the payload, then all is well. If they don't match, copy the + context prior to hashing back in. */ + current_digest = gcry_md_read(digest_hd_post, 0); + ssl_print_data("Decrypted Payload for Digest", digest_data, PAYLOAD_LEN); + ssl_print_data("Calculated Digest: ", current_digest, 4); + ssl_print_data("Received Digest: ", relay_digest, 4); + if (memcmp(current_digest,relay_digest,4) != 0) { + gcry_md_copy (digest_hd, digest_hd_pre); + ret = 0; + } + + gcry_md_close(digest_hd_pre); + gcry_md_close(digest_hd_post); + g_free(digest_data); + return ret; +} + +/* Parse the contents of a Tor relay cell */ +static gint +dissect_relay_cell(proto_tree *payload_tree, tvbuff_t *tvb, gint offset, guint circid, packet_info *pinfo) +{ + guint8 relay_command; + TorService* service; + cell_key_t *cell_key; + guint8 *decrypted_data = NULL; + StringInfo *data_key = NULL; + StringInfo *stored_data = NULL; + tvbuff_t *tvb_decrypted, *next_tvb; + gint d_offset=0, i; + gboolean found_payload=FALSE; + guint data_length; + dissector_handle_t tmp_handle; + guint8 *first_four; + char relay_digest[4]; + gcry_md_hd_t digest_hd; + + service = g_malloc(sizeof(TorService) + 8); + service->circid = circid; + /*FIXME: get correct direction */ + memcpy(service->source, pinfo->src.data, pinfo->src.len); + + for (service->direction = REVERSE; + service->direction < 2; service->direction++) { + cell_key = g_hash_table_lookup(tor_key_hash, service); + if (cell_key) { + break; + } + } + g_free(service); + + if ((!cell_key)) { + return 0; + } + + /* Get the encrypted payload from the tvb buffer */ + decrypted_data = (guint8 *) g_malloc ((PAYLOAD_LEN) * sizeof(guint8)); + memset(decrypted_data,0,PAYLOAD_LEN); + tvb_memcpy(tvb, decrypted_data , offset, PAYLOAD_LEN); + + /*Prepare the key for looking up the encrypted data */ + data_key = se_alloc0(8 + sizeof(StringInfo)); + data_key->data = ((guchar*)data_key+sizeof(StringInfo)); + memcpy(data_key->data, decrypted_data,8); + data_key->data_len = 8; + + /* Have we already decrypted this payload ? */ + if ((stored_data = g_hash_table_lookup(tor_relay_data_hash, data_key)) == NULL) { + /* A Tor cell is encrypted by each hop in the circuit. We iterate through the + keys we have for this circuit and decrypt each hop's layer until we get + the plaintext. */ + for (i=1; i <= cell_key->no_of_hops; i++) { + cell_key_t *ckey; + if ((ckey = tor_get_cell_key(cell_key,i)) == 0) + break; + ssl_print_data("Encrypted Data", decrypted_data, PAYLOAD_LEN); + ssl_print_data("Cell Key", ckey->key, 16); + tor_decrypt_cell(decrypted_data, ckey); + ssl_print_data("Decrypted Data", decrypted_data, PAYLOAD_LEN); + /* If bytes 2 and 3 of the decrypted cell are zero then it might + be fully decrypted. To be sure, we have to check the digest + at bytes six to ten first. */ + if (!decrypted_data[1] && !decrypted_data[2]) { + /* Use the SHA1 context for this circuit hop when checking the + cell's four-byte digest.*/ + digest_hd = ckey->digest_hd; + memcpy(relay_digest, decrypted_data + 5, 4); + /* If the digest is correct, then this packet is ready for display */ + if (check_relay_digest(&digest_hd, decrypted_data, relay_digest)) { + found_payload=TRUE; + tor_save_decrypted(data_key, decrypted_data); + break; + } + } + } + } else { + memcpy(decrypted_data,stored_data->data, stored_data->data_len); + found_payload=TRUE; + } + + /* If we can't decrypt the payload or match the digest in the decrypted payload + then we have nothing to dissect */ + if (!found_payload) { + return 0; + } + + /* Display the Decrypted Cell */ + ssl_print_data("Found Decrypted Data", decrypted_data, PAYLOAD_LEN); + + tvb_decrypted = tvb_new_real_data(decrypted_data, PAYLOAD_LEN, PAYLOAD_LEN); + tvb_set_child_real_data_tvbuff(tvb, tvb_decrypted); + + add_new_data_source(pinfo, tvb_decrypted, "Decrypted Relay Cell"); + + /* Handler to free the Decrypted Data Buffer. */ + tvb_set_free_cb(tvb_decrypted,g_free); + + /* Dissect the Decrypted Relay Cell */ + relay_command = tvb_get_guint8(tvb_decrypted, d_offset); + proto_tree_add_item(payload_tree, + hf_tor_relay_command, + tvb_decrypted, d_offset, + 1, + FALSE); + d_offset+=1; + + proto_tree_add_item(payload_tree, + hf_tor_recognized, + tvb_decrypted, d_offset, + 2, + FALSE); + d_offset+=2; + + proto_tree_add_item(payload_tree, + hf_tor_streamid, + tvb_decrypted, d_offset, + 2, + FALSE); + d_offset+=2; + + proto_tree_add_item(payload_tree, + hf_tor_relay_digest, + tvb_decrypted, d_offset, + 4, + FALSE); + d_offset+=4; + + data_length=(guint)tvb_get_ntohs(tvb_decrypted, d_offset); + proto_tree_add_item(payload_tree, + hf_tor_relay_data_length, + tvb_decrypted, d_offset, + 2, + FALSE); + d_offset+=2; + + switch(relay_command) { + case RELAY_RESOLVE: + d_offset += dissect_relay_resolve_payload(payload_tree, tvb_decrypted, d_offset); + break; + case RELAY_RESOLVED: + d_offset += dissect_relay_resolved_payload(payload_tree, tvb_decrypted, d_offset); + break; + case RELAY_CONNECTED: + d_offset += dissect_relay_connected_payload(payload_tree, tvb_decrypted, d_offset); + break; + case RELAY_END: + d_offset += dissect_relay_end_payload(payload_tree, tvb_decrypted, d_offset); + /*FIXME: Clean up with gcry_md_close (gcry_md_hd_t h) */ + break; + case RELAY_BEGIN: + d_offset += dissect_relay_resolve_payload(payload_tree, tvb_decrypted, d_offset); + break; + case RELAY_TRUNCATED: + d_offset += dissect_destroy_cell(payload_tree, tvb_decrypted, d_offset); + break; + /*This contains a payload requiring subdissection */ + case RELAY_DATA: + first_four = tvb_get_string(tvb_decrypted, d_offset, 4); + if (!memcmp(first_four,"HTTP",4) || + !memcmp(first_four,"GET",3) || + !memcmp(first_four,"POST",4)) { + tmp_handle = http_handle; + } else { + tmp_handle = data_handle; + } + next_tvb = tvb_new_subset(tvb_decrypted, d_offset, data_length, data_length); + call_dissector(tmp_handle, next_tvb, pinfo, payload_tree); + g_free(first_four); + d_offset+=RELAY_DATA_LEN; + break; + /*This contains a payload requiring subdissection */ + case RELAY_ESTABLISH_INTRO: + d_offset += dissect_relay_establish_intro_payload(payload_tree, + tvb_decrypted, d_offset); + break; + case RELAY_ESTABLISH_RENDEZVOUS: + d_offset += dissect_relay_establish_rendezvous_payload(payload_tree, + tvb_decrypted, + d_offset); + break; + case RELAY_INTRODUCE1: + case RELAY_INTRODUCE2: + d_offset += dissect_relay_introduce_payload(payload_tree, + tvb_decrypted, + d_offset); + break; + case RELAY_RENDEZVOUS1: + d_offset += dissect_relay_rendezvous_payload(payload_tree, + tvb_decrypted, + d_offset, TRUE); + break; + case RELAY_RENDEZVOUS2: + d_offset += dissect_relay_rendezvous_payload(payload_tree, + tvb_decrypted, + d_offset, FALSE); + break; + /* These contain no payload */ + case RELAY_TRUNCATE : + case RELAY_DROP : + case RELAY_BEGIN_DIR: + case RELAY_EXTEND : + case RELAY_EXTENDED : + case RELAY_SENDME : + case RELAY_INTRO_ESTABLISHED: + case RELAY_RENDEZVOUS_ESTABLISHED: + case RELAY_COMMAND_INTRODUCE_ACK: + default: + proto_tree_add_item(payload_tree, + hf_tor_relay_data, + tvb_decrypted, d_offset, + RELAY_DATA_LEN, + FALSE); + d_offset+=RELAY_DATA_LEN; + } + + d_offset+=tor_add_padding(payload_tree, tvb_decrypted, d_offset); + + return d_offset; +} + +static void +update_cell_directions(guint circid, packet_info *pinfo, guint direction) +{ + TorService* service; + cell_key_t *tmp_cell_key; + service = g_malloc(sizeof(TorService) + 8); + service->circid = circid; + service->direction = direction; + memset(service->source,0,4); + tmp_cell_key = g_hash_table_lookup(tor_key_hash, service); + if (tmp_cell_key) { + g_hash_table_remove(tor_key_hash, service); + memcpy(service->source, pinfo->src.data, pinfo->src.len); + g_hash_table_insert(tor_key_hash, service, tmp_cell_key); + } +} + +static gint +dissect_create_cell(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + gint start=offset; + proto_tree_add_item(payload_tree, + hf_tor_create, + tvb, offset, + 509, + FALSE); + offset+=509; + + return (offset-start); +} + +static gint +dissect_createfast_cell(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + gint start=offset; + proto_tree_add_item(payload_tree, + hf_tor_key_material_x, + tvb, offset, + HASH_LEN, + FALSE); + offset+=HASH_LEN; + + return (offset-start); +} + +static gint +dissect_createdfast_cell(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + gint start=offset; + proto_tree_add_item(payload_tree, + hf_tor_key_material_y, + tvb, offset, + HASH_LEN, + FALSE); + offset+=HASH_LEN; + + proto_tree_add_item(payload_tree, + hf_tor_derivative_key_data, + tvb, offset, + HASH_LEN, + FALSE); + offset+=HASH_LEN; + + return (offset-start); +} + +static gint +dissect_created_cell(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + gint start=offset; + proto_tree_add_item(payload_tree, + hf_tor_dh_data, + tvb, offset, + DH_LEN, + FALSE); + offset+=DH_LEN; + + proto_tree_add_item(payload_tree, + hf_tor_derivative_key_data, + tvb, offset, + HASH_LEN, + FALSE); + offset+=HASH_LEN; + + return (offset-start); +} + +static gint +dissect_netinfo_cell(proto_tree *payload_tree, tvbuff_t *tvb, gint offset) +{ + gint i, no_of_addresses; + gint start=offset; + proto_tree_add_item(payload_tree, + hf_tor_timestamp, + tvb, offset, + 4, + FALSE); + offset+=4; + + offset+=add_tor_address(payload_tree, tvb, offset,TRUE); + + proto_tree_add_item(payload_tree, + hf_tor_number_of_addresses, + tvb, offset, + 1, + FALSE); + no_of_addresses=tvb_get_guint8(tvb, offset); + offset+=1; + + for (i=0; i < no_of_addresses; i++) { + offset+=add_tor_address(payload_tree, tvb, offset,FALSE); + } + return (offset-start); +} + +static gint +dissect_versions_cell(proto_tree *payload_tree, tvbuff_t *tvb, gint offset, + gint tor_length) +{ + gint i; + proto_tree_add_string_format(payload_tree, + hf_tor_length, + tvb, offset, + 2, + "Length:", "Length: %s", + tvb_bytes_to_str(tvb, offset, 2)); + offset+=2; + for (i=0; icinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "Tor"); + + ti = proto_tree_add_item(tree, proto_tor, tvb, offset, -1, + FALSE); + tor_tree = proto_item_add_subtree(ti, ett_tor); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + while (tvb_offset_exists(tvb, offset)) { + + /*Inspect the packet. if we don't have enough data to dissect it, + request more. */ + tor_circid=(guint)tvb_get_ntohs(tvb, offset); + tor_cmd = tvb_get_guint8(tvb, offset+2); + switch(tor_cmd) { + case NETINFO: + /* TODO: need to calculate length based on no of addresses here */ + required=CELL_LEN; + break; + case VERSIONS: + tor_length=(guint)tvb_get_ntohs(tvb, offset+3); + required=tor_length + 4; + break; + default: + required=CELL_LEN; + } + + available = tvb_reported_length_remaining(tvb, offset); + if (available < required) { + pinfo->desegment_offset = offset; + pinfo->desegment_len = (required-available); + return; + } + + /* + * Put the line into the protocol tree. + */ + + val_str = match_strval(tor_cmd, vals_circuit_commands); + if (check_col(pinfo->cinfo, COL_INFO)) { + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Tor Cell: %s", val_str); + } + + if (!tor_cmd) { + ti=proto_tree_add_item(tor_tree, + hf_tor_padding, + tvb, offset, + (tvb_length_remaining(tvb,offset) > CELL_LEN)? + CELL_LEN:tvb_length_remaining(tvb,offset), + FALSE); + offset+=(tvb_length_remaining(tvb,offset) > CELL_LEN)? + CELL_LEN:tvb_length_remaining(tvb,offset); + continue; + } + + /* + * Add the CircID field + */ + ti=proto_tree_add_item(tor_tree, + hf_tor_circid, + tvb, offset, + 2, + FALSE); + offset+=2; + + /* + * Add the Command field + */ + proto_tree_add_item(tor_tree, + hf_tor_command, + tvb, offset, + 1, + FALSE); + offset+=1; + /* + * Add the Payload + */ + ti = proto_tree_add_item(tor_tree, + hf_tor_payload, + tvb, offset, + 0, + FALSE); + payload_tree = proto_item_add_subtree(ti, ett_tor); + + switch(tor_cmd) { + case VERSIONS: + offset+=dissect_versions_cell(payload_tree, tvb, offset, tor_length); + break; + case NETINFO: + offset+=dissect_netinfo_cell(payload_tree, tvb, offset); + break; + case CREATED: + update_cell_directions(tor_circid, pinfo, REVERSE); + offset+=dissect_created_cell(payload_tree, tvb, offset); + break; + case CREATED_FAST: + update_cell_directions(tor_circid, pinfo, REVERSE); + offset+=dissect_createdfast_cell(payload_tree, tvb, offset); + break; + case CREATE_FAST: + update_cell_directions(tor_circid, pinfo, FORWARD); + offset+=dissect_createfast_cell(payload_tree, tvb, offset); + break; + case CREATE: + update_cell_directions(tor_circid, pinfo, FORWARD); + offset+=dissect_create_cell(payload_tree, tvb, offset); + break; + case DESTROY: + offset+=dissect_destroy_cell(payload_tree, tvb, offset); + break; + case RELAY_EARLY: + case RELAY: + used = dissect_relay_cell(payload_tree, tvb, offset, tor_circid, pinfo); + if (!used) { + proto_tree_add_item(payload_tree, + hf_tor_encrypted_cell, + tvb, offset, + PAYLOAD_LEN, + FALSE); + } + offset+=PAYLOAD_LEN; + break; + default: + break; + } + + offset+=tor_add_padding(tor_tree, tvb, offset); + + } + +} + +void +proto_register_tor(void) +{ + static hf_register_info hf[] = { + { &hf_tor_circid, + { "CircID", "tor.circid", + FT_UINT16, BASE_DEC, NULL, 0x0, + "CircID", HFILL }}, + { &hf_tor_command, + { "Command", "tor.command", + FT_UINT8, BASE_HEX, VALS(vals_circuit_commands), 0x0, + "Command", HFILL }}, + { &hf_tor_length, + { "Length", "tor.length", + FT_STRING, BASE_NONE, NULL, 0x0, + "Length", HFILL }}, + { &hf_tor_payload, + { "Payload", "tor.payload", + FT_STRING, BASE_NONE, NULL, 0x0, + "Payload", HFILL }}, + { &hf_tor_timestamp, + { "Timestamp", "tor.timestamp", + FT_UINT64, BASE_DEC, NULL, 0x0, + "Timestamp", HFILL }}, + { &hf_tor_other_or_address, + { "Other OR's Address", "tor.otheroraddress", + FT_IPv4, BASE_NONE, NULL, 0x0, + "Other OR's Address", HFILL }}, + { &hf_tor_other_or_address_ipv6, + { "Other OR's Address IPv6", "tor.otheroraddress_ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, + "Other OR's Address IPv6", HFILL }}, + { &hf_tor_number_of_addresses, + { "Number of Addresses", "tor.numberofaddresses", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of Addresses", HFILL }}, + { &hf_tor_this_or_address, + { "This OR's Address", "tor.thisoraddress", + FT_IPv4, BASE_NONE, NULL, 0x0, + "This OR's Address", HFILL }}, + { &hf_tor_this_or_address_ipv6, + { "This OR's Address IPv6", "tor.thisoraddress_ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, + "This OR's Address IPv6", HFILL }}, + { &hf_tor_ttl, + { "TTL", "tor.ttl", + FT_UINT64, BASE_DEC, NULL, 0x0, + "TTL", HFILL }}, + { &hf_tor_address_type, + { "Address Type", "tor.addresstype", + FT_UINT8, BASE_HEX, VALS(vals_address_types), 0x0, + "Address Type", HFILL }}, + { &hf_tor_address_length, + { "Address Length", "tor.addresslength", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Address Length", HFILL }}, + { &hf_tor_hostname, + { "Hostname", "tor.hostname", + FT_STRING, BASE_NONE, NULL, 0x0, + "Hostname", HFILL }}, + { &hf_tor_key_material_y, + { "Key Material (Y)", "tor.keymaterialy", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Key Material (Y)", HFILL }}, + { &hf_tor_key_material_x, + { "Key Material (X)", "tor.keymaterialx", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Key Material (X)", HFILL }}, + { &hf_tor_dh_data, + { "Diffie Hellman data", "tor.dhdata", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Diffie Hellman data", HFILL }}, + { &hf_tor_derivative_key_data, + { "Derivative key data", "tor.derivativekeydata", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Derivative key data", HFILL }}, + { &hf_tor_create, + { "Create Payload", "tor.create", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Create Payload", HFILL }}, + { &hf_tor_destroy_reason, + { "Destroy Reason", "tor.destroyreason", + FT_UINT8, BASE_HEX, VALS(vals_destroy_reason), 0x0, + "Destroy Reason", HFILL }}, + { &hf_tor_relay_command, + { "Relay Command", "tor.relay_command", + FT_UINT8, BASE_HEX, VALS(vals_relay_commands), 0x0, + "Relay Command", HFILL }}, + { &hf_tor_recognized, + { "Recognized", "tor.recognized", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Recognized", HFILL }}, + { &hf_tor_streamid, + { "Stream ID", "tor.streamid", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Stream ID", HFILL }}, + { &hf_tor_relay_digest, + { "Digest", "tor.relay_digest", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Digest", HFILL }}, + { &hf_tor_relay_data_length, + { "Relay Data Length", "tor.relay_data_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Relay Data Length", HFILL }}, + { &hf_tor_relay_data, + { "Relay Data", "tor.relay_data", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Relay Data", HFILL }}, + { &hf_tor_encrypted_cell, + { "Encrypted Cell", "tor.encrypted_cell", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Encrypted Cell", HFILL }}, + { &hf_tor_padding, + { "Padding", "tor.padding", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Padding", HFILL }}, + { &hf_tor_relay_connected_ip, + { "Relay Connected IP", "tor.relay_connected_ip", + FT_IPv4, BASE_NONE, NULL, 0x0, + "Relay Connected IP", HFILL }}, + { &hf_tor_relay_connected_ttl, + { "Relay Connected TTL", "tor.relay_connected_ttl", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Relay Connected TTL", HFILL }}, + { &hf_tor_relay_end_reason, + { "Relay End Reason", "tor.relay_end_reason", + FT_UINT8, BASE_HEX, VALS(vals_relay_end_reason), 0x0, + "Relay End Reason", HFILL }}, + { &hf_tor_relay_end_ip, + { "Relay End IP", "tor.relay_end_ip", + FT_IPv4, BASE_NONE, NULL, 0x0, + "Relay End IP", HFILL }}, + { &hf_tor_relay_end_ipv6, + { "Relay End IPv6", "tor.relay_end_ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, + "Relay End IPv6", HFILL }}, + { &hf_tor_relay_end_ttl, + { "Relay End TTL", "tor.relay_end_ttl", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Relay End TTL", HFILL }}, + { &hf_tor_resolved_status, + { "Resolved Status", "tor.resolved_status", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Resolved Status", HFILL }}, + { &hf_tor_resolve_address, + { "Resolve Address", "tor.resolve_address", + FT_STRING, BASE_NONE, NULL, 0x0, + "Resolved Address", HFILL }}, + { &hf_tor_resolve_port, + { "Resolve Port", "tor.resolve_port", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Resolved Port", HFILL }}, + { &hf_tor_establish_intro_kl, + { "Establish Intro Key Length", "tor.establish_intro_kl", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Establish Intro Key Length", HFILL }}, + { &hf_tor_establish_intro_pk, + { "Establish Intro Public Key", "tor.establish_intro_pk", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Establish Intro Public Key", HFILL }}, + { &hf_tor_establish_intro_hs, + { "Establish Intro Session Hash", "tor.establish_intro_hs", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Establish Intro Session Hash", HFILL }}, + { &hf_tor_establish_intro_sig, + { "Establish Intro Signature", "tor.establish_intro_sig", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Establish Intro Signature", HFILL }}, + { &hf_tor_establish_rendezvous_cookie, + { "Establish Rendezvous Cookie", "tor.establish_rendezvous_cookie", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Establish Rendezvous Cookie", HFILL }}, + { &hf_tor_introduce_pk_id, + { "Introduce PK ID", "tor.introduce_pk_id", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Introduce PK ID", HFILL }}, + { &hf_tor_introduce_encrypted_payload, + { "Introduce Encrypted Payload", "tor.introduce_encrypted_payload", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Introduce Encrypted Payload", HFILL }}, + { &hf_tor_rendezvous_cookie, + { "Rendezvous Cookie", "tor.rendezvous_cookie", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Rendezvous Cookie", HFILL }}, + { &hf_tor_rendezvous_dh, + { "Rendezvous Diffie Hellman", "tor.rendezvous_dh", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Rendezvous Diffie Hellman", HFILL }}, + { &hf_tor_rendezvous_hd, + { "Rendezvous Handshake Digest", "tor.rendezvous_hd", + FT_BYTES, BASE_NONE, NULL, 0x0, + "Rendezvous Handshake Digest", HFILL }}, + }; + + static gint *ett[] = { + &ett_tor + }; + module_t *tor_module; + + + proto_tor = proto_register_protocol("Tor Protocol", "Tor", "tor"); + register_dissector("tor", dissect_tor, proto_tor); + proto_register_field_array(proto_tor, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Preferences */ + tor_module = prefs_register_protocol(proto_tor, proto_reg_handoff_tor); + + prefs_register_string_preference(tor_module, "cell_keys_list", "Tor cell keys list", + "Semicolon-separated list of AES keys used for Tor cell decryption; " + "each list entry must be in the form of ,,. " + " is the key used to encrypt cells", + (const gchar **)&cell_keys_list); +} + +void +proto_reg_handoff_tor(void) +{ + dissector_handle_t tor_handle; + + tor_handle = find_dissector("tor"); + ssl_dissector_add(TCP_PORT_SSL_TOR, "tor", TRUE); + data_handle = find_dissector("data"); + http_handle = find_dissector("http"); + tor_parse(); + +} Index: config.sub =================================================================== --- config.sub (revision 33624) +++ config.sub (working copy) @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. -timestamp='2006-09-20' +timestamp='2009-06-11' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -72,8 +72,8 @@ version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -122,6 +122,7 @@ case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` @@ -152,6 +153,9 @@ os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -245,17 +249,20 @@ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ + | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ + | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore \ + | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ @@ -268,6 +275,7 @@ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | moxie \ | mt \ | msp430 \ | nios | nios2 \ @@ -277,7 +285,7 @@ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | score \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -286,7 +294,7 @@ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) + | z8k | z80) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) @@ -324,19 +332,22 @@ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ + | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ @@ -358,21 +369,25 @@ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ + | xstormy16-* | xtensa*-* \ | ymp-* \ - | z8k-*) + | z8k-* | z80-*) ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) @@ -435,6 +450,10 @@ basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; aux) basic_machine=m68k-apple os=-aux @@ -443,10 +462,26 @@ basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; c90) basic_machine=c90-cray os=-unicos ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -475,8 +510,8 @@ basic_machine=craynv-cray os=-unicosmp ;; - cr16c) - basic_machine=cr16c-unknown + cr16) + basic_machine=cr16-unknown os=-elf ;; crds | unos) @@ -514,6 +549,10 @@ basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp @@ -668,6 +707,14 @@ basic_machine=m68k-isi os=-sysv ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -683,6 +730,10 @@ basic_machine=i386-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -809,6 +860,14 @@ basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; @@ -925,6 +984,9 @@ basic_machine=sh-hitachi os=-hms ;; + sh5el) + basic_machine=sh5le-unknown + ;; sh64) basic_machine=sh64-unknown ;; @@ -1014,6 +1076,10 @@ basic_machine=tic6x-unknown os=-coff ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; tx39) basic_machine=mipstx39-unknown ;; @@ -1089,6 +1155,10 @@ basic_machine=z8k-unknown os=-sim ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -1127,7 +1197,7 @@ we32k) basic_machine=we32k-att ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) @@ -1197,10 +1267,11 @@ # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ @@ -1209,7 +1280,7 @@ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ + | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ @@ -1219,7 +1290,7 @@ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1349,6 +1420,9 @@ -zvmoe) os=-zvmoe ;; + -dicos*) + os=-dicos + ;; -none) ;; *) @@ -1414,6 +1488,9 @@ m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; @@ -1543,7 +1620,7 @@ -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*)