├── .github └── workflows │ ├── freebsd.yml │ ├── macos.yml │ ├── openbsd.yml │ ├── ubuntu.yml │ └── windows.yml ├── .gitignore ├── .vimrc ├── CHANGELOG ├── LICENSE ├── Makefile ├── README-android.txt ├── README-win32.txt ├── README.md ├── doc ├── iodine-server.service ├── iodine-server.socket ├── iodine.te ├── proto_00000402.txt ├── proto_00000500.txt └── proto_00000502.txt ├── man └── iodine.8 ├── src ├── Android.16.mk ├── Android.mk ├── Makefile ├── android_dns.h ├── base128.c ├── base32.c ├── base64.c ├── client.c ├── client.h ├── common.c ├── common.h ├── dns.c ├── dns.h ├── encoding.c ├── encoding.h ├── fw_query.c ├── fw_query.h ├── iodine.c ├── iodined.c ├── login.c ├── login.h ├── md5.c ├── md5.h ├── osflags ├── read.c ├── read.h ├── tun.c ├── tun.h ├── user.c ├── user.h ├── util.c ├── util.h ├── version.h └── windows.h └── tests ├── Makefile ├── base32.c ├── base64.c ├── common.c ├── dns.c ├── encoding.c ├── fw_query.c ├── login.c ├── read.c ├── test.c ├── test.h └── user.c /.github/workflows/freebsd.yml: -------------------------------------------------------------------------------- 1 | name: freebsd 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: make 19 | uses: vmactions/freebsd-vm@v1.2.0 20 | with: 21 | prepare: | 22 | pkg install -y \ 23 | devel/check \ 24 | devel/git \ 25 | devel/pkgconf 26 | run: | 27 | make 28 | make test 29 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: macos 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: macos-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: make 20 | run: make 21 | - name: install check 22 | run: brew install check 23 | - name: run tests 24 | run: make test 25 | -------------------------------------------------------------------------------- /.github/workflows/openbsd.yml: -------------------------------------------------------------------------------- 1 | name: openbsd 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: make 19 | uses: vmactions/openbsd-vm@v1.1.8 20 | with: 21 | prepare: | 22 | pkg_add \ 23 | check \ 24 | git \ 25 | pkgconf 26 | run: | 27 | make 28 | make test 29 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: ubuntu 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: make 20 | run: make 21 | - name: install check 22 | run: sudo apt install check 23 | - name: run tests 24 | run: make test 25 | 26 | build-android: 27 | 28 | runs-on: ubuntu-latest 29 | 30 | steps: 31 | - uses: actions/checkout@v4 32 | - uses: nttld/setup-ndk@v1 33 | with: 34 | ndk-version: r21e 35 | - name: make 36 | run: make cross-android 37 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: windows 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: windows-latest 16 | defaults: 17 | run: 18 | shell: msys2 {0} 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - uses: msys2/setup-msys2@v2 23 | with: 24 | msystem: MINGW64 25 | update: false 26 | install: git make mingw-w64-x86_64-toolchain mingw-w64-x86_64-zlib 27 | - name: make 28 | run: make TARGETOS=windows32 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | *.o 3 | /src/base64u.c 4 | /src/base64u.h 5 | /tests/test 6 | *.o.d 7 | /src/obj/local/*/iodine 8 | /src/libs/*/iodine 9 | -------------------------------------------------------------------------------- /.vimrc: -------------------------------------------------------------------------------- 1 | set noexpandtab 2 | set tabstop=8 3 | set softtabstop=8 4 | set shiftwidth=8 5 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2 | iodine - https://code.kryo.se/iodine 3 | 4 | ************************************ 5 | 6 | CHANGES: 7 | 8 | master: 9 | - Changed deprecated tzsetwall() to tzset() (only used by FreeBSD), 10 | patch by Pouria Mousavizadeh Tehrani. 11 | - Now builds on macOS even without if_utun.h (pre 10.6). 12 | 13 | 2023-04-17: 0.8.0 "Burning Snowman" 14 | - Mac OS X: Support native utun VPN devices. Patch by 15 | Peter Sagerson, ported from OpenVPN by Catalin Patulea. 16 | - Fix compilation failure on kFreeBSD and Hurd, by Gregor Herrmann 17 | - Patch from Ryan Welton that fixes compilation warning. 18 | - README converted to markdown by Nicolas Braud-Santoni. 19 | - Linux: use pkg-config for systemd support flags. 20 | Patch by Jason A. Donenfeld. 21 | - Add support for IPv6 in the server. 22 | Raw mode will be with same protocol as used for login. 23 | Traffic inside tunnel is still IPv4. 24 | - Update android build to try to support 5.0 (Lollipop) and newer. 25 | - Change external IP lookup to using myip.opendns.com via DNS. 26 | - Add option to choose IPv4 listen address from external IP lookup. 27 | - Add server support for handling multiple domains via wildcard. 28 | - Recognize tap device component id 'root' prefix on Windows. 29 | 30 | 2014-06-16: 0.7.0 "Kryoptonite" 31 | - Partial IPv6 support (#107) 32 | Client can connect to iodined through an relaying IPv6 33 | nameserver. Server only supports IPv4 for now. 34 | Traffic inside tunnel is IPv4. 35 | - Add socket activation for systemd, by Michael Scherer. 36 | - Add automated lookup of external ip (via -n auto). 37 | - Bugfix for OS X (Can't assign requested address) 38 | - Fix DNS tunneling bug caused by uninitialized variable, #94 39 | - Handle spaces when entering password interactively, fixes #93. 40 | Patch by Hagar. 41 | - Add -R option to set OpenBSD routing domain for the DNS socket. 42 | Patch by laurent at gouloum fr, fixes #95. 43 | - Add android patches and makefile, from Marcel Bokhorst, fixes #105. 44 | - Added missing break in iodine.c, by Pavel Pergamenshchik, #108. 45 | - A number of minor patches from Frank Denis, Gregor Herrmann and 46 | Barak A. Pearlmutter. 47 | - Testcase compilation fixes for OS X and FreeBSD 48 | - Do not let sockets be inherited by sub-processes, fixes #99. 49 | - Add unspecified RR type (called PRIVATE; id 65399, in private use 50 | range). For servers with RFC3597 support. Fixes #97. 51 | - Fix authentication bypass vulnerability; found by Oscar Reparaz. 52 | 53 | 2010-02-06: 0.6.0-rc1 "Hotspotify" 54 | - Fixed tunnel not working on Windows. 55 | - Any device name is now supported on Windows, fixes #47. 56 | - Multiple installed TAP32 interfaces are now supported, fixes #46. 57 | - Return nonzero if tunnel fails to open, fixes #62. 58 | - Support for setting a SELinux context, based on patch by 59 | Sebastien Raveau. Sample context file in doc/iodine.te 60 | - Allow listen port and DNS forward port to be the same if listen IP 61 | does not include localhost. 62 | - The client will now exit if configuring IP or MTU fails. 63 | - The starting cache miss value is randomized at startup, fixes #65. 64 | - Raw UDP mode added. If the iodined server is reachable directly, 65 | packets can be sent to it without DNS encoding. Fixes #36. 66 | - Do not overwrite users CC/CFLAGS/LDFLAGS, only add to them. 67 | - Added -F option to write pidfile, based on patch from 68 | misc at mandriva.org. Fixes #70. 69 | - Allow password to be set via environment variable, fixes #77. 70 | Based on patch by logix. 71 | - Client now prints server tunnel IP, fixes #78. Patch by logix. 72 | - Fix build error on Mac OS X 10.6, patch by G. Rischard. #79. 73 | - Added support for CNAME/TXT/A/MX query types, fixes #75. 74 | Patch by Anne Bezemer, merge help by logix. 75 | - Merged low-latency patch from Anne Bezemer, fixes #76. 76 | - Resolve client nameserver argument if given as hostname, fixes #82. 77 | - Open log before chroot, fixes #86: logging on FreeBSD. 78 | - Merged big bugfix patch from Anne Bezemer, #88. 79 | 80 | 2009-06-01: 0.5.2 "WifiFree" 81 | - Fixed client segfault on OS X, #57 82 | - Added check that nameserver lookup was successful 83 | - Fixed ENOTSOCK error on OS X and FreeBSD, #58. 84 | 85 | 2009-03-21: 0.5.1 "Boringo" 86 | - Added initial Windows support, fixes #43. 87 | - Added length check of autoprobe responses 88 | - Refactored and added unit tests 89 | - Added syslog logging for iodined on version and login packets 90 | - Fixed segfault when encoding just one block, fixes #51. 91 | The normal code was never affected by this. 92 | - Added win32 code to read DNS server from system, fixes #45. 93 | - Disabled password echo on win32, fixes #44. 94 | - Fix encoding error making all autoprobing > 1024 bytes fail, #52. 95 | - Increase default interface MTU to 1200. 96 | - Fix autoprobing error making every third probe fail, set IP flag 97 | Dont-Fragment where supported. Fixes #54. 98 | - Added TAP32 version 0901 as accepted (#53). 99 | 100 | 2009-01-23: 0.5.0 "iPassed" 101 | - Fixed segfault in server when sending version reject. 102 | - Applied patch to make iodine build on BeOS R5-BONE and Haiku, 103 | from Francois Revol. Still work to do to get tun device working. 104 | - Added capability to forward DNS queries outside tunnel domain to 105 | a nameserver on localhost. Use -b port to enable, fixes #31. 106 | - iodined now replies to NS request on its own domain, fixes issue #33. 107 | The destination IP address is sent as reply. Use -n to specify 108 | a specific IP address to return (if behind NAT etc). 109 | - Upstream data is now Base64 encoded if relay server preserves case and 110 | supports the plus (+) character in domain names, fixes #16. 111 | - Fixed problem in client when DNS trans. ID has highest bit set (#37) 112 | - IP addresses are now assigned within the netmask, so iodined can 113 | use any address for itself, fixes #28. 114 | - Netmask size is now adjustable. Setting a small net will reduce the 115 | number of users. Use x.x.x.x/n notation on iodined tunnel ip. 116 | This fixes #27. 117 | - Downstream data is now fragmented, and the fragment size is auto- 118 | probed after login. Fixes #7. It only took a few years :) 119 | - Enhanced the checks that validates incoming packets 120 | - Fixed endless loop in fragment size autodetection, #39. 121 | - Fixed broken hostname dot placing with specific lengths, #40. 122 | 123 | 2008-08-06: 0.4.2 "Opened Zone" 124 | - Applied a few small patches from Maxim Bourmistrov and Gregor Herrmann 125 | - Applied a patch for not creating and configuring the tun interface, 126 | Debian bug #477692 by Vincent Bernat, controlled by -s switch 127 | - Applied a security patch from Andrew Griffiths, use setgroups() to 128 | limit the groups of the user 129 | - Applied a patch to make iodine build on (Open)Solaris, from Albert Lee 130 | Needs TUN/TAP driver http://www.whiteboard.ne.jp/~admin2/tuntap/ 131 | Still needs more code in tun.c for opening/closing the device 132 | - Added option in server (-c) to disable IP/port checking on packets, 133 | will hopefully help when server is behind NAT 134 | - Fixed bug #21, now only IP address part of each packet is checked. 135 | Should remove the need for the -c option and also work with 136 | bugfixed DNS servers worldwide. 137 | - Added -D option on server to enable debugging. Debug level 1 now 138 | prints info about each RX/TX datagram. 139 | 140 | 2007-11-30: 0.4.1 "Tea Online" 141 | - Introduced encoding API 142 | - Switched to new Base32 implementation 143 | - Added Base64 implementation that only uses 63 chars (not used yet) 144 | - Refined 'install' make target and use $(MAKE) for recursive calls 145 | - All received error messages (RCODE field) are echoed 146 | - Top domain limited to 128 chars 147 | - Case preservation check sent after login to decide codec 148 | - Fixed crash on incoming NULL query in server with bad top domain 149 | - /etc/resolv.conf is consulted if no nameserver is given on commandline 150 | - Applied patch from Matthew W. S. Bell (Detach before chroot/dropping priv) 151 | 152 | 2007-03-25: 0.4.0 "Run Home" 153 | - Added multiuser support (up to 8 users simultaneously) 154 | - Added authentication (password entered as argument or on stdin) 155 | - Added manpage 156 | - Added install/uninstall make target 157 | - Cleanup of dns code, more test cases, use check library 158 | - Changed directory structure 159 | 160 | 2006-11-08: 0.3.4 161 | - Fixed handshake() buffer overflow 162 | (Found by poplix, Secunia: SA22674 / FrSIRT/ADV-2006-4333) 163 | - Added more tests 164 | - More name parsing enhancements 165 | - Now runs on Linux/AMD64 166 | - Added setting to change server port 167 | 168 | 2006-11-05: 0.3.3 169 | - Fixed possible buffer overflow 170 | (Found by poplix, Bugtraq ID: 20883) 171 | - Reworked dns hostname encoding 172 | 173 | 2006-09-11: 0.3.2 174 | - Support for NetBSD 175 | - Fixed potential security problems 176 | - Name parsing routines rewritten, added regression tests 177 | - New encoding, 25% more peak upstream throughput 178 | - New -l option to set local ip to listen to on server 179 | 180 | 2006-07-11: 0.3.1 181 | - Add Mac OSX support 182 | - Add setting device name 183 | - Use compression of domain name in reply (should allow setting MTU 184 | approx 200 bytes higher) 185 | 186 | 2006-06-24: 0.3.0 187 | - First public release 188 | - Support for Linux, FreeBSD, OpenBSD 189 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006-2020 iodine authors 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose 4 | with or without fee is hereby granted, provided that the above copyright notice 5 | and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 9 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | prefix?=/usr/local 2 | sbindir=$(prefix)/sbin 3 | datadir=$(prefix)/share 4 | mandir=$(datadir)/man 5 | docdir=$(datadir)/doc 6 | 7 | DESTDIR= 8 | 9 | INSTALL=install 10 | INSTALL_FLAGS= 11 | 12 | MKDIR=mkdir 13 | MKDIR_FLAGS=-p 14 | 15 | RM=rm 16 | RM_FLAGS=-f 17 | 18 | TARGETOS = `uname` 19 | 20 | all: 21 | @$(MAKE) -C src TARGETOS=$(TARGETOS) all 22 | 23 | install: all 24 | $(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(sbindir) 25 | $(INSTALL) $(INSTALL_FLAGS) bin/iodine $(DESTDIR)$(sbindir)/iodine 26 | chmod 755 $(DESTDIR)$(sbindir)/iodine 27 | $(INSTALL) $(INSTALL_FLAGS) bin/iodined $(DESTDIR)$(sbindir)/iodined 28 | chmod 755 $(DESTDIR)$(sbindir)/iodined 29 | $(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(mandir)/man8 30 | $(INSTALL) $(INSTALL_FLAGS) man/iodine.8 $(DESTDIR)$(mandir)/man8/iodine.8 31 | chmod 644 $(DESTDIR)$(mandir)/man8/iodine.8 32 | $(MKDIR) $(MKDIR_FLAGS) $(DESTDIR)$(docdir)/iodine 33 | $(INSTALL) $(INSTALL_FLAGS) README.md $(DESTDIR)$(docdir)/iodine/README.md 34 | chmod 644 $(DESTDIR)$(docdir)/iodine/README.md 35 | 36 | uninstall: 37 | $(RM) $(RM_FLAGS) $(DESTDIR)$(sbindir)/iodine 38 | $(RM) $(RM_FLAGS) $(DESTDIR)$(sbindir)/iodined 39 | $(RM) $(RM_FLAGS) $(DESTDIR)$(mandir)/man8/iodine.8 40 | 41 | test: all 42 | @echo "!! The check library is required for compiling and running the tests" 43 | @echo "!! Get it at https://libcheck.github.io/check/" 44 | @$(MAKE) -C tests TARGETOS=$(TARGETOS) all 45 | 46 | clean: 47 | @echo "Cleaning..." 48 | @$(MAKE) -C src clean 49 | @$(MAKE) -C tests clean 50 | @rm -rf bin iodine-latest* 51 | 52 | #Helper target for windows/android zipfiles 53 | iodine-latest: 54 | @rm -rf iodine-latest* 55 | @mkdir -p iodine-latest 56 | @echo "Create date: " > iodine-latest/VERSION.txt 57 | @LANG=en_US date >> iodine-latest/VERSION.txt 58 | @echo "Git version: " >> iodine-latest/VERSION.txt 59 | @git rev-parse HEAD >> iodine-latest/VERSION.txt 60 | @for i in README.md CHANGELOG; do cp $$i iodine-latest/$$i.txt; done 61 | @unix2dos iodine-latest/* 62 | 63 | #non-PIE build for old android 64 | cross-android-old: 65 | @$(MAKE) -C src base64u.c 66 | @(cd src && ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk APP_PLATFORM=android-3) 67 | 68 | #Position-indepedent build for modern android 69 | cross-android: 70 | @$(MAKE) -C src base64u.c 71 | @(cd src && ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.16.mk APP_PLATFORM=android-16) 72 | 73 | iodine-latest-android.zip: iodine-latest 74 | @mv iodine-latest iodine-latest-android 75 | @mkdir -p iodine-latest-android/pre-kitkat/armeabi 76 | @mkdir -p iodine-latest-android/pre-kitkat/x86 77 | @$(MAKE) cross-android-old TARGET_ARCH_ABI=armeabi 78 | @cp src/libs/armeabi/* iodine-latest-android/pre-kitkat/armeabi 79 | @$(MAKE) cross-android-old TARGET_ARCH_ABI=x86 80 | @cp src/libs/x86/* iodine-latest-android/pre-kitkat/x86 81 | @rm -rf src/libs src/obj 82 | @mkdir -p iodine-latest-android/armeabi 83 | @mkdir -p iodine-latest-android/arm64-v8a 84 | @mkdir -p iodine-latest-android/x86 85 | @$(MAKE) cross-android TARGET_ARCH_ABI=armeabi 86 | @cp src/libs/armeabi/* iodine-latest-android/armeabi 87 | @$(MAKE) cross-android TARGET_ARCH_ABI=arm64-v8a 88 | @cp src/libs/arm64-v8a/* iodine-latest-android/arm64-v8a 89 | @$(MAKE) cross-android TARGET_ARCH_ABI=x86 90 | @cp src/libs/x86/* iodine-latest-android/x86 91 | @cp README-android.txt iodine-latest-android 92 | @zip -r iodine-latest-android.zip iodine-latest-android 93 | 94 | cross-mingw32: 95 | @$(MAKE) -C src TARGETOS=windows32 CC=i686-w64-mingw32-gcc all 96 | 97 | cross-mingw64: 98 | @$(MAKE) -C src TARGETOS=windows32 CC=x86_64-w64-mingw32-gcc all 99 | 100 | iodine-latest-windows.zip: iodine-latest 101 | @mv iodine-latest iodine-latest-windows 102 | @mkdir -p iodine-latest-windows/64bit iodine-latest-windows/32bit 103 | @$(MAKE) -C src TARGETOS=windows32 CC=i686-w64-mingw32-gcc clean all 104 | @i686-w64-mingw32-strip bin/iodine* 105 | @for i in `ls bin`; do cp bin/$$i iodine-latest-windows/32bit/$$i.exe; done 106 | @cp /usr/i686-w64-mingw32/sys-root/mingw/bin/zlib1.dll iodine-latest-windows/32bit 107 | @$(MAKE) -C src TARGETOS=windows32 CC=x86_64-w64-mingw32-gcc clean all 108 | @x86_64-w64-mingw32-strip bin/iodine* 109 | @for i in `ls bin`; do cp bin/$$i iodine-latest-windows/64bit/$$i.exe; done 110 | @cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/zlib1.dll iodine-latest-windows/64bit 111 | @cp README-win32.txt iodine-latest-windows 112 | @zip -r iodine-latest-windows.zip iodine-latest-windows 113 | 114 | -------------------------------------------------------------------------------- /README-android.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | iodine - https://code.kryo.se/iodine 4 | 5 | *********************************** 6 | 7 | Extra README file for Android 8 | 9 | 10 | == Running iodine on Android: 11 | 1. Get root access on your android device 12 | 13 | 2. Find/build a compatible tun.ko for your specific Android kernel 14 | 15 | 3. Copy tun.ko and the iodine binary to your device: 16 | (Almost all devices need the armeabi binary. Only Intel powered 17 | ones need the x86 build.) 18 | 19 | adb push tun.ko /data/local/tmp 20 | adb push iodine /data/local/tmp 21 | adb shell 22 | su 23 | cd /data/local/tmp 24 | chmod 777 iodine 25 | 26 | 4. Run iodine (see the man page for parameters) 27 | 28 | ./iodine ... 29 | 30 | For more information: http://blog.bokhorst.biz/5123 31 | 32 | == Building iodine for Android: 33 | 1. Download and install the Android SDK and NDK 34 | 35 | 2. Download and unpack the iodine sources 36 | 37 | 3. Build: 38 | cd src 39 | make base64u.h base64u.c 40 | ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.16.mk APP_PLATFORM=android-16 41 | 42 | or run "make cross-android" in the iodine root directory. 43 | To build for other archs, specify TARGET_ARCH_ABI: 44 | "make cross-android TARGET_ARCH_ABI=x86" 45 | 46 | For older android versions (pre-kitkat), build with "make cross-android-old" in the 47 | root directory, or manually like above but with APP_PLATFORM=android-3 and with 48 | APP_BUILD_SCRIPT=Android.mk 49 | 50 | The iodine binary ends up in src/libs//iodine 51 | -------------------------------------------------------------------------------- /README-win32.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | iodine - https://code.kryo.se/iodine 4 | 5 | *********************************** 6 | 7 | Extra README file for Win32 related stuff 8 | 9 | 10 | == Running iodine on Windows: 11 | 12 | 0. After iodine 0.6, you need Windows XP or newer to run. 13 | 14 | 1. Install the TAP driver 15 | https://openvpn.net/index.php/open-source/downloads.html 16 | Download the OpenVPN TAP driver (under section Tap-windows) 17 | Problems has been reported with the NDIS6 version (9.2x.y), use the 18 | NDIS5 version for now if possible. 19 | 20 | 2. Have at least one TAP32 interface installed. There are scripts for adding 21 | and removing in the OpenVPN bin directory. If you have more than one 22 | installed, use -d to specify which. Use double quotes if you have spaces, 23 | example: iodine.exe -d "Local Area Connection 4" abc.ab 24 | 25 | 3. Make sure the interface you want to use does not have a default gateway set. 26 | 27 | 4. Run iodine/iodined as normal (see the main README file). 28 | You may have to run it as administrator depending on user privileges. 29 | 30 | 5. Enjoy! 31 | 32 | 33 | == Building on Windows: 34 | You need: 35 | MinGW, MSYS, GCC, zlib 36 | 37 | Then just run make 38 | 39 | 40 | == Cross-compiling for MinGW: 41 | You need: 42 | MinGW crosscompiler, crosscompiled zlib 43 | 44 | Then run "make cross-mingw" 45 | Note that the binaries will not get a .exe suffix 46 | 47 | 48 | == Zlib download 49 | You can get zlib for MinGW here (both for native and crosscompile): 50 | https://code.kryo.se/iodine/deps/zlib.zip 51 | Unzip it in your MinGW directory on Windows or in $ROOT/usr for 52 | cross-compile. 53 | 54 | 55 | == Results of crappy Win32 API: 56 | The following fixable limitations apply: 57 | - Server cannot read packet destination address 58 | 59 | The following (probably) un-fixable limitations apply: 60 | - A password entered as -P argument can be shown in process list 61 | - Priviligies cannot be dropped 62 | - chroot() cannot be used 63 | - Detaching from terminal not possible 64 | - Server on windows must be run with /30 netmask 65 | - Client can only talk to server, not other clients 66 | 67 | -------------------------------------------------------------------------------- /doc/iodine-server.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Iodine Server 3 | After=local-fs.target network.target 4 | 5 | [Service] 6 | EnvironmentFile=-/etc/sysconfig/iodine-server 7 | ExecStart=/usr/local/bin/iodined -i 30 -f $OPTIONS 8 | StandardOutput=syslog 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /doc/iodine-server.socket: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Iodine socket 3 | 4 | [Socket] 5 | ListenDatagram=53 6 | ListenDatagram=0.0.0.0:53 7 | BindIPv6Only=ipv6-only 8 | 9 | [Install] 10 | WantedBy=sockets.target 11 | -------------------------------------------------------------------------------- /doc/iodine.te: -------------------------------------------------------------------------------- 1 | # Sample post-initialization SELinux policy for Iodine 2 | policy_module(iodine, 1.1) 3 | 4 | require { 5 | type init_t; 6 | type initrc_t; 7 | type unconfined_t; 8 | type unlabeled_t; 9 | class udp_socket { read write }; 10 | class rawip_socket { write read }; 11 | class association recvfrom; 12 | class unix_dgram_socket { create connect }; 13 | } 14 | 15 | type iodine_t; 16 | domain_type(iodine_t) 17 | domain_dyntrans_type(initrc_t) 18 | allow initrc_t iodine_t:process dyntransition; 19 | 20 | allow iodine_t unconfined_t:udp_socket { read write }; 21 | allow iodine_t unconfined_t:rawip_socket { write read }; 22 | allow iodine_t unlabeled_t:association recvfrom; 23 | allow iodine_t self:unix_dgram_socket { create connect }; 24 | corenet_raw_receive_generic_node(iodine_t) 25 | corenet_rw_tun_tap_dev(iodine_t) 26 | -------------------------------------------------------------------------------- /doc/proto_00000402.txt: -------------------------------------------------------------------------------- 1 | Detailed specification of protocol in version 00000402 2 | ====================================================== 3 | 4 | CMC = 2 byte Cache Miss Counter, increased every time it is used 5 | 6 | Version: 7 | Client sends: 8 | First byte v or V 9 | Rest encoded with base32: 10 | 4 bytes big endian protocol version 11 | CMC 12 | Server replies: 13 | 4 chars: 14 | VACK (version ok), followed by login challenge 15 | VNAK (version differs), followed by server protocol version 16 | VFUL (server has no free slots), followed by max users 17 | 4 byte value: means login challenge/server protocol version/max users 18 | 1 byte userid of the new user, or any byte if not VACK 19 | 20 | Login: 21 | Client sends: 22 | First byte l or L 23 | Rest encoded with base32: 24 | 1 byte userid 25 | 16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge) 26 | CMC 27 | Server replies: 28 | LNAK means not accepted 29 | x.x.x.x-y.y.y.y-mtu means accepted (server ip, client ip, mtu) 30 | 31 | Case check: 32 | Client sends: 33 | First byte z or Z 34 | Lots of data that should not be decoded 35 | Server replies: 36 | The requested domain copied raw 37 | 38 | Data: 39 | Data header: 40 | 321 0 41 | +---+-+ 42 | |UUU|L| 43 | +---+-+ 44 | 45 | UUU = Userid 46 | L = Last fragment in packet flag 47 | 48 | First byte is the header, 4 bits coded as hex in ASCII. 49 | Followed by data encoded with Base32. 50 | 51 | Ping: 52 | Client sends: 53 | First byte p or P 54 | Rest encoded with Base32: 55 | 1 byte userid 56 | CMC 57 | 58 | The server response to Ping and Data packets is a DNS NULL type response: 59 | If server has nothing to send, data length is 0 bytes. 60 | If server has a packet to send, data length is set and the data is a full raw 61 | unencoded ip packet, prefixed with 32 bits tun data. 62 | -------------------------------------------------------------------------------- /doc/proto_00000500.txt: -------------------------------------------------------------------------------- 1 | Detailed specification of protocol in version 00000500 2 | ====================================================== 3 | 4 | CMC = 2 byte Cache Miss Counter, increased every time it is used 5 | 6 | Version: 7 | Client sends: 8 | First byte v or V 9 | Rest encoded with base32: 10 | 4 bytes big endian protocol version 11 | CMC 12 | Server replies: 13 | 4 chars: 14 | VACK (version ok), followed by login challenge 15 | VNAK (version differs), followed by server protocol version 16 | VFUL (server has no free slots), followed by max users 17 | 4 byte value: means login challenge/server protocol version/max users 18 | 1 byte userid of the new user, or any byte if not VACK 19 | 20 | Login: 21 | Client sends: 22 | First byte l or L 23 | Rest encoded with base32: 24 | 1 byte userid 25 | 16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge) 26 | CMC 27 | Server replies: 28 | LNAK means not accepted 29 | x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits) 30 | 31 | Case check: 32 | Client sends: 33 | First byte z or Z 34 | Lots of data that should not be decoded 35 | Server replies: 36 | The requested domain copied raw 37 | 38 | Switch codec: 39 | Client sends: 40 | First byte s or S 41 | 5 bits coded as Base32 char, meaning userid 42 | 5 bits coded as Base32 char, with value 5 or 6, representing number of raw 43 | bits per encoded byte 44 | Server sends: 45 | Name of codec if accepted. After this all upstream data packets must 46 | be encoded with the new codec. 47 | BADCODEC if not accepted. Client must then revert to Base32 48 | 49 | Probe downstream fragment size: 50 | Client sends: 51 | First byte r or R 52 | 15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF 53 | meaning 4 bits userid, 11 bits fragment size 54 | Then follows a long random query which contents does not matter 55 | Server sends: 56 | Requested number of bytes as a response. The first two bytes contains 57 | the requested length. Rest of message can be any data. 58 | BADFRAG if requested length not accepted. 59 | 60 | Set downstream fragment size: 61 | Client sends: 62 | First byte n or N 63 | Rest encoded with base32: 64 | 1 byte userid 65 | 2 bytes new downstream fragment size 66 | CMC 67 | Server sends: 68 | 2 bytes new downstream fragment size. After this all downstream 69 | payloads will be max (fragsize + 2) bytes long. 70 | BADFRAG if not accepted. 71 | 72 | Data: 73 | Upstream data header: 74 | 3210 432 10 43 210 4321 0 75 | +----+---+--+--+---+----+-+ 76 | |UUUU|SSS|FF|FF|DDD|GGGG|L| 77 | +----+---+--+--+---+----+-+ 78 | 79 | Downstream data header: 80 | 7 654 3210 765 4321 0 81 | +-+---+----+---+----+-+ 82 | |C|SSS|FFFF|DDD|GGGG|L| 83 | +-+---+----+---+----+-+ 84 | 85 | UUUU = Userid 86 | L = Last fragment in packet flag 87 | SS = Upstream packet sequence number 88 | FFFF = Upstream fragment number 89 | DDD = Downstream packet sequence number 90 | GGGG = Downstream fragment number 91 | C = Compression enabled for downstream packet 92 | 93 | Upstream data packet starts with 1 byte ASCII hex coded user byte, then 3 bytes 94 | Base32 encoded header, then comes the payload data, encoded with chosen codec. 95 | 96 | Downstream data starts with 2 byte header. Then payload data, which may be 97 | compressed. 98 | 99 | Ping: 100 | Client sends: 101 | First byte p or P 102 | Rest encoded with Base32: 103 | 1 byte with 4 bits userid 104 | 1 byte with: 105 | 3 bits downstream seqno 106 | 4 bits downstream fragment 107 | CMC 108 | 109 | The server response to Ping and Data packets is a DNS NULL type response: 110 | If server has nothing to send, data length is 0 bytes. 111 | If server has something to send, it will send a downstream data packet, 112 | prefixed with 2 bytes header as shown above. 113 | -------------------------------------------------------------------------------- /doc/proto_00000502.txt: -------------------------------------------------------------------------------- 1 | Detailed specification of protocol in version 00000502 2 | ====================================================== 3 | 4 | Note: work in progress!! 5 | 6 | ====================================================== 7 | 1. DNS protocol 8 | ====================================================== 9 | 10 | Quick alphabetical index / register: 11 | 0-9 Data packet 12 | A-F Data packet 13 | I IP address 14 | L Login 15 | N Downstream fragsize (NS.topdomain A-type reply) 16 | O Options 17 | P Ping 18 | R Downstream fragsize probe 19 | S Switch upstream codec 20 | V Version 21 | W (WWW.topdomain A-type reply) 22 | Y Downstream codec check 23 | Z Upstream codec check 24 | 25 | 26 | CMC = 2 byte Cache Miss Counter, increased every time it is used 27 | 28 | Version: 29 | Client sends: 30 | First byte v or V 31 | Rest encoded with base32: 32 | 4 bytes big endian protocol version 33 | CMC 34 | Server replies: 35 | 4 chars: 36 | VACK (version ok), followed by login challenge 37 | VNAK (version differs), followed by server protocol version 38 | VFUL (server has no free slots), followed by max users 39 | 4 byte value: means login challenge/server protocol version/max users 40 | 1 byte userid of the new user, or any byte if not VACK 41 | 42 | Login: 43 | Client sends: 44 | First byte l or L 45 | Rest encoded with base32: 46 | 1 byte userid 47 | 16 bytes MD5 hash of: (first 32 bytes of password) xor (8 repetitions of login challenge) 48 | CMC 49 | Server replies: 50 | LNAK means not accepted 51 | x.x.x.x-y.y.y.y-mtu-netmask means accepted (server ip, client ip, mtu, netmask bits) 52 | 53 | IP Request: (for where to try raw login) 54 | Client sends: 55 | First byte i or I 56 | 5 bits coded as Base32 char, meaning userid 57 | CMC as 3 Base32 chars 58 | Server replies 59 | BADIP if bad userid 60 | First byte I 61 | Then comes external IP address of iodined server 62 | as 4 bytes (IPv4) or 16 bytes (IPv6) 63 | 64 | Upstream codec check / bounce: 65 | Client sends: 66 | First byte z or Z 67 | Lots of data that should not be decoded 68 | Server replies: 69 | The requested domain copied raw, in the lowest-grade downstream codec 70 | available for the request type. 71 | 72 | Downstream codec check: 73 | Client sends: 74 | First byte y or Y 75 | 1 char, meaning downstream codec to use 76 | 5 bits coded as Base32 char, meaning check variant 77 | CMC as 3 Base32 chars 78 | Possibly extra data, depending on check variant 79 | Server sends: 80 | Data encoded with requested downstream codec; data content depending 81 | on check variant number. 82 | BADCODEC if requested downstream codec not available. 83 | BADLEN if check variant is not available, or problem with extra data. 84 | 85 | Downstream codec chars are same as in 'O' Option request, below. 86 | 87 | Check variants: 88 | 1: Send encoded DOWNCODECCHECK1 string as defined in encoding.h 89 | 90 | (Other variants reserved; possibly variant that sends a decoded-encoded 91 | copy of Base32-encoded extra data in the request) 92 | 93 | Switch codec: 94 | Client sends: 95 | First byte s or S 96 | 5 bits coded as Base32 char, meaning userid 97 | 5 bits coded as Base32 char, representing number of raw bits per 98 | encoded byte: 99 | 5: Base32 (a-z0-5) 100 | 6: Base64 (a-zA-Z0-9+-) 101 | 26: Base64u (a-zA-Z0-9_-) 102 | 7: Base128 (a-zA-Z0-9\274-\375) 103 | CMC as 3 Base32 chars 104 | Server sends: 105 | Name of codec if accepted. After this all upstream data packets must 106 | be encoded with the new codec. 107 | BADCODEC if not accepted. Client must then revert to previous codec 108 | BADLEN if length of query is too short 109 | 110 | Options: 111 | Client sends: 112 | First byte o or O 113 | 5 bits coded as Base32 char, meaning userid 114 | 1 char, meaning option 115 | CMC as 3 Base32 chars 116 | Server sends: 117 | Full name of option if accepted. After this, option immediately takes 118 | effect in server. 119 | BADCODEC if not accepted. Previous situation remains. 120 | All options affect only the requesting client. 121 | 122 | Option chars: 123 | t or T: Downstream encoding Base32, for TXT/CNAME/A/MX (default) 124 | s or S: Downstream encoding Base64, for TXT/CNAME/A/MX 125 | u or U: Downstream encoding Base64u, for TXT/CNAME/A/MX 126 | v or V: Downstream encoding Base128, for TXT/CNAME/A/MX 127 | r or R: Downstream encoding Raw, for PRIVATE/TXT/NULL (default for 128 | PRIVATE and NULL) 129 | If codec unsupported for request type, server will use Base32; note 130 | that server will answer any mix of request types that a client sends. 131 | Server may disregard this option; client must always use the downstream 132 | encoding type indicated in every downstream DNS packet. 133 | 134 | l or L: Lazy mode, server will keep one request unanswered until the 135 | next one comes in. Applies only to data transfer; handshake is always 136 | answered immediately. 137 | i or I: Immediate (non-lazy) mode, server will answer all requests 138 | (nearly) immediately. 139 | 140 | Probe downstream fragment size: 141 | Client sends: 142 | First byte r or R 143 | 15 bits coded as 3 Base32 chars: UUUUF FFFFF FFFFF 144 | meaning 4 bits userid, 11 bits fragment size 145 | Then follows a long random query which contents does not matter 146 | Server sends: 147 | Requested number of bytes as a response. The first two bytes contain 148 | the requested length. The third byte is 107 (0x6B). The fourth byte 149 | is a random value, and each following byte is incremented with 107. 150 | This is checked by the client to determine corruption. 151 | BADFRAG if requested length not accepted. 152 | 153 | Set downstream fragment size: 154 | Client sends: 155 | First byte n or N 156 | Rest encoded with base32: 157 | 1 byte userid 158 | 2 bytes new downstream fragment size 159 | CMC 160 | Server sends: 161 | 2 bytes new downstream fragment size. After this all downstream 162 | payloads will be max (fragsize + 2) bytes long. 163 | BADFRAG if not accepted. 164 | 165 | Data: 166 | Upstream data header: 167 | 3210 432 10 43 210 4321 0 43210 168 | +----+---+--+--+---+----+-+-----+ 169 | |UUUU|SSS|FF|FF|DDD|GGGG|L|UDCMC| 170 | +----+---+--+--+---+----+-+-----+ 171 | 172 | Downstream data header: 173 | 7 654 3210 765 4321 0 174 | +-+---+----+---+----+-+ 175 | |C|SSS|FFFF|DDD|GGGG|L| 176 | +-+---+----+---+----+-+ 177 | 178 | UUUU = Userid 179 | L = Last fragment in packet flag 180 | SS = Upstream packet sequence number 181 | FFFF = Upstream fragment number 182 | DDD = Downstream packet sequence number 183 | GGGG = Downstream fragment number 184 | C = Compression enabled for downstream packet 185 | UDCMC = Upstream Data CMC, 36 steps a-z0-9, case-insensitive 186 | 187 | Upstream data packet starts with 1 byte ASCII hex coded user byte; then 3 bytes 188 | Base32 encoded header; then 1 char data-CMC; then comes the payload data, 189 | encoded with the chosen upstream codec. 190 | 191 | Downstream data starts with 2 byte header. Then payload data, which may be 192 | compressed. 193 | 194 | In NULL and PRIVATE responses, downstream data is always raw. In all other 195 | response types, downstream data is encoded (see Options above). 196 | Encoding type is indicated by 1 prefix char: 197 | TXT: 198 | End result is always DNS-chopped (series of len-prefixed strings 199 | <=255 bytes) 200 | t or T: Base32 encoded before chop, decoded after un-chop 201 | s or S: Base64 encoded before chop, decoded after un-chop 202 | u or U: Base64u encoded before chop, decoded after un-chop 203 | v or V: Base128 encoded before chop, decoded after un-chop 204 | r or R: Raw no encoding, only DNS-chop 205 | SRV/MX/CNAME/A: 206 | h or H: Hostname encoded with Base32 207 | i or I: Hostname encoded with Base64 208 | j or J: Hostname encoded with Base64u 209 | k or K: Hostname encoded with Base128 210 | SRV and MX may reply with multiple hostnames, each encoded separately. Each 211 | has a 10-multiple priority, and encoding/decoding is done in strictly 212 | increasing priority sequence 10, 20, 30, etc. without gaps. Note that some DNS 213 | relays will shuffle the answer records in the response. 214 | 215 | Ping: 216 | Client sends: 217 | First byte p or P 218 | Rest encoded with Base32: 219 | 1 byte with 4 bits userid 220 | 1 byte with: 221 | 3 bits downstream seqno 222 | 4 bits downstream fragment 223 | CMC 224 | 225 | The server response to Ping and Data packets is a DNS NULL/TXT/.. type response, 226 | always starting with the 2 bytes downstream data header as shown above. 227 | If server has nothing to send, no data is added after the header. 228 | If server has something to send, it will add the downstream data packet 229 | (or some fragment of it) after the header. 230 | 231 | 232 | "Lazy-mode" operation 233 | ===================== 234 | 235 | Client-server DNS traffic sequence has been reordered to provide increased 236 | (interactive) performance and greatly reduced latency. 237 | 238 | Idea taken from Lucas Nussbaum's slides (24th IFIP International Security 239 | Conference, 2009) at http://www.loria.fr/~lnussbau/tuns.html. Current 240 | implementation is original to iodine, no code or documentation from any other 241 | project was consulted during development. 242 | 243 | Server: 244 | Upstream data is acked immediately*, to keep the slow upstream data flowing 245 | as fast as possible (client waits for ack to send next frag). 246 | 247 | Upstream pings are answered _only_ when 1) downstream data arrives from tun, 248 | OR 2) new upstream ping/data arrives from client. 249 | In most cases, this means we answer the previous DNS query instead of the 250 | current one. The current query is kept in queue and used as soon as 251 | downstream data has to be sent. 252 | 253 | *: upstream data ack is usually done as reply on the previous ping packet, 254 | and the upstream-data packet itself is kept in queue. 255 | 256 | Client: 257 | Downstream data is acked immediately, to keep it flowing fast (includes a 258 | ping after last downstream frag). 259 | 260 | Also, after all available upstream data is sent & acked by the server (which 261 | in some cases uses up the last query), send an additional ping to prime the 262 | server for the next downstream data. 263 | 264 | 265 | ====================================================== 266 | 2. Raw UDP protocol 267 | ====================================================== 268 | 269 | All Raw UDP protcol messages start with a 3 byte header: 0x10d19e 270 | This is not the start of a valid DNS message so it is easy to identify. 271 | The fourth byte contains the command and the user id. 272 | 273 | 7654 3210 274 | +----+----+ 275 | |CCCC|UUUU| 276 | +----+----+ 277 | 278 | Login message (command = 1): 279 | The header is followed by a MD5 hash with the same password as in the DNS 280 | login. The client starts the raw mode by sending this message, and uses 281 | the login challenge +1, and the server responds using the login challenge -1. 282 | After the login message has been exchanged, both the server and the client 283 | switch to raw udp mode for the rest of the connection. 284 | 285 | Data message (command = 2): 286 | After the header comes the payload data, which may be compressed. 287 | 288 | Ping message (command = 3): 289 | Sent from client to server and back to keep session open. Has no payload. 290 | 291 | -------------------------------------------------------------------------------- /man/iodine.8: -------------------------------------------------------------------------------- 1 | .\" groff -man -Tascii iodine.8 2 | .TH IODINE 8 "APR 2023" "User Manuals" 3 | .SH NAME 4 | iodine, iodined \- tunnel IPv4 over DNS 5 | .SH SYNOPSIS 6 | .B iodine [-v] 7 | 8 | .B iodine [-h] 9 | 10 | .B iodine [-4] [-6] [-f] [-r] [-u 11 | .I user 12 | .B ] [-P 13 | .I password 14 | .B ] [-m 15 | .I fragsize 16 | .B ] [-t 17 | .I chrootdir 18 | .B ] [-d 19 | .I device 20 | .B ] [-R 21 | .I rdomain 22 | .B ] [-m 23 | .I fragsize 24 | .B ] [-M 25 | .I namelen 26 | .B ] [-z 27 | .I context 28 | .B ] [-F 29 | .I pidfile 30 | .B ] [-T 31 | .I dnstype 32 | .B ] [-O 33 | .I downenc 34 | .B ] [-L 35 | .I 0|1 36 | .B ] [-I 37 | .I interval 38 | .B ] 39 | .B [ 40 | .I nameserver 41 | .B ] 42 | .I topdomain 43 | 44 | .B iodined [-v] 45 | 46 | .B iodined [-h] 47 | 48 | .B iodined [-4] [-6] [-c] [-s] [-f] [-D] [-u 49 | .I user 50 | .B ] [-t 51 | .I chrootdir 52 | .B ] [-d 53 | .I device 54 | .B ] [-m 55 | .I mtu 56 | .B ] [-l 57 | .I listen_ip4 58 | .B ] [-L 59 | .I listen_ip6 60 | .B ] [-p 61 | .I port 62 | .B ] [-n 63 | ( 64 | .B auto 65 | | 66 | .I external_ip 67 | ) 68 | .B ] [-b 69 | .I dnsport 70 | .B ] [-P 71 | .I password 72 | .B ] [-z 73 | .I context 74 | .B ] [-F 75 | .I pidfile 76 | .B ] [-i 77 | .I max_idle_time 78 | .B ] 79 | .I tunnel_ip 80 | .B [ 81 | .I /netmask 82 | .B ] 83 | .I topdomain 84 | .SH DESCRIPTION 85 | .B iodine 86 | lets you tunnel IPv4 data through a DNS 87 | server. This can be useful in situations where Internet access is firewalled, 88 | but DNS queries are allowed. It needs a TUN/TAP device to operate. The 89 | bandwidth is asymmetrical, 90 | with a measured maximum of 680 kbit/s upstream and 2.3 Mbit/s 91 | downstream in a wired LAN test network. 92 | Realistic sustained throughput on a Wifi network using a carrier-grade 93 | DNS cache has been measured at some 50 kbit/s upstream and over 200 kbit/s 94 | downstream. 95 | .B iodine 96 | is the client application, 97 | .B iodined 98 | is the server. 99 | 100 | Note: server and client are required to speak the exact same protocol. In most 101 | cases, this means running the same iodine version. Unfortunately, implementing 102 | backward and forward protocol compatibility is usually not feasible. 103 | .SH OPTIONS 104 | .SS Common Options: 105 | .TP 106 | .B -v 107 | Print version info and exit. 108 | .TP 109 | .B -h 110 | Print usage info and exit. 111 | .TP 112 | .B -f 113 | Keep running in foreground. 114 | .TP 115 | .B -4 116 | Force/allow only IPv4 DNS queries 117 | .TP 118 | .B -6 119 | Force/allow only IPv6 DNS queries 120 | .TP 121 | .B -u user 122 | Drop privileges and run as user 'user' after setting up tunnel. 123 | .TP 124 | .B -t chrootdir 125 | Chroot to 'chrootdir' after setting up tunnel. 126 | .TP 127 | .B -d device 128 | Use the TUN device 'device' instead of the normal one, which is dnsX on Linux 129 | and otherwise tunX. On Mac OS X 10.6, this can also be utunX, which will attempt 130 | to use an utun device built into the OS. 131 | .TP 132 | .B -P password 133 | Use 'password' to authenticate. If not used, 134 | .B stdin 135 | will be used as input. Only the first 32 characters will be used. 136 | .TP 137 | .B -z context 138 | Apply SELinux 'context' after initialization. 139 | .TP 140 | .B -F pidfile 141 | Create 'pidfile' and write process id in it. 142 | .SS Client Options: 143 | .TP 144 | .B -r 145 | Skip raw UDP mode. If not used, iodine will try getting the public IP address 146 | of the iodined host and test if it is reachable directly. If it is, traffic 147 | will be sent to the server instead of the DNS relay. 148 | .TP 149 | .B -R rdomain 150 | Use OpenBSD routing domain 'rdomain' for the DNS connection. 151 | .TP 152 | .B -m fragsize 153 | Force maximum downstream fragment size. Not setting this will cause the 154 | client to automatically probe the maximum accepted downstream fragment size. 155 | .TP 156 | .B -M namelen 157 | Maximum length of upstream hostnames, default 255. 158 | Usable range ca. 100 to 255. 159 | Use this option to scale back upstream bandwidth in favor of downstream 160 | bandwidth. 161 | Also useful for DNS servers that perform unreliably when using full-length 162 | hostnames, noticeable when fragment size autoprobe returns very 163 | different results each time. 164 | .TP 165 | .B -T dnstype 166 | DNS request type override. 167 | By default, autodetection will probe for working DNS request types, and 168 | will select the request type that is expected to provide the most bandwidth. 169 | However, it may turn out that a DNS relay imposes limits that skew the 170 | picture, which may lead to an "unexpected" DNS request type providing 171 | more bandwidth. 172 | In that case, use this option to override the autodetection. 173 | In (expected) decreasing bandwidth order, the supported DNS request types are: 174 | .IR NULL , 175 | .IR PRIVATE , 176 | .IR TXT , 177 | .IR SRV , 178 | .IR MX , 179 | .I CNAME 180 | and 181 | .I A 182 | (returning CNAME). 183 | Note that 184 | .IR SRV , 185 | .I MX 186 | and 187 | .I A 188 | may/will cause additional lookups by "smart" caching 189 | nameservers to get an actual IP address, which may either slow down or fail 190 | completely. The 191 | .IR PRIVATE 192 | type uses value 65399 (in the 'private use' range) and requires servers 193 | implementing RFC 3597. 194 | .TP 195 | .B -O downenc 196 | Force downstream encoding type for all query type responses except NULL. 197 | Default is autodetected, but may not spot all problems for the more advanced 198 | codecs. 199 | Use this option to override the autodetection. 200 | .I Base32 201 | is the lowest-grade codec and should always work; this is used when 202 | autodetection fails. 203 | .I Base64 204 | provides more bandwidth, but may not work on all nameservers. 205 | .I Base64u 206 | is equal to Base64 except in using underscore ('_') 207 | instead of plus sign ('+'), possibly working where 208 | .I Base64 209 | does not. 210 | .I Base128 211 | uses high byte values (mostly accented letters in iso8859-1), 212 | which might work with some nameservers. 213 | For TXT queries, 214 | .I Raw 215 | will provide maximum performance, but this will only work if the nameserver 216 | path is fully 8-bit-clean for responses that are assumed to be "legible text". 217 | .TP 218 | .B -L 0|1 219 | Lazy-mode switch. 220 | \-L1 (default): Use lazy mode for improved performance and decreased latency. 221 | A very small minority of DNS relays appears to be unable to handle the 222 | lazy mode traffic pattern, resulting in no or very little data coming through. 223 | The iodine client will detect this and try to switch back to legacy mode, 224 | but this may not always work. 225 | In these situations use \-L0 to force running in legacy mode 226 | (implies \-I1). 227 | .TP 228 | .B -I interval 229 | Maximum interval between requests (pings) so that intermediate DNS 230 | servers will not time out. Default is 4 in lazy mode, which will work 231 | fine in most cases. When too many SERVFAIL errors occur, iodine 232 | will automatically reduce this to 1. 233 | To get absolute minimum DNS traffic, 234 | increase well above 4, but not so high that SERVFAIL errors start to occur. 235 | There are some DNS relays with very small timeouts, 236 | notably dnsadvantage.com (ultradns), that will give 237 | SERVFAIL errors even with \-I1; data will still get trough, 238 | and these errors can be ignored. 239 | Maximum useful value is 59, since iodined will close a client's 240 | connection after 60 seconds of inactivity. 241 | .SS Server Options: 242 | .TP 243 | .B -c 244 | Disable checking the client IP address on all incoming requests. 245 | By default, requests originating from non-matching IP addresses will be 246 | rejected, however this will cause problems when requests are routed 247 | via a cluster of DNS servers. 248 | .TP 249 | .B -s 250 | Don't try to configure IP address or MTU. 251 | This should only be used if you have already configured the device that will be 252 | used. 253 | .TP 254 | .B -D 255 | Increase debug level. Level 1 prints info about each RX/TX packet. 256 | Implies the 257 | .B -f 258 | option. 259 | On level 2 (\-DD) or higher, DNS queries will be printed literally. 260 | When using Base128 upstream encoding, this is best viewed as 261 | ISO Latin-1 text instead of (illegal) UTF-8. 262 | This is easily done with : "LC_ALL=C luit iodined \-DD ..." 263 | (see luit(1)). 264 | .TP 265 | .B -m mtu 266 | Set 'mtu' as mtu size for the tun device. 267 | This will be sent to the client on login, and the client will use the same mtu 268 | for its tun device. Default 1130. Note that the DNS traffic will be 269 | automatically fragmented when needed. 270 | .TP 271 | .B -l external|listen_ip4 272 | Make the server listen only on 'listen_ip4' for incoming IPv4 requests. 273 | By default, incoming requests are accepted from all interfaces (0.0.0.0). 274 | A domain name can be used as argument - use one with only one A record. 275 | If listen_ip4 is 'external', iodined will use the opendns.com DNS service to 276 | retrieve the external IP of the host and use that as listen address. 277 | .TP 278 | .B -L listen_ip6 279 | Make the server listen only on 'listen_ip6' for incoming IPv6 requests. 280 | By default, incoming requests are accepted from all interfaces (::). 281 | A domain name can be used as argument - use one with only one AAAA record. 282 | .TP 283 | .B -p port 284 | Make the server listen on 'port' instead of 53 for traffic. 285 | If 'listen_ip4' does not include localhost, this 'port' can be the same 286 | as 'dnsport'. 287 | .B Note: 288 | You must make sure the dns requests are forwarded to this port yourself. 289 | .TP 290 | .B -n auto|external_ip 291 | The IP address to return in NS responses. Default is to return the address used 292 | as destination in the query. 293 | If external_ip is 'auto', iodined will use the opendns.com DNS service to 294 | retrieve the external IP of the host and use that for NS responses. 295 | .TP 296 | .B -b dnsport 297 | If this port is specified, all incoming requests not inside the tunnel domain 298 | will be forwarded to this port on localhost, to be handled by a real dns. 299 | If 'listen_ip' does not include localhost, this 'dnsport' can be the 300 | same as 'port'. 301 | .B Note: 302 | The forwarding is not fully transparent, and not advised for use 303 | in production environments. 304 | .TP 305 | .B -i max_idle_time 306 | Make the server stop itself after max_idle_time seconds if no traffic have been received. 307 | This should be combined with systemd or upstart on demand activation for being effective. 308 | .SS Client Arguments: 309 | .TP 310 | .B nameserver 311 | The nameserver to use to relay the dns traffic. This can be any relaying 312 | nameserver or the server running iodined if reachable. This field can be 313 | given as an IPv4/IPv6 address or as a hostname. This argument is optional, 314 | and if not specified a nameserver will be read from the 315 | .I /etc/resolv.conf 316 | file. 317 | .TP 318 | .B topdomain 319 | The dns traffic will be sent as queries for subdomains under 320 | \'topdomain'. This is normally a subdomain to a domain you own. Use a short 321 | domain name to get better throughput. If 322 | .B nameserver 323 | is the iodined server, then the topdomain can be chosen freely. This argument 324 | must be the same on both the client and the server. 325 | .SS Server Arguments: 326 | .TP 327 | .B tunnel_ip[/netmask] 328 | This is the server's ip address on the tun interface. The client will be 329 | given the next ip number in the range. It is recommended to use the 330 | 10.0.0.0 or 172.16.0.0 ranges. The default netmask is /27, can be overridden 331 | by specifying it here. Using a smaller network will limit the number of 332 | concurrent users. 333 | .TP 334 | .B topdomain 335 | The dns traffic is expected to arrive as queries for 336 | subdomains under 'topdomain'. This is normally a subdomain to a domain you 337 | own. Use a short domain name to get better throughput. This argument must be 338 | the same on both the client and the server. Queries for domains other 339 | than 'topdomain' will be forwarded when the \-b option is given, otherwise 340 | they will be dropped. The topdomain can start with '*' which will allow all 341 | domains ending with the same suffix. 342 | .SH EXAMPLES 343 | See the README file for both a quick test scenario, and a detailed description 344 | of real-world deployment. 345 | .SH SECURITY 346 | Login is a relatively secure challenge-response MD5 hash, with the 347 | password never passing the wire. 348 | However, all other data is 349 | .B NOT 350 | encrypted in any way. The DNS traffic is also vulnerable to replay, 351 | injection and man-in-the-middle attacks, especially when iodined is used 352 | with the \-c option. Use of ssh or vpn tunneling is strongly recommended. 353 | On both server and client, use 354 | .IR iptables , 355 | .I pf 356 | or other firewalls to block all traffic coming in from the tun interfaces, 357 | except to the used ssh or vpn ports. 358 | .SH ENVIRONMENT 359 | .SS IODINE_PASS 360 | If the environment variable 361 | .B IODINE_PASS 362 | is set, iodine will use the value it is set to as password instead of asking 363 | for one. The 364 | .B -P 365 | option still has precedence. 366 | .SS IODINED_PASS 367 | If the environment variable 368 | .B IODINED_PASS 369 | is set, iodined will use the value it is set to as password instead of asking 370 | for one. The 371 | .B -P 372 | option still has precedence. 373 | .SH SEE ALSO 374 | The README file in the source distribution contains some more elaborate 375 | information. 376 | .SH BUGS 377 | File bugs at https://github.com/yarrick/iodine 378 | .SH AUTHORS 379 | Erik Ekman and Bjorn Andersson . Major 380 | contributions by Anne Bezemer. 381 | -------------------------------------------------------------------------------- /src/Android.16.mk: -------------------------------------------------------------------------------- 1 | # 2 | # iodine for Android 3 | # 4 | # by Marcel Bokhorst 5 | # http://blog.bokhorst.biz/5123/computers-en-internet/iodine-for-android/ 6 | # 7 | # cd iodine-0.6.0-rc1/src 8 | # make base64u.h base64u.c 9 | # .../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk 10 | # 11 | 12 | LOCAL_PATH:= $(call my-dir) 13 | 14 | HEAD_COMMIT = `git rev-parse --short HEAD` 15 | 16 | include $(CLEAR_VARS) 17 | 18 | LOCAL_MODULE := iodine 19 | LOCAL_SRC_FILES := tun.c dns.c read.c encoding.c login.c base32.c base64.c base64u.c base128.c md5.c common.c iodine.c client.c util.c 20 | LOCAL_CFLAGS := -c -DANDROID -DLINUX -DIFCONFIGPATH=\"/system/bin/\" -Wall -DGITREVISION=\"$(HEAD_COMMIT)\" 21 | LOCAL_LDLIBS := -lz 22 | LOCAL_CFLAGS += -fPIE 23 | LOCAL_LDFLAGS += -fPIE -pie 24 | 25 | include $(BUILD_EXECUTABLE) 26 | 27 | -------------------------------------------------------------------------------- /src/Android.mk: -------------------------------------------------------------------------------- 1 | # 2 | # iodine for Android 3 | # 4 | # by Marcel Bokhorst 5 | # http://blog.bokhorst.biz/5123/computers-en-internet/iodine-for-android/ 6 | # 7 | # cd iodine-0.6.0-rc1/src 8 | # make base64u.h base64u.c 9 | # .../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk 10 | # 11 | 12 | LOCAL_PATH:= $(call my-dir) 13 | 14 | HEAD_COMMIT = `git rev-parse --short HEAD` 15 | 16 | include $(CLEAR_VARS) 17 | 18 | LOCAL_MODULE := iodine 19 | LOCAL_SRC_FILES := tun.c dns.c read.c encoding.c login.c base32.c base64.c base64u.c base128.c md5.c common.c iodine.c client.c util.c 20 | LOCAL_CFLAGS := -c -DANDROID -DLINUX -DIFCONFIGPATH=\"/system/bin/\" -Wall -DGITREVISION=\"$(HEAD_COMMIT)\" 21 | LOCAL_LDLIBS := -lz 22 | 23 | include $(BUILD_EXECUTABLE) 24 | 25 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | COMMONOBJS = tun.o dns.o read.o encoding.o login.o base32.o base64.o base64u.o base128.o md5.o common.o 2 | CLIENTOBJS = iodine.o client.o util.o 3 | CLIENT = ../bin/iodine 4 | SERVEROBJS = iodined.o user.o fw_query.o 5 | SERVER = ../bin/iodined 6 | 7 | OS = `echo $(TARGETOS) | tr "a-z" "A-Z"` 8 | ARCH = `uname -m` 9 | HEAD_COMMIT = `git rev-parse --short HEAD` 10 | 11 | LIBPATH = -L. 12 | LDFLAGS += -lz `sh osflags $(TARGETOS) link` $(LIBPATH) 13 | CFLAGS += -std=c99 -c -g -Wall -D$(OS) -pedantic `sh osflags $(TARGETOS) cflags` -DGITREVISION=\"$(HEAD_COMMIT)\" 14 | CFLAGS += -Wstrict-prototypes -Wtype-limits -Wmissing-declarations -Wmissing-prototypes 15 | 16 | all: stateos $(CLIENT) $(SERVER) 17 | 18 | stateos: 19 | @echo OS is $(OS), arch is $(ARCH) 20 | 21 | $(CLIENT): $(COMMONOBJS) $(CLIENTOBJS) 22 | @echo LD $@ 23 | @mkdir -p ../bin 24 | @$(CC) $(COMMONOBJS) $(CLIENTOBJS) -o $(CLIENT) $(LDFLAGS) 25 | 26 | $(SERVER): $(COMMONOBJS) $(SERVEROBJS) 27 | @echo LD $@ 28 | @mkdir -p ../bin 29 | @$(CC) $(COMMONOBJS) $(SERVEROBJS) -o $(SERVER) $(LDFLAGS) 30 | 31 | .c.o: 32 | @echo CC $< 33 | @$(CC) $(CFLAGS) $< -o $@ 34 | 35 | base64u.c: base64.c 36 | @echo Making $@ 37 | @echo '/* No use in editing, produced by Makefile! */' > $@ 38 | @sed -e 's/\([Bb][Aa][Ss][Ee]64\)/\1u/g ; s/0123456789+/0123456789_/' < base64.c >> $@ 39 | 40 | clean: 41 | @echo "Cleaning src/" 42 | @rm -f $(CLIENT){,.exe} $(SERVER){,.exe} *~ *.o *.core base64u.* 43 | @rm -rf obj libs #android stuff 44 | 45 | -------------------------------------------------------------------------------- /src/android_dns.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Marcel Bokhorst 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef __FIX_ANDROID_H__ 18 | #define __FIX_ANDROID_H__ 19 | 20 | /* Newer android platforms can have this data already */ 21 | #ifndef C_IN 22 | 23 | typedef struct { 24 | unsigned id :16; 25 | unsigned rd :1; 26 | unsigned tc :1; 27 | unsigned aa :1; 28 | unsigned opcode :4; 29 | unsigned qr :1; 30 | unsigned rcode :4; 31 | unsigned cd: 1; 32 | unsigned ad: 1; 33 | unsigned unused :1; 34 | unsigned ra :1; 35 | unsigned qdcount :16; 36 | unsigned ancount :16; 37 | unsigned nscount :16; 38 | unsigned arcount :16; 39 | } HEADER; 40 | 41 | #define NOERROR 0 42 | #define FORMERR 1 43 | #define SERVFAIL 2 44 | #define NXDOMAIN 3 45 | #define NOTIMP 4 46 | #define REFUSED 5 47 | 48 | #define C_IN 1 49 | 50 | #define T_A 1 51 | #define T_CNAME 5 52 | #define T_NULL 10 53 | #define T_MX 15 54 | #define T_TXT 16 55 | #define T_SRV 33 56 | 57 | #endif /* !C_IN */ 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/base128.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 J.A.Bezemer@opensourcepartners.nl 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /* 18 | * raw 76543210 76543210 76543210 76543210 76543210 76543210 76543210 19 | * enc 65432106 54321065 43210654 32106543 21065432 10654321 06543210 20 | * ^ ^ ^ ^ ^ ^ ^ ^ 21 | * 22 | * 0001 1 0001 1 23 | * 0011 3 0011 3 24 | * 0111 7 0111 7 25 | * 1111 f 0110 6 26 | * 1110 e 0100 4 27 | * 1100 c 28 | * 1000 8 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "encoding.h" 36 | 37 | #define BASE128_BLKSIZE_RAW 7 38 | #define BASE128_BLKSIZE_ENC 8 39 | 40 | /* Don't use '-' (restricted to middle of labels), prefer iso_8859-1 41 | * accent chars since they might readily be entered in normal use, 42 | * don't use 254-255 because of possible function overloading in DNS systems. 43 | */ 44 | static const unsigned char cb128[] = 45 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 46 | "\274\275\276\277" 47 | "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317" 48 | "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" 49 | "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357" 50 | "\360\361\362\363\364\365\366\367\370\371\372\373\374\375"; 51 | static unsigned char rev128[256]; 52 | static int reverse_init = 0; 53 | 54 | inline static void base128_reverse_init(void) 55 | { 56 | int i; 57 | unsigned char c; 58 | 59 | if (!reverse_init) { 60 | memset(rev128, 0, 256); 61 | for (i = 0; i < 128; i++) { 62 | c = cb128[i]; 63 | rev128[(int) c] = i; 64 | } 65 | reverse_init = 1; 66 | } 67 | } 68 | 69 | /* 70 | * Fills *buf with max. *buflen characters, encoding size bytes of *data. 71 | * 72 | * NOTE: *buf space should be at least 1 byte _more_ than *buflen 73 | * to hold the trailing '\0'. 74 | * 75 | * return value : #bytes filled in buf (excluding \0) 76 | * sets *buflen to : #bytes encoded from data 77 | */ 78 | static int base128_encode(char *buf, size_t *buflen, const void *data, 79 | size_t size) 80 | { 81 | unsigned char *ubuf = (unsigned char *) buf; 82 | unsigned char *udata = (unsigned char *) data; 83 | int iout = 0; /* to-be-filled output char */ 84 | int iin = 0; /* one more than last input byte that can be 85 | successfully decoded */ 86 | 87 | /* Note: Don't bother to optimize manually. GCC optimizes 88 | better(!) when using simplistic array indexing. */ 89 | 90 | while (1) { 91 | if (iout >= *buflen || iin >= size) 92 | break; 93 | ubuf[iout] = cb128[((udata[iin] & 0xfe) >> 1)]; 94 | iout++; 95 | 96 | if (iout >= *buflen || iin >= size) { 97 | iout--; /* previous char is useless */ 98 | break; 99 | } 100 | ubuf[iout] = cb128[((udata[iin] & 0x01) << 6) | 101 | ((iin + 1 < size) ? 102 | ((udata[iin + 1] & 0xfc) >> 2) : 0)]; 103 | iin++; /* 0 complete, iin=1 */ 104 | iout++; 105 | 106 | if (iout >= *buflen || iin >= size) 107 | break; 108 | ubuf[iout] = cb128[((udata[iin] & 0x03) << 5) | 109 | ((iin + 1 < size) ? 110 | ((udata[iin + 1] & 0xf8) >> 3) : 0)]; 111 | iin++; /* 1 complete, iin=2 */ 112 | iout++; 113 | 114 | if (iout >= *buflen || iin >= size) 115 | break; 116 | ubuf[iout] = cb128[((udata[iin] & 0x07) << 4) | 117 | ((iin + 1 < size) ? 118 | ((udata[iin + 1] & 0xf0) >> 4) : 0)]; 119 | iin++; /* 2 complete, iin=3 */ 120 | iout++; 121 | 122 | if (iout >= *buflen || iin >= size) 123 | break; 124 | ubuf[iout] = cb128[((udata[iin] & 0x0f) << 3) | 125 | ((iin + 1 < size) ? 126 | ((udata[iin + 1] & 0xe0) >> 5) : 0)]; 127 | iin++; /* 3 complete, iin=4 */ 128 | iout++; 129 | 130 | if (iout >= *buflen || iin >= size) 131 | break; 132 | ubuf[iout] = cb128[((udata[iin] & 0x1f) << 2) | 133 | ((iin + 1 < size) ? 134 | ((udata[iin + 1] & 0xc0) >> 6) : 0)]; 135 | iin++; /* 4 complete, iin=5 */ 136 | iout++; 137 | 138 | if (iout >= *buflen || iin >= size) 139 | break; 140 | ubuf[iout] = cb128[((udata[iin] & 0x3f) << 1) | 141 | ((iin + 1 < size) ? 142 | ((udata[iin + 1] & 0x80) >> 7) : 0)]; 143 | iin++; /* 5 complete, iin=6 */ 144 | iout++; 145 | 146 | if (iout >= *buflen || iin >= size) 147 | break; 148 | ubuf[iout] = cb128[(udata[iin] & 0x7f)]; 149 | iin++; /* 6 complete, iin=7 */ 150 | iout++; 151 | } 152 | 153 | ubuf[iout] = '\0'; 154 | 155 | /* store number of bytes from data that was used */ 156 | *buflen = iin; 157 | 158 | return iout; 159 | } 160 | 161 | #define REV128(x) rev128[(int) (x)] 162 | 163 | /* 164 | * Fills *buf with max. *buflen bytes, decoded from slen chars in *str. 165 | * Decoding stops early when *str contains \0. 166 | * Illegal encoded chars are assumed to decode to zero. 167 | * 168 | * NOTE: *buf space should be at least 1 byte _more_ than *buflen 169 | * to hold a trailing '\0' that is added (though *buf will usually 170 | * contain full-binary data). 171 | * 172 | * return value : #bytes filled in buf (excluding \0) 173 | */ 174 | static int base128_decode(void *buf, size_t *buflen, const char *str, 175 | size_t slen) 176 | { 177 | unsigned char *ustr = (unsigned char *) str; 178 | unsigned char *ubuf = (unsigned char *) buf; 179 | int iout = 0; /* to-be-filled output byte */ 180 | int iin = 0; /* next input char to use in decoding */ 181 | 182 | base128_reverse_init(); 183 | 184 | /* Note: Don't bother to optimize manually. GCC optimizes 185 | better(!) when using simplistic array indexing. */ 186 | 187 | while (1) { 188 | if (iout >= *buflen || iin + 1 >= slen || 189 | str[iin] == '\0' || str[iin + 1] == '\0') 190 | break; 191 | ubuf[iout] = ((REV128(ustr[iin]) & 0x7f) << 1) | 192 | ((REV128(ustr[iin + 1]) & 0x40) >> 6); 193 | iin++; /* 0 used up, iin=1 */ 194 | iout++; 195 | 196 | if (iout >= *buflen || iin + 1 >= slen || 197 | str[iin] == '\0' || str[iin + 1] == '\0') 198 | break; 199 | ubuf[iout] = ((REV128(ustr[iin]) & 0x3f) << 2) | 200 | ((REV128(ustr[iin + 1]) & 0x60) >> 5); 201 | iin++; /* 1 used up, iin=2 */ 202 | iout++; 203 | 204 | if (iout >= *buflen || iin + 1 >= slen || 205 | str[iin] == '\0' || str[iin + 1] == '\0') 206 | break; 207 | ubuf[iout] = ((REV128(ustr[iin]) & 0x1f) << 3) | 208 | ((REV128(ustr[iin + 1]) & 0x70) >> 4); 209 | iin++; /* 2 used up, iin=3 */ 210 | iout++; 211 | 212 | if (iout >= *buflen || iin + 1 >= slen || 213 | str[iin] == '\0' || str[iin + 1] == '\0') 214 | break; 215 | ubuf[iout] = ((REV128(ustr[iin]) & 0x0f) << 4) | 216 | ((REV128(ustr[iin + 1]) & 0x78) >> 3); 217 | iin++; /* 3 used up, iin=4 */ 218 | iout++; 219 | 220 | if (iout >= *buflen || iin + 1 >= slen || 221 | str[iin] == '\0' || str[iin + 1] == '\0') 222 | break; 223 | ubuf[iout] = ((REV128(ustr[iin]) & 0x07) << 5) | 224 | ((REV128(ustr[iin + 1]) & 0x7c) >> 2); 225 | iin++; /* 4 used up, iin=5 */ 226 | iout++; 227 | 228 | if (iout >= *buflen || iin + 1 >= slen || 229 | str[iin] == '\0' || str[iin + 1] == '\0') 230 | break; 231 | ubuf[iout] = ((REV128(ustr[iin]) & 0x03) << 6) | 232 | ((REV128(ustr[iin + 1]) & 0x7e) >> 1); 233 | iin++; /* 5 used up, iin=6 */ 234 | iout++; 235 | 236 | if (iout >= *buflen || iin + 1 >= slen || 237 | str[iin] == '\0' || str[iin + 1] == '\0') 238 | break; 239 | ubuf[iout] = ((REV128(ustr[iin]) & 0x01) << 7) | 240 | ((REV128(ustr[iin + 1]) & 0x7f)); 241 | iin += 2; /* 6,7 used up, iin=8 */ 242 | iout++; 243 | } 244 | 245 | ubuf[iout] = '\0'; 246 | 247 | return iout; 248 | } 249 | 250 | const struct encoder base128_ops = { 251 | .name = "Base128", 252 | 253 | .encode = base128_encode, 254 | .decode = base128_decode, 255 | 256 | .places_dots = false, 257 | .eats_dots = false, 258 | 259 | .blocksize_raw = BASE128_BLKSIZE_RAW, 260 | .blocksize_encoded = BASE128_BLKSIZE_ENC, 261 | }; 262 | -------------------------------------------------------------------------------- /src/base32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "encoding.h" 24 | 25 | #define BASE32_BLKSIZE_RAW 5 26 | #define BASE32_BLKSIZE_ENC 8 27 | 28 | static const char cb32[] = 29 | "abcdefghijklmnopqrstuvwxyz012345"; 30 | static const char cb32_ucase[] = 31 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"; 32 | static unsigned char rev32[256]; 33 | static int reverse_init = 0; 34 | 35 | inline static void base32_reverse_init(void) 36 | { 37 | int i; 38 | unsigned char c; 39 | 40 | if (!reverse_init) { 41 | memset(rev32, 0, 256); 42 | for (i = 0; i < 32; i++) { 43 | c = cb32[i]; 44 | rev32[(int) c] = i; 45 | c = cb32_ucase[i]; 46 | rev32[(int) c] = i; 47 | } 48 | reverse_init = 1; 49 | } 50 | } 51 | 52 | int b32_5to8(int in) 53 | { 54 | return cb32[in & 31]; 55 | } 56 | 57 | int b32_8to5(int in) 58 | { 59 | base32_reverse_init(); 60 | return rev32[in]; 61 | } 62 | 63 | /* 64 | * Fills *buf with max. *buflen characters, encoding size bytes of *data. 65 | * 66 | * NOTE: *buf space should be at least 1 byte _more_ than *buflen 67 | * to hold the trailing '\0'. 68 | * 69 | * return value : #bytes filled in buf (excluding \0) 70 | * sets *buflen to : #bytes encoded from data 71 | */ 72 | static int base32_encode(char *buf, size_t *buflen, const void *data, size_t size) 73 | { 74 | unsigned char *udata = (unsigned char *) data; 75 | int iout = 0; /* to-be-filled output char */ 76 | int iin = 0; /* one more than last input byte that can be 77 | successfully decoded */ 78 | 79 | /* Note: Don't bother to optimize manually. GCC optimizes 80 | better(!) when using simplistic array indexing. */ 81 | 82 | while (1) { 83 | if (iout >= *buflen || iin >= size) 84 | break; 85 | buf[iout] = cb32[((udata[iin] & 0xf8) >> 3)]; 86 | iout++; 87 | 88 | if (iout >= *buflen || iin >= size) { 89 | iout--; /* previous char is useless */ 90 | break; 91 | } 92 | buf[iout] = cb32[((udata[iin] & 0x07) << 2) | 93 | ((iin + 1 < size) ? 94 | ((udata[iin + 1] & 0xc0) >> 6) : 0)]; 95 | iin++; /* 0 complete, iin=1 */ 96 | iout++; 97 | 98 | if (iout >= *buflen || iin >= size) 99 | break; 100 | buf[iout] = cb32[((udata[iin] & 0x3e) >> 1)]; 101 | iout++; 102 | 103 | if (iout >= *buflen || iin >= size) { 104 | iout--; /* previous char is useless */ 105 | break; 106 | } 107 | buf[iout] = cb32[((udata[iin] & 0x01) << 4) | 108 | ((iin + 1 < size) ? 109 | ((udata[iin + 1] & 0xf0) >> 4) : 0)]; 110 | iin++; /* 1 complete, iin=2 */ 111 | iout++; 112 | 113 | if (iout >= *buflen || iin >= size) 114 | break; 115 | buf[iout] = cb32[((udata[iin] & 0x0f) << 1) | 116 | ((iin + 1 < size) ? 117 | ((udata[iin + 1] & 0x80) >> 7) : 0)]; 118 | iin++; /* 2 complete, iin=3 */ 119 | iout++; 120 | 121 | if (iout >= *buflen || iin >= size) 122 | break; 123 | buf[iout] = cb32[((udata[iin] & 0x7c) >> 2)]; 124 | iout++; 125 | 126 | if (iout >= *buflen || iin >= size) { 127 | iout--; /* previous char is useless */ 128 | break; 129 | } 130 | buf[iout] = cb32[((udata[iin] & 0x03) << 3) | 131 | ((iin + 1 < size) ? 132 | ((udata[iin + 1] & 0xe0) >> 5) : 0)]; 133 | iin++; /* 3 complete, iin=4 */ 134 | iout++; 135 | 136 | if (iout >= *buflen || iin >= size) 137 | break; 138 | buf[iout] = cb32[((udata[iin] & 0x1f))]; 139 | iin++; /* 4 complete, iin=5 */ 140 | iout++; 141 | } 142 | 143 | buf[iout] = '\0'; 144 | 145 | /* store number of bytes from data that was used */ 146 | *buflen = iin; 147 | 148 | return iout; 149 | } 150 | 151 | #define REV32(x) rev32[(int) (x)] 152 | 153 | /* 154 | * Fills *buf with max. *buflen bytes, decoded from slen chars in *str. 155 | * Decoding stops early when *str contains \0. 156 | * Illegal encoded chars are assumed to decode to zero. 157 | * 158 | * NOTE: *buf space should be at least 1 byte _more_ than *buflen 159 | * to hold a trailing '\0' that is added (though *buf will usually 160 | * contain full-binary data). 161 | * 162 | * return value : #bytes filled in buf (excluding \0) 163 | */ 164 | static int base32_decode(void *buf, size_t *buflen, const char *str, 165 | size_t slen) 166 | { 167 | unsigned char *ubuf = (unsigned char *) buf; 168 | int iout = 0; /* to-be-filled output byte */ 169 | int iin = 0; /* next input char to use in decoding */ 170 | 171 | base32_reverse_init(); 172 | 173 | /* Note: Don't bother to optimize manually. GCC optimizes 174 | better(!) when using simplistic array indexing. */ 175 | 176 | while (1) { 177 | if (iout >= *buflen || iin + 1 >= slen || 178 | str[iin] == '\0' || str[iin + 1] == '\0') 179 | break; 180 | ubuf[iout] = ((REV32(str[iin]) & 0x1f) << 3) | 181 | ((REV32(str[iin + 1]) & 0x1c) >> 2); 182 | iin++; /* 0 used up, iin=1 */ 183 | iout++; 184 | 185 | if (iout >= *buflen || iin + 2 >= slen || 186 | str[iin] == '\0' || str[iin + 1] == '\0' || 187 | str[iin + 2] == '\0') 188 | break; 189 | ubuf[iout] = ((REV32(str[iin]) & 0x03) << 6) | 190 | ((REV32(str[iin + 1]) & 0x1f) << 1) | 191 | ((REV32(str[iin + 2]) & 0x10) >> 4); 192 | iin += 2; /* 1,2 used up, iin=3 */ 193 | iout++; 194 | 195 | if (iout >= *buflen || iin + 1 >= slen || 196 | str[iin] == '\0' || str[iin + 1] == '\0') 197 | break; 198 | ubuf[iout] = ((REV32(str[iin]) & 0x0f) << 4) | 199 | ((REV32(str[iin + 1]) & 0x1e) >> 1); 200 | iin++; /* 3 used up, iin=4 */ 201 | iout++; 202 | 203 | if (iout >= *buflen || iin + 2 >= slen || 204 | str[iin] == '\0' || str[iin + 1] == '\0' || 205 | str[iin + 2] == '\0') 206 | break; 207 | ubuf[iout] = ((REV32(str[iin]) & 0x01) << 7) | 208 | ((REV32(str[iin + 1]) & 0x1f) << 2) | 209 | ((REV32(str[iin + 2]) & 0x18) >> 3); 210 | iin += 2; /* 4,5 used up, iin=6 */ 211 | iout++; 212 | 213 | if (iout >= *buflen || iin + 1 >= slen || 214 | str[iin] == '\0' || str[iin + 1] == '\0') 215 | break; 216 | ubuf[iout] = ((REV32(str[iin]) & 0x07) << 5) | 217 | ((REV32(str[iin + 1]) & 0x1f)); 218 | iin += 2; /* 6,7 used up, iin=8 */ 219 | iout++; 220 | } 221 | 222 | ubuf[iout] = '\0'; 223 | 224 | return iout; 225 | } 226 | 227 | const struct encoder base32_ops = { 228 | .name = "Base32", 229 | 230 | .encode = base32_encode, 231 | .decode = base32_decode, 232 | 233 | .places_dots = false, 234 | .eats_dots = false, 235 | 236 | .blocksize_raw = BASE32_BLKSIZE_RAW, 237 | .blocksize_encoded = BASE32_BLKSIZE_ENC, 238 | }; 239 | -------------------------------------------------------------------------------- /src/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "encoding.h" 24 | 25 | #define BASE64_BLKSIZE_RAW 3 26 | #define BASE64_BLKSIZE_ENC 4 27 | 28 | /* Note: the "unofficial" char is last here, which means that the \377 pattern 29 | in DOWNCODECCHECK1 ('Y' request) will properly test it. */ 30 | static const char cb64[] = 31 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789+"; 32 | static unsigned char rev64[256]; 33 | static int reverse_init = 0; 34 | 35 | inline static void base64_reverse_init(void) 36 | { 37 | int i; 38 | unsigned char c; 39 | 40 | if (!reverse_init) { 41 | memset(rev64, 0, 256); 42 | for (i = 0; i < 64; i++) { 43 | c = cb64[i]; 44 | rev64[(int) c] = i; 45 | } 46 | reverse_init = 1; 47 | } 48 | } 49 | 50 | /* 51 | * Fills *buf with max. *buflen characters, encoding size bytes of *data. 52 | * 53 | * NOTE: *buf space should be at least 1 byte _more_ than *buflen 54 | * to hold the trailing '\0'. 55 | * 56 | * return value : #bytes filled in buf (excluding \0) 57 | * sets *buflen to : #bytes encoded from data 58 | */ 59 | static int base64_encode(char *buf, size_t *buflen, const void *data, 60 | size_t size) 61 | { 62 | unsigned char *udata = (unsigned char *) data; 63 | int iout = 0; /* to-be-filled output char */ 64 | int iin = 0; /* one more than last input byte that can be 65 | successfully decoded */ 66 | 67 | /* Note: Don't bother to optimize manually. GCC optimizes 68 | better(!) when using simplistic array indexing. */ 69 | 70 | while (1) { 71 | if (iout >= *buflen || iin >= size) 72 | break; 73 | buf[iout] = cb64[((udata[iin] & 0xfc) >> 2)]; 74 | iout++; 75 | 76 | if (iout >= *buflen || iin >= size) { 77 | iout--; /* previous char is useless */ 78 | break; 79 | } 80 | buf[iout] = cb64[((udata[iin] & 0x03) << 4) | 81 | ((iin + 1 < size) ? 82 | ((udata[iin + 1] & 0xf0) >> 4) : 0)]; 83 | iin++; /* 0 complete, iin=1 */ 84 | iout++; 85 | 86 | if (iout >= *buflen || iin >= size) 87 | break; 88 | buf[iout] = cb64[((udata[iin] & 0x0f) << 2) | 89 | ((iin + 1 < size) ? 90 | ((udata[iin + 1] & 0xc0) >> 6) : 0)]; 91 | iin++; /* 1 complete, iin=2 */ 92 | iout++; 93 | 94 | if (iout >= *buflen || iin >= size) 95 | break; 96 | buf[iout] = cb64[(udata[iin] & 0x3f)]; 97 | iin++; /* 2 complete, iin=3 */ 98 | iout++; 99 | } 100 | 101 | buf[iout] = '\0'; 102 | 103 | /* store number of bytes from data that was used */ 104 | *buflen = iin; 105 | 106 | return iout; 107 | } 108 | 109 | #define REV64(x) rev64[(int) (x)] 110 | 111 | /* 112 | * Fills *buf with max. *buflen bytes, decoded from slen chars in *str. 113 | * Decoding stops early when *str contains \0. 114 | * Illegal encoded chars are assumed to decode to zero. 115 | * 116 | * NOTE: *buf space should be at least 1 byte _more_ than *buflen 117 | * to hold a trailing '\0' that is added (though *buf will usually 118 | * contain full-binary data). 119 | * 120 | * return value : #bytes filled in buf (excluding \0) 121 | */ 122 | static int base64_decode(void *buf, size_t *buflen, const char *str, 123 | size_t slen) 124 | { 125 | unsigned char *ubuf = (unsigned char *) buf; 126 | int iout = 0; /* to-be-filled output byte */ 127 | int iin = 0; /* next input char to use in decoding */ 128 | 129 | base64_reverse_init(); 130 | 131 | /* Note: Don't bother to optimize manually. GCC optimizes 132 | better(!) when using simplistic array indexing. */ 133 | 134 | while (1) { 135 | if (iout >= *buflen || iin + 1 >= slen || 136 | str[iin] == '\0' || str[iin + 1] == '\0') 137 | break; 138 | ubuf[iout] = ((REV64(str[iin]) & 0x3f) << 2) | 139 | ((REV64(str[iin + 1]) & 0x30) >> 4); 140 | iin++; /* 0 used up, iin=1 */ 141 | iout++; 142 | 143 | if (iout >= *buflen || iin + 1 >= slen || 144 | str[iin] == '\0' || str[iin + 1] == '\0') 145 | break; 146 | ubuf[iout] = ((REV64(str[iin]) & 0x0f) << 4) | 147 | ((REV64(str[iin + 1]) & 0x3c) >> 2); 148 | iin++; /* 1 used up, iin=2 */ 149 | iout++; 150 | 151 | if (iout >= *buflen || iin + 1 >= slen || 152 | str[iin] == '\0' || str[iin + 1] == '\0') 153 | break; 154 | ubuf[iout] = ((REV64(str[iin]) & 0x03) << 6) | 155 | (REV64(str[iin + 1]) & 0x3f); 156 | iin += 2; /* 2,3 used up, iin=4 */ 157 | iout++; 158 | } 159 | 160 | ubuf[iout] = '\0'; 161 | 162 | return iout; 163 | } 164 | 165 | const struct encoder base64_ops = { 166 | .name = "Base64", 167 | 168 | .encode = base64_encode, 169 | .decode = base64_decode, 170 | 171 | .places_dots = false, 172 | .eats_dots = false, 173 | 174 | .blocksize_raw = BASE64_BLKSIZE_RAW, 175 | .blocksize_encoded = BASE64_BLKSIZE_ENC, 176 | }; 177 | -------------------------------------------------------------------------------- /src/client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef __CLIENT_H__ 19 | #define __CLIENT_H__ 20 | 21 | void client_init(void); 22 | void client_stop(void); 23 | 24 | enum connection client_get_conn(void); 25 | const char *client_get_raw_addr(void); 26 | 27 | void client_set_nameserver(struct sockaddr_storage *, int); 28 | void client_set_topdomain(const char *cp); 29 | void client_set_password(const char *cp); 30 | int client_set_qtype(char *qtype); 31 | char *client_get_qtype(void); 32 | void client_set_downenc(char *encoding); 33 | void client_set_selecttimeout(int select_timeout); 34 | void client_set_lazymode(int lazy_mode); 35 | void client_set_hostname_maxlen(int i); 36 | 37 | int client_handshake(int dns_fd, int raw_mode, int autodetect_frag_size, 38 | int fragsize); 39 | int client_tunnel(int tun_fd, int dns_fd); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2006-2014 Erik Ekman , 2 | * 2006-2009 Bjorn Andersson 3 | * Copyright (c) 2007 Albert Lee . 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #ifdef WINDOWS32 33 | #include 34 | #include 35 | #else 36 | #include 37 | #ifdef DARWIN 38 | #define BIND_8_COMPAT 39 | #include 40 | #endif 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #endif 49 | 50 | #ifdef HAVE_SETCON 51 | # include 52 | #endif 53 | 54 | #include "common.h" 55 | 56 | /* The raw header used when not using DNS protocol */ 57 | const unsigned char raw_header[RAW_HDR_LEN] = { 0x10, 0xd1, 0x9e, 0x00 }; 58 | 59 | /* daemon(3) exists only in 4.4BSD or later, and in GNU libc */ 60 | #if !defined(ANDROID) && !defined(WINDOWS32) && !(defined(BSD) && (BSD >= 199306)) && !defined(__GLIBC__) && !defined(__HAIKU__) 61 | static int daemon(int nochdir, int noclose) 62 | { 63 | int fd, i; 64 | 65 | switch (fork()) { 66 | case 0: 67 | break; 68 | case -1: 69 | return -1; 70 | default: 71 | _exit(0); 72 | } 73 | 74 | if (!nochdir) { 75 | chdir("/"); 76 | } 77 | 78 | if (setsid() < 0) { 79 | return -1; 80 | } 81 | 82 | if (!noclose) { 83 | if ((fd = open("/dev/null", O_RDWR)) >= 0) { 84 | for (i = 0; i < 3; i++) { 85 | dup2(fd, i); 86 | } 87 | if (fd > 2) { 88 | close(fd); 89 | } 90 | } 91 | } 92 | return 0; 93 | } 94 | #endif 95 | 96 | #if defined(__BEOS__) && !defined(__HAIKU__) 97 | int setgroups(int count, int *groups) 98 | { 99 | /* errno = ENOSYS; */ 100 | return -1; 101 | } 102 | #endif 103 | 104 | #ifndef WINDOWS32 105 | void 106 | check_superuser(void) 107 | { 108 | if (geteuid() != 0) { 109 | warnx("Run as root and you'll be happy."); 110 | exit(-1); 111 | } 112 | } 113 | #endif 114 | 115 | char * 116 | format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len) 117 | { 118 | static char dst[INET6_ADDRSTRLEN + 1]; 119 | 120 | memset(dst, 0, sizeof(dst)); 121 | if (sockaddr->ss_family == AF_INET && sockaddr_len >= sizeof(struct sockaddr_in)) { 122 | getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST); 123 | } else if (sockaddr->ss_family == AF_INET6 && sockaddr_len >= sizeof(struct sockaddr_in6)) { 124 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sockaddr; 125 | if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) { 126 | struct in_addr ia; 127 | /* Get mapped v4 addr from last 32bit field */ 128 | memcpy(&ia.s_addr, &addr->sin6_addr.s6_addr[12], sizeof(ia)); 129 | strcpy(dst, inet_ntoa(ia)); 130 | } else { 131 | getnameinfo((struct sockaddr *)sockaddr, sockaddr_len, dst, sizeof(dst) - 1, NULL, 0, NI_NUMERICHOST); 132 | } 133 | } else { 134 | dst[0] = '?'; 135 | } 136 | return dst; 137 | } 138 | 139 | int 140 | get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_storage *out) 141 | { 142 | struct addrinfo hints, *addr; 143 | int res; 144 | char portnum[8]; 145 | int addrlen; 146 | 147 | memset(portnum, 0, sizeof(portnum)); 148 | snprintf(portnum, sizeof(portnum) - 1, "%d", port); 149 | 150 | memset(&hints, 0, sizeof(hints)); 151 | hints.ai_family = addr_family; 152 | #if defined(WINDOWS32) || defined(OPENBSD) 153 | /* AI_ADDRCONFIG misbehaves on windows, and does not exist in OpenBSD */ 154 | hints.ai_flags = flags; 155 | #else 156 | hints.ai_flags = AI_ADDRCONFIG | flags; 157 | #endif 158 | hints.ai_socktype = SOCK_DGRAM; 159 | hints.ai_protocol = IPPROTO_UDP; 160 | 161 | res = getaddrinfo(host, portnum, &hints, &addr); 162 | if (res != 0) { 163 | return -1; 164 | } 165 | 166 | addrlen = addr->ai_addrlen; 167 | /* Grab first result */ 168 | memcpy(out, addr->ai_addr, addr->ai_addrlen); 169 | freeaddrinfo(addr); 170 | return addrlen; 171 | } 172 | 173 | int 174 | open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len) 175 | { 176 | return open_dns_opt(sockaddr, sockaddr_len, -1); 177 | } 178 | 179 | int 180 | open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, int v6only) 181 | { 182 | int flag; 183 | int fd; 184 | 185 | if ((fd = socket(sockaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 186 | err(1, "socket"); 187 | } 188 | 189 | flag = 1; 190 | #ifdef SO_REUSEPORT 191 | setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (const void*) &flag, sizeof(flag)); 192 | #endif 193 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void*) &flag, sizeof(flag)); 194 | 195 | #ifndef WINDOWS32 196 | fd_set_close_on_exec(fd); 197 | #endif 198 | 199 | if (sockaddr->ss_family == AF_INET6 && v6only >= 0) { 200 | setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*) &v6only, sizeof(v6only)); 201 | } 202 | 203 | #ifdef IP_OPT_DONT_FRAG 204 | /* Set dont-fragment ip header flag */ 205 | flag = DONT_FRAG_VALUE; 206 | setsockopt(fd, IPPROTO_IP, IP_OPT_DONT_FRAG, (const void*) &flag, sizeof(flag)); 207 | #endif 208 | 209 | if (bind(fd, (struct sockaddr*) sockaddr, sockaddr_len) < 0) 210 | err(1, "bind() to %s", format_addr(sockaddr, sockaddr_len)); 211 | 212 | fprintf(stderr, "Opened IPv%d UDP socket\n", sockaddr->ss_family == AF_INET6 ? 6 : 4); 213 | 214 | return fd; 215 | } 216 | 217 | int 218 | open_dns_from_host(char *host, int port, int addr_family, int flags) 219 | { 220 | struct sockaddr_storage addr; 221 | int addrlen; 222 | 223 | addrlen = get_addr(host, port, addr_family, flags, &addr); 224 | if (addrlen < 0) 225 | return addrlen; 226 | 227 | return open_dns(&addr, addrlen); 228 | } 229 | 230 | void 231 | close_dns(int fd) 232 | { 233 | close(fd); 234 | } 235 | 236 | void 237 | do_chroot(char *newroot) 238 | { 239 | #if !(defined(WINDOWS32) || defined(__BEOS__) || defined(__HAIKU__)) 240 | if (chroot(newroot) != 0 || chdir("/") != 0) 241 | err(1, "%s", newroot); 242 | 243 | if (seteuid(geteuid()) != 0 || setuid(getuid()) != 0) { 244 | err(1, "set[e]uid()"); 245 | } 246 | #else 247 | warnx("chroot not available"); 248 | #endif 249 | } 250 | 251 | void 252 | do_setcon(char *context) 253 | { 254 | #ifdef HAVE_SETCON 255 | if (-1 == setcon(context)) 256 | err(1, "%s", context); 257 | #else 258 | warnx("No SELinux support built in"); 259 | #endif 260 | } 261 | 262 | void 263 | do_pidfile(char *pidfile) 264 | { 265 | #ifndef WINDOWS32 266 | FILE *file; 267 | 268 | if ((file = fopen(pidfile, "w")) == NULL) { 269 | syslog(LOG_ERR, "Cannot write pidfile to %s, exiting", pidfile); 270 | err(1, "do_pidfile: Can not write pidfile to %s", pidfile); 271 | } else { 272 | fprintf(file, "%d\n", (int)getpid()); 273 | fclose(file); 274 | } 275 | #else 276 | fprintf(stderr, "Windows version does not support pid file\n"); 277 | #endif 278 | } 279 | 280 | void 281 | do_detach(void) 282 | { 283 | #ifndef WINDOWS32 284 | fprintf(stderr, "Detaching from terminal...\n"); 285 | daemon(0, 0); 286 | umask(0); 287 | alarm(0); 288 | #else 289 | fprintf(stderr, "Windows version does not support detaching\n"); 290 | #endif 291 | } 292 | 293 | void 294 | read_password(char *buf, size_t len) 295 | { 296 | char pwd[80] = {0}; 297 | #ifndef WINDOWS32 298 | struct termios old; 299 | struct termios tp; 300 | 301 | tcgetattr(0, &tp); 302 | old = tp; 303 | 304 | tp.c_lflag &= (~ECHO); 305 | tcsetattr(0, TCSANOW, &tp); 306 | #else 307 | int i; 308 | #endif 309 | 310 | fprintf(stderr, "Enter tunnel password: "); 311 | fflush(stderr); 312 | #ifndef WINDOWS32 313 | fscanf(stdin, "%79[^\n]", pwd); 314 | #else 315 | for (i = 0; i < sizeof(pwd); i++) { 316 | pwd[i] = getch(); 317 | if (pwd[i] == '\r' || pwd[i] == '\n') { 318 | pwd[i] = 0; 319 | break; 320 | } else if (pwd[i] == '\b') { 321 | i--; /* Remove the \b char */ 322 | if (i >=0) i--; /* If not first char, remove one more */ 323 | } 324 | } 325 | #endif 326 | fprintf(stderr, "\n"); 327 | 328 | #ifndef WINDOWS32 329 | tcsetattr(0, TCSANOW, &old); 330 | #endif 331 | 332 | strncpy(buf, pwd, len); 333 | buf[len-1] = '\0'; 334 | } 335 | 336 | int 337 | check_topdomain(char *str, int allow_wildcard, char **errormsg) 338 | { 339 | int i; 340 | int dots = 0; 341 | int chunklen = 0; 342 | 343 | if (strlen(str) < 3) { 344 | if (errormsg) *errormsg = "Too short (< 3)"; 345 | return 1; 346 | } 347 | if (strlen(str) > 128) { 348 | if (errormsg) *errormsg = "Too long (> 128)"; 349 | return 1; 350 | } 351 | 352 | if (str[0] == '.') { 353 | if (errormsg) *errormsg = "Starts with a dot"; 354 | return 1; 355 | } 356 | 357 | for (i = 0; i < strlen(str); i++) { 358 | if (str[i] == '.') { 359 | dots++; 360 | if (chunklen == 0) { 361 | if (errormsg) *errormsg = "Consecutive dots"; 362 | return 1; 363 | } 364 | if (chunklen > 63) { 365 | if (errormsg) *errormsg = "Too long domain part (> 63)"; 366 | return 1; 367 | } 368 | chunklen = 0; 369 | } else { 370 | chunklen++; 371 | } 372 | if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || 373 | isdigit(str[i]) || str[i] == '-' || str[i] == '.') { 374 | continue; 375 | } else if (allow_wildcard && str[i] == '*') { 376 | /* First char allowed to be wildcard, if followed by dot */ 377 | if (i == 0) { 378 | if (str[i+1] == '.') { 379 | continue; 380 | } 381 | if (errormsg) *errormsg = "Wildcard (*) must be followed by dot"; 382 | return 1; 383 | } else { 384 | if (errormsg) *errormsg = "Wildcard (*) only allowed as first char"; 385 | return 1; 386 | } 387 | } else { 388 | if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])"; 389 | return 1; 390 | } 391 | } 392 | 393 | if (dots == 0) { 394 | if (errormsg) *errormsg = "No dots"; 395 | return 1; 396 | } 397 | if (chunklen == 0) { 398 | if (errormsg) *errormsg = "Ends with a dot"; 399 | return 1; 400 | } 401 | if (chunklen > 63) { 402 | if (errormsg) *errormsg = "Too long domain part (> 63)"; 403 | return 1; 404 | } 405 | 406 | return 0; 407 | } 408 | 409 | int 410 | query_datalen(const char *qname, const char *topdomain) 411 | { 412 | /* Return number of data bytes embedded in DNS query name, 413 | * or -1 if domains do not match. 414 | */ 415 | int qpos = strlen(qname); 416 | int tpos = strlen(topdomain); 417 | if (tpos < 3 || qpos < tpos) { 418 | /* Domain or query name too short */ 419 | return -1; 420 | } 421 | /* Backward string compare */ 422 | qpos--; 423 | tpos--; 424 | while (qpos >= 0) { 425 | if (topdomain[tpos] == '*') { 426 | /* Wild match, is first in topdomain */ 427 | if (qname[qpos] == '*') { 428 | /* Don't match against stars in query name */ 429 | return -1; 430 | } else if (qpos == 0 || qname[qpos-1] == '.') { 431 | /* Reached start of query name or chunk separator */ 432 | return qpos; 433 | } 434 | qpos--; 435 | } else if (tolower(qname[qpos]) == tolower(topdomain[tpos])) { 436 | /* Matching char, exclude wildcard in query name */ 437 | if (tpos == 0) { 438 | /* Fully matched domain */ 439 | if (qpos == 0 || qname[qpos-1] == '.') { 440 | /* Start of name or has dot before matching topdomain */ 441 | return qpos; 442 | } 443 | /* Query name has longer chunk than topdomain */ 444 | return -1; 445 | } 446 | tpos--; 447 | qpos--; 448 | } else { 449 | return -1; 450 | } 451 | } 452 | return -1; 453 | } 454 | 455 | #if defined(WINDOWS32) || defined(ANDROID) 456 | #ifndef ANDROID 457 | int 458 | inet_aton(const char *cp, struct in_addr *inp) 459 | { 460 | inp->s_addr = inet_addr(cp); 461 | return inp->s_addr != INADDR_ANY; 462 | } 463 | #endif 464 | 465 | void 466 | vwarn(const char *fmt, va_list list) 467 | { 468 | if (fmt) vfprintf(stderr, fmt, list); 469 | #ifndef ANDROID 470 | if (errno == 0) { 471 | fprintf(stderr, ": WSA error %d\n", WSAGetLastError()); 472 | } else { 473 | fprintf(stderr, ": %s\n", strerror(errno)); 474 | } 475 | #endif 476 | } 477 | 478 | void 479 | warn(const char *fmt, ...) 480 | { 481 | va_list list; 482 | 483 | va_start(list, fmt); 484 | vwarn(fmt, list); 485 | va_end(list); 486 | } 487 | 488 | void 489 | err(int eval, const char *fmt, ...) 490 | { 491 | va_list list; 492 | 493 | va_start(list, fmt); 494 | vwarn(fmt, list); 495 | va_end(list); 496 | exit(eval); 497 | } 498 | 499 | void 500 | vwarnx(const char *fmt, va_list list) 501 | { 502 | if (fmt) vfprintf(stderr, fmt, list); 503 | fprintf(stderr, "\n"); 504 | } 505 | 506 | void 507 | warnx(const char *fmt, ...) 508 | { 509 | va_list list; 510 | 511 | va_start(list, fmt); 512 | vwarnx(fmt, list); 513 | va_end(list); 514 | } 515 | 516 | void 517 | errx(int eval, const char *fmt, ...) 518 | { 519 | va_list list; 520 | 521 | va_start(list, fmt); 522 | vwarnx(fmt, list); 523 | va_end(list); 524 | exit(eval); 525 | } 526 | #endif 527 | 528 | 529 | int recent_seqno(int ourseqno, int gotseqno) 530 | /* Return 1 if we've seen gotseqno recently (current or up to 3 back). 531 | Return 0 if gotseqno is new (or very old). 532 | */ 533 | { 534 | int i; 535 | for (i = 0; i < 4; i++, ourseqno--) { 536 | if (ourseqno < 0) 537 | ourseqno = 7; 538 | if (gotseqno == ourseqno) 539 | return 1; 540 | } 541 | return 0; 542 | } 543 | 544 | #ifndef WINDOWS32 545 | /* Set FD_CLOEXEC flag on file descriptor. 546 | * This stops it from being inherited by system() calls. 547 | */ 548 | void 549 | fd_set_close_on_exec(int fd) 550 | { 551 | int flags; 552 | 553 | flags = fcntl(fd, F_GETFD); 554 | if (flags == -1) 555 | err(4, "Failed to get fd flags"); 556 | flags |= FD_CLOEXEC; 557 | if (fcntl(fd, F_SETFD, flags) == -1) 558 | err(4, "Failed to set fd flags"); 559 | } 560 | #endif 561 | 562 | -------------------------------------------------------------------------------- /src/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2015 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef __COMMON_H__ 19 | #define __COMMON_H__ 20 | 21 | /* Last byte of raw header is the command */ 22 | #define RAW_HDR_LEN 4 23 | #define RAW_HDR_IDENT_LEN 3 24 | #define RAW_HDR_CMD 3 25 | #define RAW_HDR_CMD_LOGIN 0x10 26 | #define RAW_HDR_CMD_DATA 0x20 27 | #define RAW_HDR_CMD_PING 0x30 28 | 29 | #define RAW_HDR_CMD_MASK 0xF0 30 | #define RAW_HDR_USR_MASK 0x0F 31 | #define RAW_HDR_GET_CMD(x) ((x)[RAW_HDR_CMD] & RAW_HDR_CMD_MASK) 32 | #define RAW_HDR_GET_USR(x) ((x)[RAW_HDR_CMD] & RAW_HDR_USR_MASK) 33 | extern const unsigned char raw_header[RAW_HDR_LEN]; 34 | 35 | #include 36 | #ifdef WINDOWS32 37 | #include "windows.h" 38 | #else 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #endif 45 | 46 | #define DNS_PORT 53 47 | 48 | #ifndef MIN 49 | #define MIN(a,b) ((a)<(b)?(a):(b)) 50 | #endif 51 | #ifndef MAX 52 | #define MAX(a,b) ((a)>(b)?(a):(b)) 53 | #endif 54 | 55 | #define QUERY_NAME_SIZE 256 56 | 57 | #if defined IP_MTU_DISCOVER 58 | /* Linux */ 59 | # define IP_OPT_DONT_FRAG IP_MTU_DISCOVER 60 | # define DONT_FRAG_VALUE IP_PMTUDISC_DO 61 | #elif defined IP_DONTFRAG 62 | /* FreeBSD */ 63 | # define IP_OPT_DONT_FRAG IP_DONTFRAG 64 | # define DONT_FRAG_VALUE 1 65 | #elif defined IP_DONTFRAGMENT 66 | /* Winsock2 */ 67 | # define IP_OPT_DONT_FRAG IP_DONTFRAGMENT 68 | # define DONT_FRAG_VALUE 1 69 | #endif 70 | 71 | #define T_PRIVATE 65399 72 | /* Undefined RR type; "private use" range, see 73 | * http://www.bind9.net/dns-parameters */ 74 | #define T_UNSET 65432 75 | /* Unused RR type, never actually sent */ 76 | 77 | struct packet 78 | { 79 | int len; /* Total packet length */ 80 | int sentlen; /* Length of chunk currently transmitted */ 81 | int offset; /* Current offset */ 82 | char data[64*1024]; /* The data */ 83 | char seqno; /* The packet sequence number */ 84 | char fragment; /* Fragment index */ 85 | }; 86 | 87 | struct query { 88 | char name[QUERY_NAME_SIZE]; 89 | unsigned short type; 90 | unsigned short rcode; 91 | unsigned short id; 92 | struct sockaddr_storage destination; 93 | socklen_t dest_len; 94 | struct sockaddr_storage from; 95 | socklen_t fromlen; 96 | unsigned short id2; 97 | struct sockaddr_storage from2; 98 | socklen_t fromlen2; 99 | }; 100 | 101 | enum connection { 102 | CONN_RAW_UDP = 0, 103 | CONN_DNS_NULL, 104 | CONN_MAX 105 | }; 106 | 107 | #ifdef WINDOWS32 108 | static inline void check_superuser(void) 109 | { 110 | } 111 | #else 112 | void check_superuser(void); 113 | #endif 114 | char *format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len); 115 | int get_addr(char *, int, int, int, struct sockaddr_storage *); 116 | int open_dns(struct sockaddr_storage *, size_t); 117 | int open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, 118 | int v6only); 119 | int open_dns_from_host(char *host, int port, int addr_family, int flags); 120 | void close_dns(int); 121 | 122 | void do_chroot(char *); 123 | void do_setcon(char *); 124 | void do_detach(void); 125 | void do_pidfile(char *); 126 | 127 | void read_password(char*, size_t); 128 | 129 | int check_topdomain(char *, int, char **); 130 | 131 | int query_datalen(const char *qname, const char *topdomain); 132 | 133 | #if defined(WINDOWS32) || defined(ANDROID) 134 | #ifndef ANDROID 135 | int inet_aton(const char *cp, struct in_addr *inp); 136 | #endif 137 | 138 | void vwarn(const char *fmt, va_list list); 139 | void warn(const char *fmt, ...); 140 | void err(int eval, const char *fmt, ...); 141 | void vwarnx(const char *fmt, va_list list); 142 | void warnx(const char *fmt, ...); 143 | void errx(int eval, const char *fmt, ...); 144 | #endif 145 | 146 | int recent_seqno(int , int); 147 | 148 | #ifndef WINDOWS32 149 | void fd_set_close_on_exec(int fd); 150 | #endif 151 | 152 | #endif 153 | -------------------------------------------------------------------------------- /src/dns.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef __DNS_H__ 19 | #define __DNS_H__ 20 | 21 | #include "common.h" 22 | 23 | typedef enum { 24 | QR_QUERY = 0, 25 | QR_ANSWER = 1 26 | } qr_t; 27 | 28 | extern int dnsc_use_edns0; 29 | 30 | int dns_encode(char *, size_t, struct query *, qr_t, const char *, size_t); 31 | int dns_encode_ns_response(char *buf, size_t buflen, struct query *q, 32 | char *topdomain); 33 | int dns_encode_a_response(char *buf, size_t buflen, struct query *q); 34 | unsigned short dns_get_id(char *packet, size_t packetlen); 35 | int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t); 36 | 37 | #endif /* _DNS_H_ */ 38 | -------------------------------------------------------------------------------- /src/encoding.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include "common.h" 20 | #include "encoding.h" 21 | 22 | int build_hostname(char *buf, size_t buflen, const char *data, 23 | const size_t datalen, const char *topdomain, 24 | const struct encoder *encoder, int maxlen) 25 | { 26 | size_t space; 27 | char *b; 28 | 29 | space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8; 30 | /* 8 = 5 max header length + 1 dot before topdomain + 2 safety */ 31 | 32 | if (!encoder->places_dots) 33 | space -= (space / 57); /* space for dots */ 34 | 35 | memset(buf, 0, buflen); 36 | 37 | encoder->encode(buf, &space, data, datalen); 38 | 39 | if (!encoder->places_dots) 40 | inline_dotify(buf, buflen); 41 | 42 | b = buf; 43 | b += strlen(buf); 44 | 45 | /* move b back one step to see if the dot is there */ 46 | b--; 47 | if (*b != '.') 48 | *++b = '.'; 49 | b++; 50 | /* move b ahead of the string so we can copy to it */ 51 | 52 | strncpy(b, topdomain, strlen(topdomain)+1); 53 | 54 | return space; 55 | } 56 | 57 | int unpack_data(char *buf, size_t buflen, char *data, size_t datalen, 58 | const struct encoder *enc) 59 | { 60 | if (!enc->eats_dots) 61 | datalen = inline_undotify(data, datalen); 62 | return enc->decode(buf, &buflen, data, datalen); 63 | } 64 | 65 | int inline_dotify(char *buf, size_t buflen) 66 | { 67 | unsigned dots; 68 | unsigned pos; 69 | unsigned total; 70 | char *reader, *writer; 71 | 72 | total = strlen(buf); 73 | dots = total / 57; 74 | 75 | writer = buf; 76 | writer += total; 77 | writer += dots; 78 | 79 | total += dots; 80 | if (strlen(buf) + dots > buflen) { 81 | writer = buf; 82 | writer += buflen; 83 | total = buflen; 84 | } 85 | 86 | reader = writer - dots; 87 | pos = (unsigned) (reader - buf) + 1; 88 | 89 | while (dots) { 90 | *writer-- = *reader--; 91 | pos--; 92 | if (pos % 57 == 0) { 93 | *writer-- = '.'; 94 | dots--; 95 | } 96 | } 97 | 98 | /* return new length of string */ 99 | return total; 100 | } 101 | 102 | int inline_undotify(char *buf, size_t len) 103 | { 104 | unsigned pos; 105 | unsigned dots; 106 | char *reader, *writer; 107 | 108 | writer = buf; 109 | reader = writer; 110 | 111 | pos = 0; 112 | dots = 0; 113 | 114 | while (pos < len) { 115 | if (*reader == '.') { 116 | reader++; 117 | pos++; 118 | dots++; 119 | continue; 120 | } 121 | *writer++ = *reader++; 122 | pos++; 123 | } 124 | 125 | /* return new length of string */ 126 | return len - dots; 127 | } 128 | -------------------------------------------------------------------------------- /src/encoding.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman 3 | * 2006-2009 Bjorn Andersson 4 | * Copyright (c) 2017 Ralf Ramsauer 5 | * 6 | * Authors: 7 | * Bjorn Andersson 8 | * Erok Ekman , 9 | * Ralf Ramsauer 10 | * 11 | * Permission to use, copy, modify, and/or distribute this software for any 12 | * purpose with or without fee is hereby granted, provided that the above 13 | * copyright notice and this permission notice appear in all copies. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | 24 | #ifndef _ENCODING_H_ 25 | #define _ENCODING_H_ 26 | 27 | #include 28 | 29 | /* All-0, all-1, 01010101, 10101010: each 4 times to make sure the pattern 30 | spreads across multiple encoded chars -> 16 bytes total. 31 | Followed by 32 bytes from my /dev/random; should be enough. 32 | */ 33 | #define DOWNCODECCHECK1 \ 34 | "\000\000\000\000\377\377\377\377\125\125\125\125\252\252\252\252" \ 35 | "\201\143\310\322\307\174\262\027\137\117\316\311\111\055\122\041" \ 36 | "\141\251\161\040\045\263\006\163\346\330\104\060\171\120\127\277" 37 | #define DOWNCODECCHECK1_LEN 48 38 | 39 | struct encoder { 40 | const char name[8]; 41 | int (*encode)(char *dst, size_t *dstlen, const void *src, size_t srclen); 42 | int (*decode)(void *dst, size_t *dstlen, const char *src, size_t srclen); 43 | 44 | const bool places_dots; 45 | const bool eats_dots; 46 | 47 | const int blocksize_raw; 48 | const int blocksize_encoded; 49 | }; 50 | 51 | int build_hostname(char *, size_t, const char *, const size_t, const char *, 52 | const struct encoder *, int); 53 | int unpack_data(char *, size_t, char *, size_t, const struct encoder *); 54 | int inline_dotify(char *, size_t); 55 | int inline_undotify(char *, size_t); 56 | 57 | extern const struct encoder base32_ops; 58 | extern const struct encoder base64_ops; 59 | extern const struct encoder base64u_ops; 60 | extern const struct encoder base128_ops; 61 | 62 | int b32_5to8(int); 63 | int b32_8to5(int); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /src/fw_query.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2014 Erik Ekman 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include "fw_query.h" 19 | 20 | static struct fw_query fwq[FW_QUERY_CACHE_SIZE]; 21 | static int fwq_ix; 22 | 23 | void fw_query_init(void) 24 | { 25 | memset(fwq, 0, sizeof(struct fw_query) * FW_QUERY_CACHE_SIZE); 26 | fwq_ix = 0; 27 | } 28 | 29 | void fw_query_put(struct fw_query *fw_query) 30 | { 31 | memcpy(&(fwq[fwq_ix]), fw_query, sizeof(struct fw_query)); 32 | 33 | ++fwq_ix; 34 | if (fwq_ix >= FW_QUERY_CACHE_SIZE) 35 | fwq_ix = 0; 36 | } 37 | 38 | void fw_query_get(unsigned short query_id, struct fw_query **fw_query) 39 | { 40 | int i; 41 | 42 | *fw_query = NULL; 43 | for (i = 0; i < FW_QUERY_CACHE_SIZE; i++) { 44 | if (fwq[i].id == query_id) { 45 | *fw_query = &(fwq[i]); 46 | return; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/fw_query.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2014 Erik Ekman 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #ifndef __FW_QUERY_H__ 18 | #define __FW_QUERY_H__ 19 | 20 | #include 21 | #ifdef WINDOWS32 22 | #include "windows.h" 23 | #include 24 | #else 25 | #include 26 | #endif 27 | 28 | #define FW_QUERY_CACHE_SIZE 16 29 | 30 | struct fw_query { 31 | struct sockaddr_storage addr; 32 | int addrlen; 33 | unsigned short id; 34 | }; 35 | 36 | void fw_query_init(void); 37 | void fw_query_put(struct fw_query *fw_query); 38 | void fw_query_get(unsigned short query_id, struct fw_query **fw_query); 39 | 40 | #endif /*__FW_QUERY_H__*/ 41 | 42 | -------------------------------------------------------------------------------- /src/iodine.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #ifdef WINDOWS32 32 | #include "windows.h" 33 | #include 34 | #else 35 | #include 36 | #include 37 | #include 38 | #endif 39 | 40 | #include "common.h" 41 | #include "tun.h" 42 | #include "client.h" 43 | #include "util.h" 44 | 45 | #ifdef WINDOWS32 46 | WORD req_version = MAKEWORD(2, 2); 47 | WSADATA wsa_data; 48 | #endif 49 | 50 | #if !defined(BSD) && !defined(__GLIBC__) 51 | static char *__progname; 52 | #else 53 | extern char *__progname; 54 | #endif 55 | 56 | #define PASSWORD_ENV_VAR "IODINE_PASS" 57 | 58 | static void 59 | sighandler(int sig) 60 | { 61 | client_stop(); 62 | } 63 | 64 | #if defined(__GNUC__) || defined(__clang__) 65 | /* mark as no return to help some compilers to avoid warnings 66 | * about use of uninitialized variables */ 67 | static inline void usage(void) __attribute__((noreturn)); 68 | static inline void help(FILE * stream, bool verbose) __attribute__((noreturn)); 69 | #endif 70 | 71 | static void help(FILE *stream, bool verbose) 72 | { 73 | fprintf(stream, 74 | "iodine IP over DNS tunneling client\n\n" 75 | "Usage: %s [-46fhrv] [-u user] [-t chrootdir] [-d device] [-P password]\n" 76 | " [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-I sec]\n" 77 | " [-z context] [-F pidfile] [nameserver] topdomain\n", __progname); 78 | 79 | if (!verbose) 80 | exit(2); 81 | 82 | fprintf(stream, 83 | "\nOptions to try if connection doesn't work:\n" 84 | " -4 to connect only to IPv4\n" 85 | " -6 to connect only to IPv6\n" 86 | " -T force dns type: NULL, PRIVATE, TXT, SRV, MX, CNAME, A (default: autodetect)\n" 87 | " -O force downstream encoding for -T other than NULL: Base32, Base64, Base64u,\n" 88 | " Base128, or (only for TXT:) Raw (default: autodetect)\n" 89 | " -I max interval between requests (default 4 sec) to prevent DNS timeouts\n" 90 | " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n" 91 | " -m max size of downstream fragments (default: autodetect)\n" 92 | " -M max size of upstream hostnames (~100-255, default: 255)\n" 93 | " -r to skip raw UDP mode attempt\n" 94 | " -P password used for authentication (max 32 chars will be used)\n\n" 95 | "Other options:\n" 96 | " -v to print version info and exit\n" 97 | " -h to print this help and exit\n" 98 | " -f to keep running in foreground\n" 99 | " -u name to drop privileges and run as user 'name'\n" 100 | " -t dir to chroot to directory dir\n" 101 | " -d device to set tunnel device name\n" 102 | " -z context, to apply specified SELinux context after initialization\n" 103 | " -F pidfile to write pid to a file\n\n" 104 | "nameserver is the IP number/hostname of the relaying nameserver. If absent,\n" 105 | " /etc/resolv.conf is used\n" 106 | "topdomain is the FQDN that is delegated to the tunnel endpoint.\n"); 107 | 108 | exit(0); 109 | } 110 | 111 | static inline void usage(void) 112 | { 113 | help(stderr, false); 114 | } 115 | 116 | static void version(void) 117 | { 118 | fprintf(stderr, "iodine IP over DNS tunneling client\n" 119 | "Git version: %s\n", GITREVISION); 120 | 121 | exit(0); 122 | } 123 | 124 | int main(int argc, char **argv) 125 | { 126 | char *nameserv_host; 127 | char *topdomain; 128 | char *errormsg; 129 | #ifndef WINDOWS32 130 | struct passwd *pw; 131 | #endif 132 | char *username; 133 | char password[33]; 134 | int foreground; 135 | char *newroot; 136 | char *context; 137 | char *device; 138 | char *pidfile; 139 | int choice; 140 | int tun_fd; 141 | int dns_fd; 142 | int max_downstream_frag_size; 143 | int autodetect_frag_size; 144 | int retval; 145 | int raw_mode; 146 | int lazymode; 147 | int selecttimeout; 148 | int hostname_maxlen; 149 | #ifdef OPENBSD 150 | int rtable = 0; 151 | #endif 152 | struct sockaddr_storage nameservaddr; 153 | int nameservaddr_len; 154 | int nameserv_family; 155 | 156 | nameserv_host = NULL; 157 | topdomain = NULL; 158 | errormsg = NULL; 159 | #ifndef WINDOWS32 160 | pw = NULL; 161 | #endif 162 | username = NULL; 163 | memset(password, 0, 33); 164 | srand(time(NULL)); 165 | foreground = 0; 166 | newroot = NULL; 167 | context = NULL; 168 | device = NULL; 169 | pidfile = NULL; 170 | 171 | autodetect_frag_size = 1; 172 | max_downstream_frag_size = 3072; 173 | retval = 0; 174 | raw_mode = 1; 175 | lazymode = 1; 176 | selecttimeout = 4; 177 | hostname_maxlen = 0xFF; 178 | nameserv_family = AF_UNSPEC; 179 | 180 | #ifdef WINDOWS32 181 | WSAStartup(req_version, &wsa_data); 182 | #endif 183 | 184 | srand((unsigned) time(NULL)); 185 | client_init(); 186 | 187 | #if !defined(BSD) && !defined(__GLIBC__) 188 | __progname = strrchr(argv[0], '/'); 189 | if (__progname == NULL) 190 | __progname = argv[0]; 191 | else 192 | __progname++; 193 | #endif 194 | 195 | while ((choice = getopt(argc, argv, "46vfhru:t:d:R:P:m:M:F:T:O:L:I:")) != -1) { 196 | switch(choice) { 197 | case '4': 198 | nameserv_family = AF_INET; 199 | break; 200 | case '6': 201 | nameserv_family = AF_INET6; 202 | break; 203 | case 'v': 204 | version(); 205 | /* NOTREACHED */ 206 | break; 207 | case 'f': 208 | foreground = 1; 209 | break; 210 | case 'h': 211 | help(stdout, true); 212 | /* NOTREACHED */ 213 | break; 214 | case 'r': 215 | raw_mode = 0; 216 | break; 217 | case 'u': 218 | username = optarg; 219 | break; 220 | case 't': 221 | newroot = optarg; 222 | break; 223 | case 'd': 224 | device = optarg; 225 | break; 226 | #ifdef OPENBSD 227 | case 'R': 228 | rtable = atoi(optarg); 229 | break; 230 | #endif 231 | case 'P': 232 | strncpy(password, optarg, sizeof(password)); 233 | password[sizeof(password)-1] = 0; 234 | 235 | /* XXX: find better way of cleaning up ps(1) */ 236 | memset(optarg, 0, strlen(optarg)); 237 | break; 238 | case 'm': 239 | autodetect_frag_size = 0; 240 | max_downstream_frag_size = atoi(optarg); 241 | break; 242 | case 'M': 243 | hostname_maxlen = atoi(optarg); 244 | if (hostname_maxlen > 255) 245 | hostname_maxlen = 255; 246 | if (hostname_maxlen < 10) 247 | hostname_maxlen = 10; 248 | break; 249 | case 'z': 250 | context = optarg; 251 | break; 252 | case 'F': 253 | pidfile = optarg; 254 | break; 255 | case 'T': 256 | if (client_set_qtype(optarg)) 257 | errx(5, "Invalid query type '%s'", optarg); 258 | break; 259 | case 'O': /* not -D, is Debug in server */ 260 | client_set_downenc(optarg); 261 | break; 262 | case 'L': 263 | lazymode = atoi(optarg); 264 | if (lazymode > 1) 265 | lazymode = 1; 266 | if (lazymode < 0) 267 | lazymode = 0; 268 | if (!lazymode) 269 | selecttimeout = 1; 270 | break; 271 | case 'I': 272 | selecttimeout = atoi(optarg); 273 | if (selecttimeout < 1) 274 | selecttimeout = 1; 275 | break; 276 | default: 277 | usage(); 278 | /* NOTREACHED */ 279 | } 280 | } 281 | 282 | check_superuser(); 283 | 284 | argc -= optind; 285 | argv += optind; 286 | 287 | switch (argc) { 288 | case 1: 289 | nameserv_host = get_resolvconf_addr(); 290 | topdomain = strdup(argv[0]); 291 | break; 292 | case 2: 293 | nameserv_host = argv[0]; 294 | topdomain = strdup(argv[1]); 295 | break; 296 | default: 297 | usage(); 298 | /* NOTREACHED */ 299 | } 300 | 301 | if (max_downstream_frag_size < 1 || max_downstream_frag_size > 0xffff) { 302 | warnx("Use a max frag size between 1 and 65535 bytes.\n"); 303 | usage(); 304 | /* NOTREACHED */ 305 | } 306 | 307 | if (nameserv_host) { 308 | nameservaddr_len = get_addr(nameserv_host, DNS_PORT, nameserv_family, 0, &nameservaddr); 309 | if (nameservaddr_len < 0) { 310 | errx(1, "Cannot lookup nameserver '%s': %s ", 311 | nameserv_host, gai_strerror(nameservaddr_len)); 312 | } 313 | client_set_nameserver(&nameservaddr, nameservaddr_len); 314 | } else { 315 | warnx("No nameserver found - not connected to any network?\n"); 316 | usage(); 317 | /* NOTREACHED */ 318 | } 319 | 320 | if (check_topdomain(topdomain, 0, &errormsg)) { 321 | warnx("Invalid topdomain: %s", errormsg); 322 | usage(); 323 | /* NOTREACHED */ 324 | } 325 | 326 | client_set_selecttimeout(selecttimeout); 327 | client_set_lazymode(lazymode); 328 | client_set_topdomain(topdomain); 329 | client_set_hostname_maxlen(hostname_maxlen); 330 | 331 | if (username != NULL) { 332 | #ifndef WINDOWS32 333 | if ((pw = getpwnam(username)) == NULL) { 334 | warnx("User %s does not exist!\n", username); 335 | usage(); 336 | /* NOTREACHED */ 337 | } 338 | #endif 339 | } 340 | 341 | if (strlen(password) == 0) { 342 | if (NULL != getenv(PASSWORD_ENV_VAR)) 343 | snprintf(password, sizeof(password), "%s", getenv(PASSWORD_ENV_VAR)); 344 | else 345 | read_password(password, sizeof(password)); 346 | } 347 | 348 | client_set_password(password); 349 | 350 | if ((tun_fd = open_tun(device)) == -1) { 351 | retval = 1; 352 | goto cleanup1; 353 | } 354 | if ((dns_fd = open_dns_from_host(NULL, 0, nameservaddr.ss_family, AI_PASSIVE)) < 0) { 355 | retval = 1; 356 | goto cleanup2; 357 | } 358 | #ifdef OPENBSD 359 | if (rtable > 0) 360 | socket_setrtable(dns_fd, rtable); 361 | #endif 362 | 363 | signal(SIGINT, sighandler); 364 | signal(SIGTERM, sighandler); 365 | 366 | fprintf(stderr, "Sending DNS queries for %s to %s\n", 367 | topdomain, format_addr(&nameservaddr, nameservaddr_len)); 368 | 369 | if (client_handshake(dns_fd, raw_mode, autodetect_frag_size, max_downstream_frag_size)) { 370 | retval = 1; 371 | goto cleanup2; 372 | } 373 | 374 | if (client_get_conn() == CONN_RAW_UDP) { 375 | fprintf(stderr, "Sending raw traffic directly to %s\n", client_get_raw_addr()); 376 | } 377 | 378 | fprintf(stderr, "Connection setup complete, transmitting data.\n"); 379 | 380 | if (foreground == 0) 381 | do_detach(); 382 | 383 | if (pidfile != NULL) 384 | do_pidfile(pidfile); 385 | 386 | if (newroot != NULL) 387 | do_chroot(newroot); 388 | 389 | if (username != NULL) { 390 | #ifndef WINDOWS32 391 | gid_t gids[1]; 392 | gids[0] = pw->pw_gid; 393 | if (setgroups(1, gids) < 0 || setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0) { 394 | warnx("Could not switch to user %s!\n", username); 395 | usage(); 396 | /* NOTREACHED */ 397 | } 398 | #endif 399 | } 400 | 401 | if (context != NULL) 402 | do_setcon(context); 403 | 404 | client_tunnel(tun_fd, dns_fd); 405 | 406 | cleanup2: 407 | close_dns(dns_fd); 408 | close_tun(tun_fd); 409 | cleanup1: 410 | 411 | return retval; 412 | } 413 | 414 | -------------------------------------------------------------------------------- /src/login.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #ifdef WINDOWS32 22 | #include "windows.h" 23 | #else 24 | #include 25 | #include 26 | #endif 27 | 28 | #include "login.h" 29 | #include "md5.h" 30 | 31 | /* 32 | * Needs a 16byte array for output, and 32 bytes password 33 | */ 34 | void 35 | login_calculate(char *buf, int buflen, const char *pass, int seed) 36 | { 37 | unsigned char temp[32]; 38 | md5_state_t ctx; 39 | int *ix; 40 | int i; 41 | int k; 42 | 43 | if (buflen < 16) 44 | return; 45 | 46 | memcpy(temp, pass, 32); 47 | ix = (int*) temp; 48 | 49 | for (i = 0; i < 8; i++) { 50 | k = ntohl(*ix); 51 | k ^= seed; 52 | *ix++ = htonl(k); 53 | } 54 | 55 | md5_init(&ctx); 56 | md5_append(&ctx, temp, 32); 57 | md5_finish(&ctx, (unsigned char *) buf); 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/login.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef __LOGIN_H__ 19 | #define __LOGIN_H__ 20 | 21 | void login_calculate(char *, int, const char *, int); 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /src/md5.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.c is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order 41 | either statically or dynamically; added missing #include 42 | in library. 43 | 2002-03-11 lpd Corrected argument list for main(), and added int return 44 | type, in test program and T value program. 45 | 2002-02-21 lpd Added missing #include in test program. 46 | 2000-07-03 lpd Patched to eliminate warnings about "constant is 47 | unsigned in ANSI C, signed in traditional"; made test program 48 | self-checking. 49 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 50 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). 51 | 1999-05-03 lpd Original version. 52 | */ 53 | 54 | #include "md5.h" 55 | #include 56 | 57 | #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ 58 | #ifdef ARCH_IS_BIG_ENDIAN 59 | # define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) 60 | #else 61 | # define BYTE_ORDER 0 62 | #endif 63 | 64 | #define T_MASK ((md5_word_t)~0) 65 | #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) 66 | #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) 67 | #define T3 0x242070db 68 | #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) 69 | #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) 70 | #define T6 0x4787c62a 71 | #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) 72 | #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) 73 | #define T9 0x698098d8 74 | #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) 75 | #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) 76 | #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) 77 | #define T13 0x6b901122 78 | #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) 79 | #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) 80 | #define T16 0x49b40821 81 | #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) 82 | #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) 83 | #define T19 0x265e5a51 84 | #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) 85 | #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) 86 | #define T22 0x02441453 87 | #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) 88 | #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) 89 | #define T25 0x21e1cde6 90 | #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) 91 | #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) 92 | #define T28 0x455a14ed 93 | #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) 94 | #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) 95 | #define T31 0x676f02d9 96 | #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) 97 | #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) 98 | #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) 99 | #define T35 0x6d9d6122 100 | #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) 101 | #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) 102 | #define T38 0x4bdecfa9 103 | #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) 104 | #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) 105 | #define T41 0x289b7ec6 106 | #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) 107 | #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) 108 | #define T44 0x04881d05 109 | #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) 110 | #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) 111 | #define T47 0x1fa27cf8 112 | #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) 113 | #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) 114 | #define T50 0x432aff97 115 | #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) 116 | #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) 117 | #define T53 0x655b59c3 118 | #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) 119 | #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) 120 | #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) 121 | #define T57 0x6fa87e4f 122 | #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) 123 | #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) 124 | #define T60 0x4e0811a1 125 | #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) 126 | #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) 127 | #define T63 0x2ad7d2bb 128 | #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) 129 | 130 | 131 | static void 132 | md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) 133 | { 134 | md5_word_t 135 | a = pms->abcd[0], b = pms->abcd[1], 136 | c = pms->abcd[2], d = pms->abcd[3]; 137 | md5_word_t t; 138 | #if BYTE_ORDER > 0 139 | /* Define storage only for big-endian CPUs. */ 140 | md5_word_t X[16]; 141 | #else 142 | /* Define storage for little-endian or both types of CPUs. */ 143 | md5_word_t xbuf[16]; 144 | const md5_word_t *X; 145 | #endif 146 | 147 | { 148 | #if BYTE_ORDER == 0 149 | /* 150 | * Determine dynamically whether this is a big-endian or 151 | * little-endian machine, since we can use a more efficient 152 | * algorithm on the latter. 153 | */ 154 | static const int w = 1; 155 | 156 | if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ 157 | #endif 158 | #if BYTE_ORDER <= 0 /* little-endian */ 159 | { 160 | /* 161 | * On little-endian machines, we can process properly aligned 162 | * data without copying it. 163 | */ 164 | if (!((data - (const md5_byte_t *)0) & 3)) { 165 | /* data are properly aligned */ 166 | X = (const md5_word_t *)data; 167 | } else { 168 | /* not aligned */ 169 | memcpy(xbuf, data, 64); 170 | X = xbuf; 171 | } 172 | } 173 | #endif 174 | #if BYTE_ORDER == 0 175 | else /* dynamic big-endian */ 176 | #endif 177 | #if BYTE_ORDER >= 0 /* big-endian */ 178 | { 179 | /* 180 | * On big-endian machines, we must arrange the bytes in the 181 | * right order. 182 | */ 183 | const md5_byte_t *xp = data; 184 | int i; 185 | 186 | # if BYTE_ORDER == 0 187 | X = xbuf; /* (dynamic only) */ 188 | # else 189 | # define xbuf X /* (static only) */ 190 | # endif 191 | for (i = 0; i < 16; ++i, xp += 4) 192 | xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); 193 | } 194 | #endif 195 | } 196 | 197 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 198 | 199 | /* Round 1. */ 200 | /* Let [abcd k s i] denote the operation 201 | a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ 202 | #define F(x, y, z) (((x) & (y)) | (~(x) & (z))) 203 | #define SET(a, b, c, d, k, s, Ti)\ 204 | t = a + F(b,c,d) + X[k] + Ti;\ 205 | a = ROTATE_LEFT(t, s) + b 206 | /* Do the following 16 operations. */ 207 | SET(a, b, c, d, 0, 7, T1); 208 | SET(d, a, b, c, 1, 12, T2); 209 | SET(c, d, a, b, 2, 17, T3); 210 | SET(b, c, d, a, 3, 22, T4); 211 | SET(a, b, c, d, 4, 7, T5); 212 | SET(d, a, b, c, 5, 12, T6); 213 | SET(c, d, a, b, 6, 17, T7); 214 | SET(b, c, d, a, 7, 22, T8); 215 | SET(a, b, c, d, 8, 7, T9); 216 | SET(d, a, b, c, 9, 12, T10); 217 | SET(c, d, a, b, 10, 17, T11); 218 | SET(b, c, d, a, 11, 22, T12); 219 | SET(a, b, c, d, 12, 7, T13); 220 | SET(d, a, b, c, 13, 12, T14); 221 | SET(c, d, a, b, 14, 17, T15); 222 | SET(b, c, d, a, 15, 22, T16); 223 | #undef SET 224 | 225 | /* Round 2. */ 226 | /* Let [abcd k s i] denote the operation 227 | a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ 228 | #define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) 229 | #define SET(a, b, c, d, k, s, Ti)\ 230 | t = a + G(b,c,d) + X[k] + Ti;\ 231 | a = ROTATE_LEFT(t, s) + b 232 | /* Do the following 16 operations. */ 233 | SET(a, b, c, d, 1, 5, T17); 234 | SET(d, a, b, c, 6, 9, T18); 235 | SET(c, d, a, b, 11, 14, T19); 236 | SET(b, c, d, a, 0, 20, T20); 237 | SET(a, b, c, d, 5, 5, T21); 238 | SET(d, a, b, c, 10, 9, T22); 239 | SET(c, d, a, b, 15, 14, T23); 240 | SET(b, c, d, a, 4, 20, T24); 241 | SET(a, b, c, d, 9, 5, T25); 242 | SET(d, a, b, c, 14, 9, T26); 243 | SET(c, d, a, b, 3, 14, T27); 244 | SET(b, c, d, a, 8, 20, T28); 245 | SET(a, b, c, d, 13, 5, T29); 246 | SET(d, a, b, c, 2, 9, T30); 247 | SET(c, d, a, b, 7, 14, T31); 248 | SET(b, c, d, a, 12, 20, T32); 249 | #undef SET 250 | 251 | /* Round 3. */ 252 | /* Let [abcd k s t] denote the operation 253 | a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ 254 | #define H(x, y, z) ((x) ^ (y) ^ (z)) 255 | #define SET(a, b, c, d, k, s, Ti)\ 256 | t = a + H(b,c,d) + X[k] + Ti;\ 257 | a = ROTATE_LEFT(t, s) + b 258 | /* Do the following 16 operations. */ 259 | SET(a, b, c, d, 5, 4, T33); 260 | SET(d, a, b, c, 8, 11, T34); 261 | SET(c, d, a, b, 11, 16, T35); 262 | SET(b, c, d, a, 14, 23, T36); 263 | SET(a, b, c, d, 1, 4, T37); 264 | SET(d, a, b, c, 4, 11, T38); 265 | SET(c, d, a, b, 7, 16, T39); 266 | SET(b, c, d, a, 10, 23, T40); 267 | SET(a, b, c, d, 13, 4, T41); 268 | SET(d, a, b, c, 0, 11, T42); 269 | SET(c, d, a, b, 3, 16, T43); 270 | SET(b, c, d, a, 6, 23, T44); 271 | SET(a, b, c, d, 9, 4, T45); 272 | SET(d, a, b, c, 12, 11, T46); 273 | SET(c, d, a, b, 15, 16, T47); 274 | SET(b, c, d, a, 2, 23, T48); 275 | #undef SET 276 | 277 | /* Round 4. */ 278 | /* Let [abcd k s t] denote the operation 279 | a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ 280 | #define I(x, y, z) ((y) ^ ((x) | ~(z))) 281 | #define SET(a, b, c, d, k, s, Ti)\ 282 | t = a + I(b,c,d) + X[k] + Ti;\ 283 | a = ROTATE_LEFT(t, s) + b 284 | /* Do the following 16 operations. */ 285 | SET(a, b, c, d, 0, 6, T49); 286 | SET(d, a, b, c, 7, 10, T50); 287 | SET(c, d, a, b, 14, 15, T51); 288 | SET(b, c, d, a, 5, 21, T52); 289 | SET(a, b, c, d, 12, 6, T53); 290 | SET(d, a, b, c, 3, 10, T54); 291 | SET(c, d, a, b, 10, 15, T55); 292 | SET(b, c, d, a, 1, 21, T56); 293 | SET(a, b, c, d, 8, 6, T57); 294 | SET(d, a, b, c, 15, 10, T58); 295 | SET(c, d, a, b, 6, 15, T59); 296 | SET(b, c, d, a, 13, 21, T60); 297 | SET(a, b, c, d, 4, 6, T61); 298 | SET(d, a, b, c, 11, 10, T62); 299 | SET(c, d, a, b, 2, 15, T63); 300 | SET(b, c, d, a, 9, 21, T64); 301 | #undef SET 302 | 303 | /* Then perform the following additions. (That is increment each 304 | of the four registers by the value it had before this block 305 | was started.) */ 306 | pms->abcd[0] += a; 307 | pms->abcd[1] += b; 308 | pms->abcd[2] += c; 309 | pms->abcd[3] += d; 310 | } 311 | 312 | void 313 | md5_init(md5_state_t *pms) 314 | { 315 | pms->count[0] = pms->count[1] = 0; 316 | pms->abcd[0] = 0x67452301; 317 | pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; 318 | pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; 319 | pms->abcd[3] = 0x10325476; 320 | } 321 | 322 | void 323 | md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) 324 | { 325 | const md5_byte_t *p = data; 326 | int left = nbytes; 327 | int offset = (pms->count[0] >> 3) & 63; 328 | md5_word_t nbits = (md5_word_t)(nbytes << 3); 329 | 330 | if (nbytes <= 0) 331 | return; 332 | 333 | /* Update the message length. */ 334 | pms->count[1] += nbytes >> 29; 335 | pms->count[0] += nbits; 336 | if (pms->count[0] < nbits) 337 | pms->count[1]++; 338 | 339 | /* Process an initial partial block. */ 340 | if (offset) { 341 | int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); 342 | 343 | memcpy(pms->buf + offset, p, copy); 344 | if (offset + copy < 64) 345 | return; 346 | p += copy; 347 | left -= copy; 348 | md5_process(pms, pms->buf); 349 | } 350 | 351 | /* Process full blocks. */ 352 | for (; left >= 64; p += 64, left -= 64) 353 | md5_process(pms, p); 354 | 355 | /* Process a final partial block. */ 356 | if (left) 357 | memcpy(pms->buf, p, left); 358 | } 359 | 360 | void 361 | md5_finish(md5_state_t *pms, md5_byte_t digest[16]) 362 | { 363 | static const md5_byte_t pad[64] = { 364 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 365 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 366 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 367 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 368 | }; 369 | md5_byte_t data[8]; 370 | int i; 371 | 372 | /* Save the length before padding. */ 373 | for (i = 0; i < 8; ++i) 374 | data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); 375 | /* Pad to 56 bytes mod 64. */ 376 | md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); 377 | /* Append the length. */ 378 | md5_append(pms, data, 8); 379 | for (i = 0; i < 16; ++i) 380 | digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); 381 | } 382 | 383 | 384 | 385 | -------------------------------------------------------------------------------- /src/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | 20 | L. Peter Deutsch 21 | ghost@aladdin.com 22 | 23 | */ 24 | /* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ 25 | /* 26 | Independent implementation of MD5 (RFC 1321). 27 | 28 | This code implements the MD5 Algorithm defined in RFC 1321, whose 29 | text is available at 30 | http://www.ietf.org/rfc/rfc1321.txt 31 | The code is derived from the text of the RFC, including the test suite 32 | (section A.5) but excluding the rest of Appendix A. It does not include 33 | any code or documentation that is identified in the RFC as being 34 | copyrighted. 35 | 36 | The original and principal author of md5.h is L. Peter Deutsch 37 | . Other authors are noted in the change history 38 | that follows (in reverse chronological order): 39 | 40 | 2002-04-13 lpd Removed support for non-ANSI compilers; removed 41 | references to Ghostscript; clarified derivation from RFC 1321; 42 | now handles byte order either statically or dynamically. 43 | 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. 44 | 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); 45 | added conditionalization for C++ compilation from Martin 46 | Purschke . 47 | 1999-05-03 lpd Original version. 48 | */ 49 | 50 | #ifndef md5_INCLUDED 51 | # define md5_INCLUDED 52 | 53 | /* 54 | * This package supports both compile-time and run-time determination of CPU 55 | * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be 56 | * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is 57 | * defined as non-zero, the code will be compiled to run only on big-endian 58 | * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to 59 | * run on either big- or little-endian CPUs, but will run slightly less 60 | * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. 61 | */ 62 | 63 | typedef unsigned char md5_byte_t; /* 8-bit byte */ 64 | typedef unsigned int md5_word_t; /* 32-bit word */ 65 | 66 | /* Define the state of the MD5 Algorithm. */ 67 | typedef struct md5_state_s { 68 | md5_word_t count[2]; /* message length in bits, lsw first */ 69 | md5_word_t abcd[4]; /* digest buffer */ 70 | md5_byte_t buf[64]; /* accumulate block */ 71 | } md5_state_t; 72 | 73 | #ifdef __cplusplus 74 | extern "C" 75 | { 76 | #endif 77 | 78 | /* Initialize the algorithm. */ 79 | void md5_init(md5_state_t *pms); 80 | 81 | /* Append a string to the message. */ 82 | void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); 83 | 84 | /* Finish the message and return the digest. */ 85 | void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); 86 | 87 | #ifdef __cplusplus 88 | } /* end extern "C" */ 89 | #endif 90 | 91 | #endif /* md5_INCLUDED */ 92 | -------------------------------------------------------------------------------- /src/osflags: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | : "${PKG_CONFIG:=pkg-config}" 4 | 5 | case $2 in 6 | link) 7 | 8 | case $1 in 9 | SunOS | solaris) 10 | echo '-lsocket -lnsl'; 11 | ;; 12 | BeOS) 13 | echo '-lsocket -lbind -lbsd'; 14 | ;; 15 | Haiku) 16 | echo '-lnetwork -lbsd'; 17 | ;; 18 | windows32) 19 | echo '-lws2_32 -liphlpapi'; 20 | ;; 21 | Linux) 22 | FLAGS=""; 23 | "$PKG_CONFIG" --exists libselinux && FLAGS="$FLAGS $($PKG_CONFIG --libs libselinux)"; 24 | "$PKG_CONFIG" --exists libsystemd-daemon && FLAGS="$FLAGS $($PKG_CONFIG --libs libsystemd-daemon)"; 25 | "$PKG_CONFIG" --exists libsystemd && FLAGS="$FLAGS $($PKG_CONFIG --libs libsystemd)"; 26 | echo $FLAGS; 27 | ;; 28 | esac 29 | ;; 30 | cflags) 31 | case $1 in 32 | windows32) 33 | echo '-DWINVER=0x0501'; 34 | ;; 35 | BeOS) 36 | echo '-Dsocklen_t=int'; 37 | ;; 38 | Haiku) 39 | echo '-D_DEFAULT_SOURCE'; 40 | ;; 41 | Darwin) 42 | echo '-D__APPLE_USE_RFC_3542'; 43 | ;; 44 | Linux) 45 | FLAGS="-D_GNU_SOURCE" 46 | "$PKG_CONFIG" --exists libselinux && FLAGS="$FLAGS -DHAVE_SETCON"; 47 | "$PKG_CONFIG" --exists libsystemd-daemon && FLAGS="$FLAGS -DHAVE_SYSTEMD"; 48 | "$PKG_CONFIG" --exists libsystemd && FLAGS="$FLAGS -DHAVE_SYSTEMD"; 49 | echo $FLAGS; 50 | ;; 51 | GNU/kFreeBSD|GNU) 52 | echo '-D_GNU_SOURCE' 53 | ;; 54 | esac 55 | ;; 56 | *) 57 | ;; 58 | esac 59 | -------------------------------------------------------------------------------- /src/read.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "read.h" 23 | 24 | static int 25 | readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop) 26 | { 27 | char *dummy; 28 | char *s; 29 | char *d; 30 | int len; 31 | int offset; 32 | char c; 33 | 34 | if (loop <= 0) 35 | return 0; 36 | 37 | len = 0; 38 | s = *src; 39 | d = dst; 40 | while(*s && len < length - 2) { 41 | c = *s++; 42 | 43 | /* is this a compressed label? */ 44 | if ((c & 0xc0) == 0xc0) { 45 | offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff)); 46 | if (offset > packetlen) { 47 | if (len == 0) { 48 | /* Bad jump first in packet */ 49 | return 0; 50 | } else { 51 | /* Bad jump after some data */ 52 | break; 53 | } 54 | } 55 | dummy = packet + offset; 56 | len += readname_loop(packet, packetlen, &dummy, d, length - len, loop - 1); 57 | goto end; 58 | } 59 | 60 | while(c && len < length - 1) { 61 | *d++ = *s++; 62 | len++; 63 | 64 | c--; 65 | } 66 | 67 | if (len >= length - 1) { 68 | break; /* We used up all space */ 69 | } 70 | 71 | if (*s != 0) { 72 | *d++ = '.'; 73 | len++; 74 | } 75 | } 76 | dst[len++] = '\0'; 77 | 78 | end: 79 | (*src) = s+1; 80 | return len; 81 | } 82 | 83 | int 84 | readname(char *packet, int packetlen, char **src, char *dst, size_t length) 85 | { 86 | return readname_loop(packet, packetlen, src, dst, length, 10); 87 | } 88 | 89 | int 90 | readshort(char *packet, char **src, unsigned short *dst) 91 | { 92 | unsigned char *p; 93 | 94 | p = (unsigned char *) *src; 95 | *dst = (p[0] << 8) | p[1]; 96 | 97 | (*src) += sizeof(unsigned short); 98 | return sizeof(unsigned short); 99 | } 100 | 101 | int 102 | readlong(char *packet, char **src, uint32_t *dst) 103 | { 104 | /* A long as described in dns protocol is always 32 bits */ 105 | unsigned char *p; 106 | 107 | p = (unsigned char *) *src; 108 | 109 | *dst = ((uint32_t)p[0] << 24) 110 | | ((uint32_t)p[1] << 16) 111 | | ((uint32_t)p[2] << 8) 112 | | ((uint32_t)p[3]); 113 | 114 | (*src) += sizeof(uint32_t); 115 | return sizeof(uint32_t); 116 | } 117 | 118 | int 119 | readdata(char *packet, char **src, char *dst, size_t len) 120 | { 121 | memcpy(dst, *src, len); 122 | 123 | (*src) += len; 124 | 125 | return len; 126 | } 127 | 128 | int 129 | readtxtbin(char *packet, char **src, size_t srcremain, char *dst, size_t dstremain) 130 | { 131 | unsigned char *uc; 132 | int tocopy; 133 | int dstused = 0; 134 | 135 | while (srcremain > 0) 136 | { 137 | uc = (unsigned char*) (*src); 138 | tocopy = *uc; 139 | (*src)++; 140 | srcremain--; 141 | 142 | if (tocopy > srcremain) 143 | return 0; /* illegal, better have nothing */ 144 | if (tocopy > dstremain) 145 | return 0; /* doesn't fit, better have nothing */ 146 | 147 | memcpy(dst, *src, tocopy); 148 | dst += tocopy; 149 | (*src) += tocopy; 150 | srcremain -= tocopy; 151 | dstremain -= tocopy; 152 | dstused += tocopy; 153 | } 154 | return dstused; 155 | } 156 | 157 | int 158 | putname(char **buf, size_t buflen, const char *host) 159 | { 160 | char *word; 161 | int left; 162 | char *h; 163 | char *p; 164 | 165 | h = strdup(host); 166 | left = buflen; 167 | p = *buf; 168 | 169 | word = strtok(h, "."); 170 | while(word) { 171 | size_t word_len = strlen(word); 172 | if (word_len > 63 || word_len > left) { 173 | free(h); 174 | return -1; 175 | } 176 | 177 | left -= (word_len + 1); 178 | *p++ = (char)word_len; 179 | memcpy(p, word, word_len); 180 | p += word_len; 181 | 182 | word = strtok(NULL, "."); 183 | } 184 | 185 | *p++ = 0; 186 | 187 | free(h); 188 | 189 | *buf = p; 190 | return buflen - left; 191 | } 192 | 193 | int 194 | putbyte(char **dst, unsigned char value) 195 | { 196 | **dst = value; 197 | (*dst)++; 198 | 199 | return sizeof(char); 200 | } 201 | 202 | int 203 | putshort(char **dst, unsigned short value) 204 | { 205 | unsigned char *p; 206 | 207 | p = (unsigned char *) *dst; 208 | 209 | *p++ = (value >> 8); 210 | *p++ = value; 211 | 212 | (*dst) = (char *) p; 213 | return sizeof(short); 214 | } 215 | 216 | int 217 | putlong(char **dst, uint32_t value) 218 | { 219 | /* A long as described in dns protocol is always 32 bits */ 220 | unsigned char *p; 221 | 222 | p = (unsigned char *) *dst; 223 | 224 | *p++ = (value >> 24); 225 | *p++ = (value >> 16); 226 | *p++ = (value >> 8); 227 | *p++ = (value); 228 | 229 | (*dst) = (char *) p; 230 | return sizeof(uint32_t); 231 | } 232 | 233 | int 234 | putdata(char **dst, const char *data, size_t len) 235 | { 236 | memcpy(*dst, data, len); 237 | 238 | (*dst) += len; 239 | return len; 240 | } 241 | 242 | int 243 | puttxtbin(char **buf, size_t bufremain, const char *from, size_t fromremain) 244 | { 245 | unsigned char uc; 246 | unsigned char *ucp = &uc; 247 | char *cp = (char *) ucp; 248 | int tocopy; 249 | int bufused = 0; 250 | 251 | while (fromremain > 0) 252 | { 253 | tocopy = fromremain; 254 | if (tocopy > 252) 255 | tocopy = 252; /* allow off-by-1s in caches etc */ 256 | if (tocopy + 1 > bufremain) 257 | return -1; /* doesn't fit, better have nothing */ 258 | 259 | uc = tocopy; 260 | **buf = *cp; 261 | (*buf)++; 262 | bufremain--; 263 | bufused++; 264 | 265 | memcpy(*buf, from, tocopy); 266 | (*buf) += tocopy; 267 | from += tocopy; 268 | bufremain -= tocopy; 269 | fromremain -= tocopy; 270 | bufused += tocopy; 271 | } 272 | return bufused; 273 | } 274 | -------------------------------------------------------------------------------- /src/read.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef _READ_H_ 19 | #define _READ_H_ 20 | 21 | int readname(char *, int, char **, char *, size_t); 22 | int readshort(char *, char **, unsigned short *); 23 | int readlong(char *, char **, uint32_t *); 24 | int readdata(char *, char **, char *, size_t); 25 | int readtxtbin(char *, char **, size_t, char *, size_t); 26 | 27 | int putname(char **, size_t, const char *); 28 | int putbyte(char **, unsigned char); 29 | int putshort(char **, unsigned short); 30 | int putlong(char **, uint32_t); 31 | int putdata(char **, const char *, size_t); 32 | int puttxtbin(char **, size_t, const char *, size_t); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/tun.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef _TUN_H_ 19 | #define _TUN_H_ 20 | 21 | int open_tun(const char *); 22 | void close_tun(int); 23 | int write_tun(int, char *, size_t); 24 | ssize_t read_tun(int, char *, size_t); 25 | int tun_setip(const char *, const char *, int); 26 | int tun_setmtu(const unsigned); 27 | 28 | #endif /* _TUN_H_ */ 29 | -------------------------------------------------------------------------------- /src/user.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef WINDOWS32 28 | #include 29 | #else 30 | #include 31 | #endif 32 | 33 | #include "common.h" 34 | #include "encoding.h" 35 | #include "user.h" 36 | 37 | struct tun_user *users; 38 | unsigned usercount; 39 | 40 | int init_users(in_addr_t my_ip, int netbits) 41 | { 42 | int i; 43 | int skip = 0; 44 | char newip[32]; 45 | 46 | int maxusers; 47 | 48 | in_addr_t netmask = 0; 49 | struct in_addr net; 50 | struct in_addr ipstart; 51 | 52 | for (i = 0; i < netbits; i++) { 53 | netmask = (netmask << 1) | 1; 54 | } 55 | netmask <<= (32 - netbits); 56 | net.s_addr = htonl(netmask); 57 | ipstart.s_addr = my_ip & net.s_addr; 58 | 59 | maxusers = (1 << (32-netbits)) - 3; /* 3: Net addr, broadcast addr, iodined addr */ 60 | usercount = MIN(maxusers, USERS); 61 | 62 | users = calloc(usercount, sizeof(struct tun_user)); 63 | for (i = 0; i < usercount; i++) { 64 | in_addr_t ip; 65 | users[i].id = i; 66 | snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); 67 | ip = ipstart.s_addr + inet_addr(newip); 68 | if (ip == my_ip && skip == 0) { 69 | /* This IP was taken by iodined */ 70 | skip++; 71 | snprintf(newip, sizeof(newip), "0.0.0.%d", i + skip + 1); 72 | ip = ipstart.s_addr + inet_addr(newip); 73 | } 74 | users[i].tun_ip = ip; 75 | net.s_addr = ip; 76 | users[i].disabled = 0; 77 | users[i].authenticated = 0; 78 | users[i].authenticated_raw = 0; 79 | users[i].options_locked = 0; 80 | users[i].active = 0; 81 | /* Rest is reset on login ('V' packet) */ 82 | } 83 | 84 | return usercount; 85 | } 86 | 87 | const char *users_get_first_ip(void) 88 | { 89 | struct in_addr ip; 90 | ip.s_addr = users[0].tun_ip; 91 | return strdup(inet_ntoa(ip)); 92 | } 93 | 94 | int find_user_by_ip(uint32_t ip) 95 | { 96 | int ret; 97 | int i; 98 | 99 | ret = -1; 100 | for (i = 0; i < usercount; i++) { 101 | if (users[i].active && 102 | users[i].authenticated && 103 | !users[i].disabled && 104 | users[i].last_pkt + 60 > time(NULL) && 105 | ip == users[i].tun_ip) { 106 | ret = i; 107 | break; 108 | } 109 | } 110 | return ret; 111 | } 112 | 113 | /* If this returns true, then reading from tun device is blocked. 114 | So only return true when all clients have at least one packet in 115 | the outpacket-queue, so that sending back-to-back is possible 116 | without going through another select loop. 117 | */ 118 | int all_users_waiting_to_send(void) 119 | { 120 | time_t now; 121 | int ret; 122 | int i; 123 | 124 | ret = 1; 125 | now = time(NULL); 126 | for (i = 0; i < usercount; i++) { 127 | if (users[i].active && !users[i].disabled && 128 | users[i].last_pkt + 60 > now && 129 | ((users[i].conn == CONN_RAW_UDP) || 130 | ((users[i].conn == CONN_DNS_NULL) 131 | #ifdef OUTPACKETQ_LEN 132 | && users[i].outpacketq_filled < 1 133 | #else 134 | && users[i].outpacket.len == 0 135 | #endif 136 | ))) { 137 | 138 | ret = 0; 139 | break; 140 | } 141 | } 142 | return ret; 143 | } 144 | 145 | int find_available_user(void) 146 | { 147 | int ret = -1; 148 | int i; 149 | for (i = 0; i < usercount; i++) { 150 | /* Not used at all or not used in one minute */ 151 | if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) { 152 | users[i].active = 1; 153 | users[i].authenticated = 0; 154 | users[i].authenticated_raw = 0; 155 | users[i].options_locked = 0; 156 | users[i].last_pkt = time(NULL); 157 | users[i].fragsize = 4096; 158 | users[i].conn = CONN_DNS_NULL; 159 | ret = i; 160 | break; 161 | } 162 | } 163 | return ret; 164 | } 165 | 166 | void user_switch_codec(int userid, const struct encoder *enc) 167 | { 168 | if (userid < 0 || userid >= usercount) 169 | return; 170 | 171 | users[userid].encoder = enc; 172 | } 173 | 174 | void user_set_conn_type(int userid, enum connection c) 175 | { 176 | if (userid < 0 || userid >= usercount) 177 | return; 178 | 179 | if (c < CONN_RAW_UDP || c >= CONN_MAX) 180 | return; 181 | 182 | users[userid].conn = c; 183 | } 184 | 185 | -------------------------------------------------------------------------------- /src/user.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef __USER_H__ 19 | #define __USER_H__ 20 | 21 | #define USERS 16 22 | 23 | #define OUTPACKETQ_LEN 4 /* Note: 16 users * 1 packet = 1MB */ 24 | /* Undefine to have no queue for packets coming in from tun device, which may 25 | lead to massive dropping in multi-user situations with high traffic. */ 26 | 27 | #define DNSCACHE_LEN 4 28 | /* Undefine to disable. Should be less than 18; also see comments in iodined.c */ 29 | 30 | 31 | #define QMEMPING_LEN 30 32 | /* Max advisable: 64k/2 = 32000. Total mem usage: QMEMPING_LEN * USERS * 6 bytes */ 33 | 34 | #define QMEMDATA_LEN 15 35 | /* Max advisable: 36/2 = 18. Total mem usage: QMEMDATA_LEN * USERS * 6 bytes */ 36 | 37 | struct tun_user { 38 | char id; 39 | int active; 40 | int authenticated; 41 | int authenticated_raw; 42 | int options_locked; 43 | int disabled; 44 | time_t last_pkt; 45 | int seed; 46 | in_addr_t tun_ip; 47 | struct sockaddr_storage host; 48 | socklen_t hostlen; 49 | struct query q; 50 | struct query q_sendrealsoon; 51 | int q_sendrealsoon_new; 52 | struct packet inpacket; 53 | struct packet outpacket; 54 | int outfragresent; 55 | const struct encoder *encoder; 56 | char downenc; 57 | int out_acked_seqno; 58 | int out_acked_fragment; 59 | int fragsize; 60 | enum connection conn; 61 | int lazy; 62 | unsigned char qmemping_cmc[QMEMPING_LEN * 4]; 63 | unsigned short qmemping_type[QMEMPING_LEN]; 64 | int qmemping_lastfilled; 65 | unsigned char qmemdata_cmc[QMEMDATA_LEN * 4]; 66 | unsigned short qmemdata_type[QMEMDATA_LEN]; 67 | int qmemdata_lastfilled; 68 | #ifdef OUTPACKETQ_LEN 69 | struct packet outpacketq[OUTPACKETQ_LEN]; 70 | int outpacketq_nexttouse; 71 | int outpacketq_filled; 72 | #endif 73 | #ifdef DNSCACHE_LEN 74 | struct query dnscache_q[DNSCACHE_LEN]; 75 | char dnscache_answer[DNSCACHE_LEN][4096]; 76 | int dnscache_answerlen[DNSCACHE_LEN]; 77 | int dnscache_lastfilled; 78 | #endif 79 | }; 80 | 81 | extern struct tun_user *users; 82 | 83 | int init_users(in_addr_t, int); 84 | const char* users_get_first_ip(void); 85 | int find_user_by_ip(uint32_t); 86 | int all_users_waiting_to_send(void); 87 | int find_available_user(void); 88 | void user_switch_codec(int userid, const struct encoder *enc); 89 | void user_set_conn_type(int userid, enum connection c); 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include "common.h" 20 | #include "util.h" 21 | 22 | char *get_resolvconf_addr(void) 23 | { 24 | static char addr[16]; 25 | char *rv = NULL; 26 | #ifndef WINDOWS32 27 | char buf[80]; 28 | FILE *fp; 29 | #ifdef ANDROID 30 | fp = popen("getprop net.dns1", "r"); 31 | if (fp == NULL) 32 | err(1, "getprop net.dns1 failed"); 33 | if (fgets(buf, sizeof(buf), fp) == NULL) 34 | err(1, "read getprop net.dns1 failed"); 35 | if (sscanf(buf, "%15s", addr) == 1) 36 | rv = addr; 37 | pclose(fp); 38 | #else 39 | if ((fp = fopen("/etc/resolv.conf", "r")) == NULL) 40 | err(1, "/etc/resolv.conf"); 41 | 42 | while (feof(fp) == 0) { 43 | fgets(buf, sizeof(buf), fp); 44 | 45 | if (sscanf(buf, "nameserver %15s", addr) == 1) { 46 | rv = addr; 47 | break; 48 | } 49 | } 50 | 51 | fclose(fp); 52 | #endif 53 | #else /* !WINDOWS32 */ 54 | FIXED_INFO *fixed_info; 55 | ULONG buflen; 56 | DWORD ret; 57 | 58 | fixed_info = malloc(sizeof(FIXED_INFO)); 59 | buflen = sizeof(FIXED_INFO); 60 | 61 | if (GetNetworkParams(fixed_info, &buflen) == ERROR_BUFFER_OVERFLOW) { 62 | /* official ugly api workaround */ 63 | free(fixed_info); 64 | fixed_info = malloc(buflen); 65 | } 66 | 67 | ret = GetNetworkParams(fixed_info, &buflen); 68 | if (ret == NO_ERROR) { 69 | strncpy(addr, fixed_info->DnsServerList.IpAddress.String, sizeof(addr)); 70 | addr[15] = 0; 71 | rv = addr; 72 | } 73 | free(fixed_info); 74 | #endif 75 | return rv; 76 | } 77 | 78 | #ifdef OPENBSD 79 | void 80 | socket_setrtable(int fd, int rtable) 81 | { 82 | #ifdef SO_RTABLE 83 | if (setsockopt (fd, IPPROTO_IP, SO_RTABLE, &rtable, sizeof(rtable)) == -1) 84 | err(1, "Failed to set routing table %d", rtable); 85 | #else 86 | fprintf(stderr, "Routing domain support was not available at compile time.\n"); 87 | #endif 88 | } 89 | #endif 90 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef __UTIL_H__ 19 | #define __UTIL_H__ 20 | 21 | char *get_resolvconf_addr(void); 22 | void socket_setrtable(int fd, int rtable); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef _VERSION_H_ 19 | #define _VERSION_H_ 20 | 21 | /* This is the version of the network protocol 22 | It is usually equal to the latest iodine version number */ 23 | #define PROTOCOL_VERSION 0x00000502 24 | 25 | #endif /* _VERSION_H_ */ 26 | 27 | -------------------------------------------------------------------------------- /src/windows.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef __FIX_WINDOWS_H__ 19 | #define __FIX_WINDOWS_H__ 20 | 21 | typedef unsigned int in_addr_t; 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | /* Missing from the mingw headers */ 30 | #ifndef DNS_TYPE_SRV 31 | # define DNS_TYPE_SRV 33 32 | #endif 33 | #ifndef DNS_TYPE_TXT 34 | # define DNS_TYPE_TXT 16 35 | #endif 36 | 37 | #define T_A DNS_TYPE_A 38 | #define T_NS DNS_TYPE_NS 39 | #define T_NULL DNS_TYPE_NULL 40 | #define T_CNAME DNS_TYPE_CNAME 41 | #define T_MX DNS_TYPE_MX 42 | #define T_TXT DNS_TYPE_TXT 43 | #define T_SRV DNS_TYPE_SRV 44 | 45 | #define C_IN 1 46 | 47 | #define FORMERR 1 48 | #define SERVFAIL 2 49 | #define NXDOMAIN 3 50 | #define NOTIMP 4 51 | #define REFUSED 5 52 | 53 | #define sleep(seconds) Sleep((seconds)*1000) 54 | 55 | typedef struct { 56 | unsigned id :16; /* query identification number */ 57 | /* fields in third byte */ 58 | unsigned rd :1; /* recursion desired */ 59 | unsigned tc :1; /* truncated message */ 60 | unsigned aa :1; /* authoritive answer */ 61 | unsigned opcode :4; /* purpose of message */ 62 | unsigned qr :1; /* response flag */ 63 | /* fields in fourth byte */ 64 | unsigned rcode :4; /* response code */ 65 | unsigned cd: 1; /* checking disabled by resolver */ 66 | unsigned ad: 1; /* authentic data from named */ 67 | unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ 68 | unsigned ra :1; /* recursion available */ 69 | /* remaining bytes */ 70 | unsigned qdcount :16; /* number of question entries */ 71 | unsigned ancount :16; /* number of answer entries */ 72 | unsigned nscount :16; /* number of authority entries */ 73 | unsigned arcount :16; /* number of resource entries */ 74 | } HEADER; 75 | 76 | struct ip { 77 | unsigned int ip_hl:4; /* header length */ 78 | unsigned int ip_v:4; /* version */ 79 | u_char ip_tos; /* type of service */ 80 | u_short ip_len; /* total length */ 81 | u_short ip_id; /* identification */ 82 | u_short ip_off; /* fragment offset field */ 83 | #define IP_RF 0x8000 /* reserved fragment flag */ 84 | #define IP_DF 0x4000 /* dont fragment flag */ 85 | #define IP_MF 0x2000 /* more fragments flag */ 86 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ 87 | u_char ip_ttl; /* time to live */ 88 | u_char ip_p; /* protocol */ 89 | u_short ip_sum; /* checksum */ 90 | struct in_addr ip_src, ip_dst; /* source and dest address */ 91 | }; 92 | 93 | DWORD WINAPI tun_reader(LPVOID arg); 94 | struct tun_data { 95 | HANDLE tun; 96 | int sock; 97 | struct sockaddr_storage addr; 98 | int addrlen; 99 | }; 100 | 101 | /* No-op for now. */ 102 | #define syslog(...) 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | TEST = test 2 | OBJS = test.o base32.o base64.o common.o read.o dns.o encoding.o login.o user.o fw_query.o 3 | SRCOBJS = ../src/base32.o ../src/base64.o ../src/common.o ../src/read.o ../src/dns.o ../src/encoding.o ../src/login.o ../src/md5.o ../src/user.o ../src/fw_query.o 4 | 5 | OS = `uname | tr "a-z" "A-Z"` 6 | 7 | CHECK_PATH = /usr/local 8 | LDFLAGS = -L$(CHECK_PATH)/lib `pkg-config check --libs` -lpthread `sh ../src/osflags $(TARGETOS) link` 9 | CFLAGS = -std=c99 -g -Wall -D$(OS) `pkg-config check --cflags` -I../src -I$(CHECK_PATH)/include -pedantic `sh ../src/osflags $(TARGETOS) cflags` 10 | 11 | all: $(TEST) 12 | @LD_LIBRARY_PATH=${CHECK_PATH}/lib ./$(TEST) 13 | 14 | $(TEST): $(OBJS) $(SRCOBJS) 15 | @echo LD $(TEST) 16 | @$(CC) -o $@ $(SRCOBJS) $(OBJS) $(LDFLAGS) 17 | 18 | .c.o: 19 | @echo CC $< 20 | @$(CC) $(CFLAGS) -c $< 21 | 22 | clean: 23 | @echo "Cleaning tests/" 24 | @rm -f *~ *.core $(TEST) $(OBJS) 25 | 26 | -------------------------------------------------------------------------------- /tests/base32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "encoding.h" 25 | #include "test.h" 26 | 27 | #define TUPLES 5 28 | 29 | static struct tuple 30 | { 31 | char *a; 32 | char *b; 33 | } testpairs[TUPLES] = { 34 | { "iodinetestingtesting", "nfxwi0lomv0gk21unfxgo3dfon0gs1th" }, 35 | { "abc123", "mfrggmjsgm" }, 36 | { "test", "orsxg3a" }, 37 | { "tst", "orzxi" }, 38 | { "", "" }, 39 | }; 40 | 41 | START_TEST(test_base32_encode) 42 | { 43 | size_t len; 44 | char buf[4096]; 45 | int val; 46 | 47 | 48 | len = sizeof(buf); 49 | val = base32_ops.encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a)); 50 | 51 | ck_assert(val == strlen(testpairs[_i].b)); 52 | ck_assert_str_eq(buf, testpairs[_i].b); 53 | } 54 | END_TEST 55 | 56 | START_TEST(test_base32_decode) 57 | { 58 | size_t len; 59 | char buf[4096]; 60 | int val; 61 | 62 | len = sizeof(buf); 63 | val = base32_ops.decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b)); 64 | 65 | ck_assert(val == strlen(testpairs[_i].a)); 66 | ck_assert_str_eq(buf, testpairs[_i].a); 67 | } 68 | END_TEST 69 | 70 | START_TEST(test_base32_5to8_8to5) 71 | { 72 | int i; 73 | int c; 74 | 75 | for (i = 0; i < 32; i++) { 76 | c = b32_5to8(i); 77 | ck_assert(b32_8to5(c) == i); 78 | } 79 | } 80 | END_TEST 81 | 82 | START_TEST(test_base32_blksize) 83 | { 84 | size_t rawlen; 85 | size_t enclen; 86 | char *rawbuf; 87 | char *encbuf; 88 | int i; 89 | int val; 90 | 91 | rawlen = base32_ops.blocksize_raw; 92 | enclen = base32_ops.blocksize_encoded; 93 | 94 | rawbuf = malloc(rawlen + 16); 95 | encbuf = malloc(enclen + 16); 96 | 97 | for (i = 0; i < rawlen; i++) { 98 | rawbuf[i] = 'A'; 99 | } 100 | rawbuf[i] = 0; 101 | 102 | val = base32_ops.encode(encbuf, &enclen, rawbuf, rawlen); 103 | 104 | ck_assert_msg(rawlen == 5, "raw length was %zu not 5", rawlen); 105 | ck_assert_msg(enclen == 5, "encoded %zu bytes, not 5", enclen); 106 | ck_assert_msg(val == 8, "encoded string %s was length %d", encbuf, val); 107 | 108 | memset(rawbuf, 0, rawlen + 16); 109 | 110 | enclen = val; 111 | val = base32_ops.decode(rawbuf, &rawlen, encbuf, enclen); 112 | 113 | ck_assert_msg(rawlen == 5, "raw length was %zu not 5", rawlen); 114 | ck_assert_msg(val == 5, "val was not 5 but %d", val); 115 | for (i = 0; i < rawlen; i++) { 116 | ck_assert(rawbuf[i] == 'A'); 117 | } 118 | } 119 | END_TEST 120 | 121 | TCase * 122 | test_base32_create_tests(void) 123 | { 124 | TCase *tc; 125 | 126 | tc = tcase_create("Base32"); 127 | tcase_add_loop_test(tc, test_base32_encode, 0, TUPLES); 128 | tcase_add_loop_test(tc, test_base32_decode, 0, TUPLES); 129 | tcase_add_test(tc, test_base32_5to8_8to5); 130 | tcase_add_test(tc, test_base32_blksize); 131 | 132 | return tc; 133 | } 134 | -------------------------------------------------------------------------------- /tests/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "encoding.h" 25 | #include "test.h" 26 | 27 | #define TUPLES 5 28 | 29 | static struct tuple 30 | { 31 | char *a; 32 | char *b; 33 | } testpairs[TUPLES] = { 34 | { "iodinetestingtesting", "Aw8KAw4LDgvZDgLUz2rLC2rPBMC" }, 35 | { "abc1231", "ywjJmtiZmq" }, 36 | { 37 | "\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68" 38 | "\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50" 39 | "\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78" 40 | "\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60" 41 | "\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48" 42 | "\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70" 43 | "\xBE\xEB\x6C\xAE\xAA\x68\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58" 44 | "\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40", 45 | 46 | "+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ" 47 | "776543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654" 48 | "3210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba" 49 | }, 50 | { 51 | "\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xAA\x68" 52 | "\x9E\x69\x64\x8E\x28\x60\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50" 53 | "\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40\x3F\x3F\x3C\xEF\xAE\x78" 54 | "\xDF\x6D\x74\xCF\x2C\x70\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60" 55 | "\x7D\xE7\x5C\x6D\xA6\x58\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48" 56 | "\x1C\x61\x44\x0C\x20\x40\xFF\xEF\x7C\xEF\xAE\x78\xDF\x6D\x74\xCF\x2C\x70" 57 | "\xBE\xEB\x6C\xAE\xA1\x61\x91\x61\x61\x81\x28\x60\x7D\xE7\x5C\x6D\xA6\x58" 58 | "\x5D\x65\x54\x4D\x24\x50\x3C\xE3\x4C\x2C\xA2\x48\x1C\x61\x44\x0C\x20\x40", 59 | 60 | "+9876543210-ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcbapZ" 61 | "776543210-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba+987654321" 62 | "0-ZYXWVUTSRQfHKwfHGsHGFEDCBAzyxwvutsrqponmlkjihgfedcba" 63 | }, 64 | { "", "" } 65 | }; 66 | 67 | START_TEST(test_base64_encode) 68 | { 69 | size_t len; 70 | char buf[4096]; 71 | int val; 72 | 73 | len = sizeof(buf); 74 | val = base64_ops.encode(buf, &len, testpairs[_i].a, strlen(testpairs[_i].a)); 75 | 76 | ck_assert(val == strlen(testpairs[_i].b)); 77 | ck_assert_str_eq(buf, testpairs[_i].b); 78 | } 79 | END_TEST 80 | 81 | START_TEST(test_base64_decode) 82 | { 83 | size_t len; 84 | char buf[4096]; 85 | int val; 86 | 87 | len = sizeof(buf); 88 | val = base64_ops.decode(buf, &len, testpairs[_i].b, strlen(testpairs[_i].b)); 89 | 90 | ck_assert(val == strlen(testpairs[_i].a)); 91 | ck_assert_str_eq(buf, testpairs[_i].a); 92 | } 93 | END_TEST 94 | 95 | START_TEST(test_base64_blksize) 96 | { 97 | size_t rawlen; 98 | size_t enclen; 99 | char *rawbuf; 100 | char *encbuf; 101 | int i; 102 | int val; 103 | 104 | rawlen = base64_ops.blocksize_raw; 105 | enclen = base64_ops.blocksize_encoded; 106 | 107 | rawbuf = malloc(rawlen + 16); 108 | encbuf = malloc(enclen + 16); 109 | 110 | for (i = 0; i < rawlen; i++) { 111 | rawbuf[i] = 'A'; 112 | } 113 | rawbuf[i] = 0; 114 | 115 | val = base64_ops.encode(encbuf, &enclen, rawbuf, rawlen); 116 | 117 | ck_assert_msg(rawlen == 3, "raw length was %zu not 3", rawlen); 118 | ck_assert_msg(enclen == 3, "encoded %zu bytes, not 3", enclen); 119 | ck_assert_msg(val == 4, "encoded string %s was length %d", encbuf, val); 120 | 121 | memset(rawbuf, 0, rawlen + 16); 122 | 123 | enclen = val; 124 | val = base64_ops.decode(rawbuf, &rawlen, encbuf, enclen); 125 | 126 | ck_assert_msg(rawlen == 3, "raw length was %zu not 3", rawlen); 127 | ck_assert(val == 3); 128 | for (i = 0; i < rawlen; i++) { 129 | ck_assert(rawbuf[i] == 'A'); 130 | } 131 | } 132 | END_TEST 133 | 134 | TCase * 135 | test_base64_create_tests(void) 136 | { 137 | TCase *tc; 138 | 139 | tc = tcase_create("Base64"); 140 | tcase_add_loop_test(tc, test_base64_encode, 0, TUPLES); 141 | tcase_add_loop_test(tc, test_base64_decode, 0, TUPLES); 142 | tcase_add_test(tc, test_base64_blksize); 143 | 144 | return tc; 145 | } 146 | -------------------------------------------------------------------------------- /tests/common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | START_TEST(test_topdomain_ok) 25 | { 26 | char *error = NULL; 27 | 28 | ck_assert(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", 0, &error) == 0); 29 | ck_assert(error == NULL); 30 | /* Allowing wildcard */ 31 | ck_assert(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", 1, &error) == 0); 32 | ck_assert(error == NULL); 33 | 34 | /* Not allowed to start with dot */ 35 | ck_assert(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", 0, &error)); 36 | ck_assert_str_eq("Starts with a dot", error); 37 | 38 | /* Test missing error msg ptr */ 39 | ck_assert(check_topdomain(".foo", 0, NULL)); 40 | } 41 | END_TEST 42 | 43 | START_TEST(test_topdomain_length) 44 | { 45 | char *error; 46 | 47 | /* Test empty and too short */ 48 | ck_assert(check_topdomain("", 0, &error)); 49 | ck_assert_str_eq("Too short (< 3)", error); 50 | error = NULL; 51 | ck_assert(check_topdomain("a", 0, &error)); 52 | ck_assert_str_eq("Too short (< 3)", error); 53 | error = NULL; 54 | ck_assert(check_topdomain(".a", 0, &error)); 55 | ck_assert_str_eq("Too short (< 3)", error); 56 | error = NULL; 57 | ck_assert(check_topdomain("a.", 0, &error)); 58 | ck_assert_str_eq("Too short (< 3)", error); 59 | error = NULL; 60 | ck_assert(check_topdomain("ab", 0, &error)); 61 | ck_assert_str_eq("Too short (< 3)", error); 62 | error = NULL; 63 | ck_assert(check_topdomain("a.b", 0, &error) == 0); 64 | 65 | /* Test too long (over 128, need rest of space for data) */ 66 | ck_assert(check_topdomain( 67 | "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." 68 | "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." 69 | "abcd12345.abcd12345.foo129xxx", 0, &error)); 70 | ck_assert_str_eq("Too long (> 128)", error); 71 | ck_assert(check_topdomain( 72 | "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." 73 | "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." 74 | "abcd12345.abcd12345.foo128xx", 0, &error) == 0); 75 | } 76 | END_TEST 77 | 78 | START_TEST(test_topdomain_chunks) 79 | { 80 | char *error; 81 | 82 | /* Must have at least one dot */ 83 | ck_assert(check_topdomain("abcde.gh", 0, &error) == 0); 84 | ck_assert(check_topdomain("abcdefgh", 0, &error)); 85 | ck_assert_str_eq("No dots", error); 86 | 87 | /* Not two consecutive dots */ 88 | ck_assert(check_topdomain("abc..defgh", 0, &error)); 89 | ck_assert_str_eq("Consecutive dots", error); 90 | 91 | /* Not end with a dots */ 92 | ck_assert(check_topdomain("abc.defgh.", 0, &error)); 93 | ck_assert_str_eq("Ends with a dot", error); 94 | 95 | /* No chunk longer than 63 chars */ 96 | ck_assert(check_topdomain("123456789012345678901234567890" 97 | "123456789012345678901234567890333.com", 0, &error) == 0); 98 | ck_assert(check_topdomain("123456789012345678901234567890" 99 | "1234567890123456789012345678904444.com", 0, &error)); 100 | ck_assert_str_eq("Too long domain part (> 63)", error); 101 | 102 | ck_assert(check_topdomain("abc.123456789012345678901234567890" 103 | "123456789012345678901234567890333.com", 0, &error) == 0); 104 | ck_assert(check_topdomain("abc.123456789012345678901234567890" 105 | "1234567890123456789012345678904444.com", 0, &error)); 106 | ck_assert_str_eq("Too long domain part (> 63)", error); 107 | 108 | ck_assert(check_topdomain("abc.123456789012345678901234567890" 109 | "123456789012345678901234567890333", 0, &error) == 0); 110 | ck_assert(check_topdomain("abc.123456789012345678901234567890" 111 | "1234567890123456789012345678904444", 0, &error)); 112 | ck_assert_str_eq("Too long domain part (> 63)", error); 113 | } 114 | END_TEST 115 | 116 | START_TEST(test_topdomain_wild) 117 | { 118 | char *error = NULL; 119 | 120 | ck_assert(check_topdomain("*.a", 0, &error) == 1); 121 | ck_assert_str_eq("Contains illegal character (allowed: [a-zA-Z0-9-.])", error); 122 | error = NULL; 123 | ck_assert(check_topdomain("*.a", 1, &error) == 0); 124 | ck_assert(error == NULL); 125 | 126 | ck_assert(check_topdomain("b*.a", 0, &error) == 1); 127 | ck_assert_str_eq("Contains illegal character (allowed: [a-zA-Z0-9-.])", error); 128 | error = NULL; 129 | ck_assert(check_topdomain("b*.a", 1, &error) == 1); 130 | ck_assert_str_eq("Wildcard (*) only allowed as first char", error); 131 | 132 | ck_assert(check_topdomain("*b.a", 0, &error) == 1); 133 | ck_assert_str_eq("Contains illegal character (allowed: [a-zA-Z0-9-.])", error); 134 | error = NULL; 135 | ck_assert(check_topdomain("*b.a", 1, &error) == 1); 136 | ck_assert_str_eq("Wildcard (*) must be followed by dot", error); 137 | 138 | ck_assert(check_topdomain("*.*.a", 0, &error) == 1); 139 | ck_assert_str_eq("Contains illegal character (allowed: [a-zA-Z0-9-.])", error); 140 | error = NULL; 141 | ck_assert(check_topdomain("*.*.a", 1, &error) == 1); 142 | ck_assert_str_eq("Wildcard (*) only allowed as first char", error); 143 | } 144 | END_TEST 145 | 146 | START_TEST(test_query_datalen) 147 | { 148 | char *topdomain = "r.foo.com"; 149 | /* With data */ 150 | ck_assert(query_datalen("foobar.r.foo.com", topdomain) == 7); 151 | ck_assert(query_datalen("foobar.r.FoO.Com", topdomain) == 7); 152 | ck_assert(query_datalen("foo.bar.r.FoO.Com", topdomain) == 8); 153 | ck_assert(query_datalen(".r.foo.com", topdomain) == 1); 154 | /* Without data */ 155 | ck_assert(query_datalen("r.foo.com", topdomain) == 0); 156 | ck_assert(query_datalen("R.foo.com", topdomain) == 0); 157 | /* Shorter query name */ 158 | ck_assert(query_datalen("foo.com", topdomain) == -1); 159 | /* Mismatched query name */ 160 | ck_assert(query_datalen("b.foo.com", topdomain) == -1); 161 | ck_assert(query_datalen("*.foo.com", topdomain) == -1); 162 | /* Query name overlaps topdomain, but is longer */ 163 | ck_assert(query_datalen("bar.foo.com", topdomain) == -1); 164 | } 165 | END_TEST 166 | 167 | START_TEST(test_query_datalen_wild) 168 | { 169 | char *topdomain = "*.foo.com"; 170 | /* With data */ 171 | ck_assert(query_datalen("foobar.a.foo.com", topdomain) == 7); 172 | ck_assert(query_datalen("foobar.r.FoO.Com", topdomain) == 7); 173 | ck_assert(query_datalen("foo.bar.r.FoO.Com", topdomain) == 8); 174 | ck_assert(query_datalen("foo.Ab.foo.cOm", topdomain) == 4); 175 | ck_assert(query_datalen("foo.Abcd.Foo.com", topdomain) == 4); 176 | ck_assert(query_datalen("***.STARs.foo.com", topdomain) == 4); 177 | ck_assert(query_datalen(".a.foo.com", topdomain) == 1); 178 | ck_assert(query_datalen(".ab.foo.com", topdomain) == 1); 179 | /* Without data */ 180 | ck_assert(query_datalen("rr.foo.com", topdomain) == 0); 181 | ck_assert(query_datalen("b.foo.com", topdomain) == 0); 182 | ck_assert(query_datalen("B.foo.com", topdomain) == 0); 183 | /* Shorter query name */ 184 | ck_assert(query_datalen("foo.com", topdomain) == -1); 185 | /* Wildcard part of query name matching topdomain */ 186 | ck_assert(query_datalen("aa.*.foo.com", topdomain) == -1); 187 | /* Mismatched query name */ 188 | ck_assert(query_datalen("bar.r.boo.com", topdomain) == -1); 189 | } 190 | END_TEST 191 | 192 | START_TEST(test_parse_format_ipv4) 193 | { 194 | char *host = "192.168.2.10"; 195 | char *formatted; 196 | struct sockaddr_storage addr; 197 | struct sockaddr_in *v4addr; 198 | int addr_len; 199 | 200 | addr_len = get_addr(host, 53, AF_INET, 0, &addr); 201 | ck_assert(addr_len == sizeof(struct sockaddr_in)); 202 | 203 | v4addr = (struct sockaddr_in *) &addr; 204 | ck_assert(v4addr->sin_addr.s_addr == htonl(0xc0a8020a)); 205 | ck_assert(v4addr->sin_port == htons(53)); 206 | 207 | formatted = format_addr(&addr, addr_len); 208 | ck_assert_str_eq(host, formatted); 209 | } 210 | END_TEST 211 | 212 | START_TEST(test_parse_format_ipv4_listen_all) 213 | { 214 | char *host = "0.0.0.0"; 215 | char *formatted; 216 | struct sockaddr_storage addr; 217 | struct sockaddr_in *v4addr; 218 | int addr_len; 219 | 220 | addr_len = get_addr(NULL, 53, AF_INET, AI_PASSIVE, &addr); 221 | ck_assert(addr_len == sizeof(struct sockaddr_in)); 222 | 223 | v4addr = (struct sockaddr_in *) &addr; 224 | ck_assert(v4addr->sin_addr.s_addr == htonl(0x00000000)); 225 | ck_assert(v4addr->sin_port == htons(53)); 226 | 227 | formatted = format_addr(&addr, addr_len); 228 | ck_assert_str_eq(host, formatted); 229 | } 230 | END_TEST 231 | 232 | START_TEST(test_parse_format_ipv6) 233 | { 234 | char *host = "2001:0db8:0505:0::123:0abc"; 235 | char *compact = "2001:db8:505::123:abc"; 236 | unsigned char v6_bits[] = { 237 | 0x20, 0x01, 0x0d, 0xb8, 0x05, 0x05, 0x00, 0x00, 238 | 0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x0a, 0xbc, 239 | }; 240 | char *formatted; 241 | struct sockaddr_storage addr; 242 | struct sockaddr_in6 *v6addr; 243 | int addr_len; 244 | 245 | addr_len = get_addr(host, 53, AF_UNSPEC, 0, &addr); 246 | ck_assert(addr_len == sizeof(struct sockaddr_in6)); 247 | 248 | v6addr = (struct sockaddr_in6 *) &addr; 249 | ck_assert(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)) == 0); 250 | ck_assert(v6addr->sin6_port == htons(53)); 251 | 252 | formatted = format_addr(&addr, addr_len); 253 | ck_assert_str_eq(compact, formatted); 254 | } 255 | END_TEST 256 | 257 | START_TEST(test_parse_format_ipv4_mapped_ipv6) 258 | { 259 | char *v4mapped = "::FFFF:192.168.2.10"; 260 | char *host = "192.168.2.10"; 261 | unsigned char v6_bits[] = { 262 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 263 | 0x00, 0x00, 0xff, 0xff, 0xc0, 0xa8, 0x02, 0x0a, 264 | }; 265 | char *formatted; 266 | struct sockaddr_storage addr; 267 | struct sockaddr_in6 *v6addr; 268 | int addr_len; 269 | 270 | addr_len = get_addr(v4mapped, 53, AF_INET6, 0, &addr); 271 | ck_assert(addr_len == sizeof(struct sockaddr_in6)); 272 | 273 | v6addr = (struct sockaddr_in6 *) &addr; 274 | ck_assert(memcmp(&v6addr->sin6_addr, v6_bits, sizeof(v6_bits)) == 0); 275 | ck_assert(v6addr->sin6_port == htons(53)); 276 | 277 | /* Format as IPv4 address */ 278 | formatted = format_addr(&addr, addr_len); 279 | ck_assert_str_eq(host, formatted); 280 | } 281 | END_TEST 282 | 283 | START_TEST(test_get_addr_err) 284 | { 285 | char *host = "192.168.2.10"; 286 | struct sockaddr_storage addr; 287 | int addr_len; 288 | int flags = AI_PASSIVE; 289 | 290 | /* Invalid host */ 291 | addr_len = get_addr(NULL, -1, flags, 0, &addr); 292 | ck_assert(addr_len == -1); 293 | /* Invalid port */ 294 | addr_len = get_addr(host, -1, flags, 0, &addr); 295 | ck_assert(addr_len == -1); 296 | /* Invalid flag */ 297 | addr_len = get_addr(host, 53, flags | 0xFFF, 0, &addr); 298 | ck_assert(addr_len == -1); 299 | /* Invalid addr */ 300 | addr_len = get_addr(host, 53, flags, 0, (struct sockaddr_storage *)NULL); 301 | ck_assert(addr_len == -1); 302 | } 303 | END_TEST 304 | 305 | TCase * 306 | test_common_create_tests(void) 307 | { 308 | TCase *tc; 309 | int sock; 310 | 311 | tc = tcase_create("Common"); 312 | tcase_add_test(tc, test_topdomain_ok); 313 | tcase_add_test(tc, test_topdomain_length); 314 | tcase_add_test(tc, test_topdomain_chunks); 315 | tcase_add_test(tc, test_topdomain_wild); 316 | tcase_add_test(tc, test_query_datalen); 317 | tcase_add_test(tc, test_query_datalen_wild); 318 | tcase_add_test(tc, test_parse_format_ipv4); 319 | tcase_add_test(tc, test_parse_format_ipv4_listen_all); 320 | tcase_add_test(tc, test_get_addr_err); 321 | 322 | /* Tests require IPv6 support */ 323 | sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 324 | if (sock >= 0) { 325 | close(sock); 326 | tcase_add_test(tc, test_parse_format_ipv6); 327 | tcase_add_test(tc, test_parse_format_ipv4_mapped_ipv6); 328 | } 329 | return tc; 330 | } 331 | -------------------------------------------------------------------------------- /tests/dns.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #ifdef DARWIN 29 | #define BIND_8_COMPAT 30 | #include 31 | #endif 32 | 33 | #include "common.h" 34 | #include "dns.h" 35 | #include "encoding.h" 36 | #include "test.h" 37 | 38 | static void dump_packet(char *, size_t); 39 | 40 | static char query_packet[] = 41 | "\x05\x39\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01\x2D\x41\x6A\x62\x63" 42 | "\x75\x79\x74\x63\x70\x65\x62\x30\x67\x71\x30\x6C\x74\x65\x62\x75\x78" 43 | "\x67\x69\x64\x75\x6E\x62\x73\x73\x61\x33\x64\x66\x6F\x6E\x30\x63\x61" 44 | "\x7A\x64\x62\x6F\x72\x71\x71\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00" 45 | "\x0A\x00\x01\x00\x00\x29\x10\x00\x00\x00\x80\x00\x00\x00"; 46 | 47 | static char answer_packet[] = 48 | "\x05\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C" 49 | "\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04" 50 | "\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01" 51 | "\xC0\x0C\x00\x0A\x00\x01\x00\x00\x00\x00\x00\x23\x74\x68\x69\x73\x20" 52 | "\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F" 53 | "\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64"; 54 | 55 | static char answer_packet_high_trans_id[] = 56 | "\x85\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C" 57 | "\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04" 58 | "\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01" 59 | "\xC0\x0C\x00\x0A\x00\x01\x00\x00\x00\x00\x00\x23\x74\x68\x69\x73\x20" 60 | "\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F" 61 | "\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64"; 62 | static char *msgData = "this is the message to be delivered"; 63 | static char *topdomain = "kryo.se"; 64 | 65 | static char *innerData = "HELLO this is the test data"; 66 | 67 | START_TEST(test_encode_query) 68 | { 69 | char buf[512]; 70 | char resolv[512]; 71 | struct query q; 72 | const struct encoder *enc; 73 | char *d; 74 | size_t len; 75 | size_t enclen; 76 | int ret; 77 | 78 | enclen = sizeof(resolv); 79 | memset(&buf, 0, sizeof(buf)); 80 | memset(&resolv, 0, sizeof(resolv)); 81 | memset(&q, 0, sizeof(struct query)); 82 | q.type = T_NULL; 83 | q.id = 1337; 84 | d = resolv; 85 | enc = &base32_ops; 86 | 87 | *d++ = 'A'; 88 | enc->encode(d, &enclen, innerData, strlen(innerData)); 89 | d = resolv + strlen(resolv); 90 | if (*d != '.') { 91 | *d++ = '.'; 92 | } 93 | strcpy(d, topdomain); 94 | len = sizeof(buf); 95 | ret = dns_encode(buf, len, &q, QR_QUERY, resolv, strlen(resolv)); 96 | len = sizeof(query_packet) - 1; /* Skip extra null character */ 97 | 98 | if (strncmp(query_packet, buf, sizeof(query_packet)) || ret != len) { 99 | printf("\n"); 100 | dump_packet(query_packet, len); 101 | dump_packet(buf, ret); 102 | } 103 | ck_assert_msg(strncmp(query_packet, buf, sizeof(query_packet)) == 0, 104 | "Did not compile expected packet"); 105 | ck_assert_msg(ret == len, 106 | "Bad packet length: %d, expected %zu", ret, len); 107 | } 108 | END_TEST 109 | 110 | START_TEST(test_decode_query) 111 | { 112 | char buf[512]; 113 | char *domain; 114 | struct query q; 115 | const struct encoder *enc; 116 | size_t len; 117 | 118 | memset(&q, 0, sizeof(struct query)); 119 | memset(&buf, 0, sizeof(buf)); 120 | q.id = 0; 121 | len = sizeof(query_packet) - 1; 122 | enc = &base32_ops; 123 | 124 | dns_decode(buf, sizeof(buf), &q, QR_QUERY, query_packet, len); 125 | domain = strstr(q.name, topdomain); 126 | len = sizeof(buf); 127 | unpack_data(buf, len, &(q.name[1]), (int) (domain - q.name) - 1, enc); 128 | 129 | ck_assert_msg(strncmp(buf, innerData, strlen(innerData)) == 0, 130 | "Did not extract expected host: '%s'", buf); 131 | ck_assert_msg(strlen(buf) == strlen(innerData), 132 | "Bad host length: %zu, expected %zu: '%s'", 133 | strlen(buf), strlen(innerData), buf); 134 | } 135 | END_TEST 136 | 137 | START_TEST(test_encode_response) 138 | { 139 | char buf[512]; 140 | char *host = "silly.host.of.iodine.code.kryo.se"; 141 | struct query q; 142 | int len; 143 | int ret; 144 | 145 | len = sizeof(buf); 146 | memset(&buf, 0, sizeof(buf)); 147 | memset(&q, 0, sizeof(struct query)); 148 | strncpy(q.name, host, strlen(host)); 149 | q.type = T_NULL; 150 | q.id = 1337; 151 | 152 | ret = dns_encode(buf, len, &q, QR_ANSWER, msgData, strlen(msgData)); 153 | len = sizeof(answer_packet) - 1; /* Skip extra null character */ 154 | 155 | ck_assert_msg(strncmp(answer_packet, buf, sizeof(answer_packet)) == 0, 156 | "Did not compile expected packet"); 157 | ck_assert_msg(ret == len, 158 | "Bad packet length: %d, expected %d", ret, len); 159 | } 160 | END_TEST 161 | 162 | START_TEST(test_decode_response) 163 | { 164 | char buf[512]; 165 | struct query q; 166 | int len; 167 | int ret; 168 | 169 | len = sizeof(buf); 170 | memset(&buf, 0, sizeof(buf)); 171 | 172 | ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet, sizeof(answer_packet)-1); 173 | ck_assert_msg(ret == strlen(msgData), 174 | "Bad data length: %d, expected %zu", ret, strlen(msgData)); 175 | ck_assert_msg(strncmp(msgData, buf, strlen(msgData)) == 0, 176 | "Did not extract expected data"); 177 | ck_assert(q.id == 0x0539); 178 | } 179 | END_TEST 180 | 181 | START_TEST(test_decode_response_with_high_trans_id) 182 | { 183 | char buf[512]; 184 | struct query q; 185 | int len; 186 | int ret; 187 | 188 | len = sizeof(buf); 189 | memset(&buf, 0, sizeof(buf)); 190 | 191 | ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id)-1); 192 | ck_assert_msg(ret == strlen(msgData), 193 | "Bad data length: %d, expected %zu", ret, strlen(msgData)); 194 | ck_assert_msg(strncmp(msgData, buf, strlen(msgData)) == 0, 195 | "Did not extract expected data"); 196 | ck_assert_msg(q.id == 0x8539, 197 | "q.id was %08X instead of %08X!", q.id, 0x8539); 198 | } 199 | END_TEST 200 | 201 | START_TEST(test_get_id_short_packet) 202 | { 203 | char buf[5]; 204 | int len; 205 | unsigned short id; 206 | 207 | len = sizeof(buf); 208 | memset(&buf, 5, sizeof(buf)); 209 | 210 | id = dns_get_id(buf, len); 211 | ck_assert(id == 0); 212 | } 213 | END_TEST 214 | 215 | START_TEST(test_get_id_low) 216 | { 217 | unsigned short id; 218 | 219 | id = dns_get_id(answer_packet, sizeof(answer_packet)); 220 | ck_assert(id == 1337); 221 | } 222 | END_TEST 223 | 224 | START_TEST(test_get_id_high) 225 | { 226 | unsigned short id; 227 | 228 | id = dns_get_id(answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id)); 229 | ck_assert(id == 0x8539); 230 | } 231 | END_TEST 232 | 233 | static void 234 | dump_packet(char *buf, size_t len) 235 | { 236 | int pos; 237 | 238 | for (pos = 0; pos < len; pos++) { 239 | printf("\\x%02X", (unsigned char) buf[pos]); 240 | } 241 | printf("\n"); 242 | for (pos = 0; pos < len; pos++) { 243 | if (isalnum((unsigned char) buf[pos])) { 244 | printf(" %c ", (unsigned char) buf[pos]); 245 | } else { 246 | printf(" "); 247 | } 248 | } 249 | printf("\n"); 250 | } 251 | 252 | TCase * 253 | test_dns_create_tests(void) 254 | { 255 | TCase *tc; 256 | 257 | tc = tcase_create("Dns"); 258 | tcase_add_test(tc, test_encode_query); 259 | tcase_add_test(tc, test_decode_query); 260 | tcase_add_test(tc, test_encode_response); 261 | tcase_add_test(tc, test_decode_response); 262 | tcase_add_test(tc, test_decode_response_with_high_trans_id); 263 | tcase_add_test(tc, test_get_id_short_packet); 264 | tcase_add_test(tc, test_get_id_low); 265 | tcase_add_test(tc, test_get_id_high); 266 | 267 | return tc; 268 | } 269 | -------------------------------------------------------------------------------- /tests/encoding.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "encoding.h" 24 | #include "test.h" 25 | 26 | #define TUPLES 4 27 | 28 | static struct tuple 29 | { 30 | char *a; 31 | char *b; 32 | } dottests[] = { 33 | { "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 34 | "aaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaa"}, 35 | { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 36 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."}, 37 | { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 38 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, 39 | { "abc123", "abc123" }, 40 | { NULL, NULL } 41 | }; 42 | 43 | START_TEST(test_inline_dotify) 44 | { 45 | char temp[1024]; 46 | char *b; 47 | 48 | memset(temp, 0, sizeof(temp)); 49 | strcpy(temp, dottests[_i].a); 50 | b = temp; 51 | inline_dotify(b, sizeof(temp)); 52 | 53 | ck_assert_str_eq(dottests[_i].b, temp); 54 | } 55 | END_TEST 56 | 57 | START_TEST(test_inline_undotify) 58 | { 59 | char temp[1024]; 60 | char *b; 61 | 62 | memset(temp, 0, sizeof(temp)); 63 | strcpy(temp, dottests[_i].b); 64 | b = temp; 65 | inline_undotify(b, sizeof(temp)); 66 | 67 | ck_assert_str_eq(dottests[_i].a, temp); 68 | } 69 | END_TEST 70 | 71 | START_TEST(test_build_hostname) 72 | { 73 | char data[256]; 74 | char buf[1024]; 75 | char *topdomain = "a.c"; 76 | int buflen; 77 | int i; 78 | 79 | for (i = 0; i < sizeof(data); i++) { 80 | data[i] = i & 0xFF; 81 | } 82 | 83 | buflen = sizeof(buf); 84 | 85 | for (i = 1; i < sizeof(data); i++) { 86 | int len = build_hostname(buf, buflen, data, i, topdomain, &base32_ops, sizeof(buf)); 87 | 88 | ck_assert(len <= i); 89 | ck_assert_msg(strstr(buf, "..") == NULL, 90 | "Found double dots when encoding data len %d! buf: %s", i, buf); 91 | } 92 | } 93 | END_TEST 94 | 95 | TCase * 96 | test_encoding_create_tests(void) 97 | { 98 | TCase *tc; 99 | 100 | tc = tcase_create("Encoding"); 101 | tcase_add_loop_test(tc, test_inline_dotify, 0, TUPLES); 102 | tcase_add_loop_test(tc, test_inline_undotify, 0, TUPLES); 103 | tcase_add_test(tc, test_build_hostname); 104 | 105 | return tc; 106 | } 107 | -------------------------------------------------------------------------------- /tests/fw_query.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009-2014 Erik Ekman 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | 19 | #include "fw_query.h" 20 | #include "test.h" 21 | 22 | START_TEST(test_fw_query_simple) 23 | { 24 | struct fw_query q; 25 | struct fw_query *qp; 26 | 27 | q.addrlen = 33; 28 | q.id = 0x848A; 29 | 30 | fw_query_init(); 31 | 32 | /* Test empty cache */ 33 | fw_query_get(0x848A, &qp); 34 | ck_assert(qp == NULL); 35 | 36 | fw_query_put(&q); 37 | 38 | /* Test cache with one entry */ 39 | fw_query_get(0x848A, &qp); 40 | ck_assert(qp->addrlen == q.addrlen); 41 | ck_assert(qp->id == q.id); 42 | } 43 | END_TEST 44 | 45 | START_TEST(test_fw_query_edge) 46 | { 47 | struct fw_query q; 48 | struct fw_query *qp; 49 | int i; 50 | 51 | fw_query_init(); 52 | 53 | q.addrlen = 33; 54 | q.id = 0x848A; 55 | fw_query_put(&q); 56 | 57 | for (i = 1; i < FW_QUERY_CACHE_SIZE; i++) { 58 | q.addrlen++; 59 | q.id++; 60 | fw_query_put(&q); 61 | } 62 | 63 | /* The query should still be cached */ 64 | fw_query_get(0x848A, &qp); 65 | ck_assert(qp->addrlen == 33); 66 | ck_assert(qp->id == 0x848A); 67 | 68 | q.addrlen++; 69 | q.id++; 70 | fw_query_put(&q); 71 | 72 | /* but now it is overwritten */ 73 | fw_query_get(0x848A, &qp); 74 | ck_assert(qp == NULL); 75 | } 76 | END_TEST 77 | 78 | TCase * 79 | test_fw_query_create_tests(void) 80 | { 81 | TCase *tc; 82 | 83 | tc = tcase_create("Forwarded query"); 84 | tcase_add_test(tc, test_fw_query_simple); 85 | tcase_add_test(tc, test_fw_query_edge); 86 | 87 | return tc; 88 | } 89 | -------------------------------------------------------------------------------- /tests/login.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include "test.h" 22 | #include "login.h" 23 | 24 | START_TEST(test_login_hash) 25 | { 26 | char ans[16]; 27 | char good[] = "\x2A\x8A\x12\xB4\xE0\x42\xEE\xAB\xD0\x19\x17\x1E\x44\xA0\x88\xCD"; 28 | char pass[32] = "iodine is the shit"; 29 | int len; 30 | int seed; 31 | 32 | len = sizeof(ans); 33 | seed = 15; 34 | 35 | memset(ans, 0, sizeof(ans)); 36 | login_calculate(ans, len, pass, seed); 37 | ck_assert(strncmp(ans, good, len) == 0); 38 | } 39 | END_TEST 40 | 41 | START_TEST(test_login_hash_short) 42 | { 43 | char ans[8]; 44 | char check[sizeof(ans)]; 45 | char pass[32] = "iodine is the shit"; 46 | int len; 47 | int seed; 48 | 49 | len = sizeof(ans); 50 | seed = 15; 51 | 52 | memset(ans, 0, sizeof(ans)); 53 | memset(check, 0, sizeof(check)); 54 | 55 | /* If len < 16, it should do nothing */ 56 | login_calculate(ans, len, pass, seed); 57 | ck_assert(memcmp(ans, check, sizeof(ans)) == 0); 58 | } 59 | END_TEST 60 | 61 | TCase * 62 | test_login_create_tests(void) 63 | { 64 | TCase *tc; 65 | 66 | tc = tcase_create("Login"); 67 | tcase_add_test(tc, test_login_hash); 68 | tcase_add_test(tc, test_login_hash_short); 69 | 70 | return tc; 71 | } 72 | -------------------------------------------------------------------------------- /tests/read.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #ifdef DARWIN 24 | #define BIND_8_COMPAT 25 | #include 26 | #endif 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "common.h" 34 | #include "encoding.h" 35 | #include "dns.h" 36 | #include "read.h" 37 | #include "test.h" 38 | 39 | START_TEST(test_read_putshort) 40 | { 41 | unsigned short k; 42 | unsigned short l; 43 | char* p; 44 | int i; 45 | 46 | for (i = 0; i < 65536; i++) { 47 | p = (char*)&k; 48 | putshort(&p, i); 49 | ck_assert_msg(ntohs(k) == i, 50 | "Bad value on putshort for %d: %d != %d", 51 | i, ntohs(k), i); 52 | 53 | p = (char*)&k; 54 | readshort(NULL, &p, &l); 55 | ck_assert_msg(l == i, 56 | "Bad value on readshort for %d: %d != %d", 57 | i, l, i); 58 | } 59 | } 60 | END_TEST 61 | 62 | START_TEST(test_read_putlong) 63 | { 64 | uint32_t k; 65 | uint32_t l; 66 | char* p; 67 | int i; 68 | int j; 69 | 70 | for (i = 0; i < 32; i++) { 71 | p = (char*)&k; 72 | j = 0xf << i; 73 | 74 | putlong(&p, j); 75 | 76 | ck_assert_msg(ntohl(k) == j, 77 | "Bad value on putlong for %d: %d != %d", i, ntohl(j), j); 78 | 79 | p = (char*)&k; 80 | readlong(NULL, &p, &l); 81 | 82 | ck_assert_msg(l == j, 83 | "Bad value on readlong for %d: %d != %d", i, l, j); 84 | } 85 | } 86 | END_TEST 87 | 88 | START_TEST(test_read_name_empty_loop) 89 | { 90 | unsigned char emptyloop[] = { 91 | 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 92 | 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 }; 93 | char buf[1024]; 94 | char *data; 95 | int rv; 96 | 97 | memset(buf, 0, sizeof(buf)); 98 | data = (char*) emptyloop + sizeof(HEADER); 99 | buf[1023] = 'A'; 100 | rv = readname((char *) emptyloop, sizeof(emptyloop), &data, buf, 1023); 101 | ck_assert(rv == 0); 102 | ck_assert(buf[1023] == 'A'); 103 | } 104 | END_TEST 105 | 106 | START_TEST(test_read_name_inf_loop) 107 | { 108 | unsigned char infloop[] = { 109 | 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 110 | 0x01, 'A', 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01 }; 111 | char buf[1024]; 112 | char *data; 113 | int rv; 114 | 115 | memset(buf, 0, sizeof(buf)); 116 | data = (char*) infloop + sizeof(HEADER); 117 | buf[4] = '\a'; 118 | rv = readname((char*) infloop, sizeof(infloop), &data, buf, 4); 119 | ck_assert(rv == 3); 120 | ck_assert(buf[4] == '\a'); 121 | } 122 | END_TEST 123 | 124 | START_TEST(test_read_name_longname) 125 | { 126 | unsigned char longname[] = 127 | "AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00" 128 | "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" 129 | "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" 130 | "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" 131 | "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" 132 | "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" 133 | "\x3FzBCDEFGHIJKLMNOPQURSTUVXYZ0123456789abcdefghijklmnopqrstuvxyzAA" 134 | "\x00\x00\x01\x00\x01"; 135 | char buf[1024]; 136 | char *data; 137 | int rv; 138 | 139 | memset(buf, 0, sizeof(buf)); 140 | data = (char*) longname + sizeof(HEADER); 141 | buf[256] = '\a'; 142 | rv = readname((char*) longname, sizeof(longname), &data, buf, 256); 143 | ck_assert(rv == 256); 144 | ck_assert(buf[256] == '\a'); 145 | } 146 | END_TEST 147 | 148 | START_TEST(test_read_name_onejump) 149 | { 150 | unsigned char onejump[] = 151 | "AA\x81\x80\x00\x01\x00\x00\x00\x00\x00\x00" 152 | "\x02hh\xc0\x15\x00\x01\x00\x01\x05zBCDE\x00"; 153 | char buf[1024]; 154 | char *data; 155 | int rv; 156 | 157 | memset(buf, 0, sizeof(buf)); 158 | data = (char*) onejump + sizeof(HEADER); 159 | rv = readname((char*) onejump, sizeof(onejump), &data, buf, 256); 160 | ck_assert(rv == 9); 161 | } 162 | END_TEST 163 | 164 | START_TEST(test_read_name_badjump_start) 165 | { 166 | unsigned char badjump[] = { 167 | 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 168 | 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 }; 169 | unsigned char *jumper; 170 | char buf[1024]; 171 | char *data; 172 | int rv; 173 | 174 | /* This test uses malloc to cause segfault if jump is executed */ 175 | memset(buf, 0, sizeof(buf)); 176 | jumper = malloc(sizeof(badjump)); 177 | if (jumper) { 178 | memcpy(jumper, badjump, sizeof(badjump)); 179 | data = (char*) jumper + sizeof(HEADER); 180 | rv = readname((char*) jumper, sizeof(badjump), &data, buf, 256); 181 | 182 | ck_assert(rv == 0); 183 | ck_assert(buf[0] == 0); 184 | } 185 | free(jumper); 186 | } 187 | END_TEST 188 | 189 | START_TEST(test_read_name_badjump_second) 190 | { 191 | unsigned char badjump2[] = { 192 | 'A', 'A', 0x81, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 193 | 0x02, 'B', 'A', 0xfe, 0xcc, 0x00, 0x01, 0x00, 0x01 }; 194 | unsigned char *jumper; 195 | char buf[1024]; 196 | char *data; 197 | int rv; 198 | 199 | /* This test uses malloc to cause segfault if jump is executed */ 200 | memset(buf, 0, sizeof(buf)); 201 | jumper = malloc(sizeof(badjump2)); 202 | if (jumper) { 203 | memcpy(jumper, badjump2, sizeof(badjump2)); 204 | data = (char*) jumper + sizeof(HEADER); 205 | rv = readname((char*) jumper, sizeof(badjump2), &data, buf, 256); 206 | 207 | ck_assert(rv == 4); 208 | ck_assert_str_eq("BA.", buf); 209 | } 210 | free(jumper); 211 | } 212 | END_TEST 213 | 214 | START_TEST(test_putname) 215 | { 216 | char out[] = "\x06" "BADGER\x06" "BADGER\x04" "KRYO\x02" "SE\x00"; 217 | char buf[256]; 218 | char *domain = "BADGER.BADGER.KRYO.SE"; 219 | char *b; 220 | int ret; 221 | 222 | memset(buf, 0, 256); 223 | b = buf; 224 | ret = putname(&b, 256, domain); 225 | 226 | ck_assert(ret == strlen(domain) + 1); 227 | ck_assert_msg(strncmp(buf, out, ret) == 0, "Happy flow failed"); 228 | } 229 | END_TEST 230 | 231 | START_TEST(test_putname_nodot) 232 | { 233 | char buf[256]; 234 | char *nodot = 235 | "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" 236 | "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"; 237 | char *b; 238 | int ret; 239 | 240 | memset(buf, 0, 256); 241 | b = buf; 242 | ret = putname(&b, 256, nodot); 243 | 244 | ck_assert(ret == -1); 245 | ck_assert(b == buf); 246 | } 247 | END_TEST 248 | 249 | START_TEST(test_putname_toolong) 250 | { 251 | char buf[256]; 252 | char *toolong = 253 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." 254 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." 255 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." 256 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." 257 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ." 258 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEFGHIJKLMNOPQRSTUVWXYZ."; 259 | char *b; 260 | int ret; 261 | 262 | memset(buf, 0, 256); 263 | b = buf; 264 | ret = putname(&b, 256, toolong); 265 | 266 | ck_assert(ret == -1); 267 | ck_assert(b == buf); 268 | } 269 | END_TEST 270 | 271 | 272 | TCase * 273 | test_read_create_tests(void) 274 | { 275 | TCase *tc; 276 | 277 | tc = tcase_create("Read"); 278 | tcase_set_timeout(tc, 60); 279 | tcase_add_test(tc, test_read_putshort); 280 | tcase_add_test(tc, test_read_putlong); 281 | tcase_add_test(tc, test_read_name_empty_loop); 282 | tcase_add_test(tc, test_read_name_inf_loop); 283 | tcase_add_test(tc, test_read_name_longname); 284 | tcase_add_test(tc, test_read_name_onejump); 285 | tcase_add_test(tc, test_read_name_badjump_start); 286 | tcase_add_test(tc, test_read_name_badjump_second); 287 | tcase_add_test(tc, test_putname); 288 | tcase_add_test(tc, test_putname_nodot); 289 | tcase_add_test(tc, test_putname_toolong); 290 | 291 | return tc; 292 | } 293 | -------------------------------------------------------------------------------- /tests/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "test.h" 25 | 26 | int 27 | main(void) 28 | { 29 | SRunner *runner; 30 | Suite *iodine; 31 | TCase *test; 32 | int failed; 33 | 34 | iodine = suite_create("iodine"); 35 | 36 | test = test_base32_create_tests(); 37 | suite_add_tcase(iodine, test); 38 | 39 | test = test_base64_create_tests(); 40 | suite_add_tcase(iodine, test); 41 | 42 | test = test_common_create_tests(); 43 | suite_add_tcase(iodine, test); 44 | 45 | test = test_dns_create_tests(); 46 | suite_add_tcase(iodine, test); 47 | 48 | test = test_encoding_create_tests(); 49 | suite_add_tcase(iodine, test); 50 | 51 | test = test_read_create_tests(); 52 | suite_add_tcase(iodine, test); 53 | 54 | test = test_login_create_tests(); 55 | suite_add_tcase(iodine, test); 56 | 57 | test = test_user_create_tests(); 58 | suite_add_tcase(iodine, test); 59 | 60 | test = test_fw_query_create_tests(); 61 | suite_add_tcase(iodine, test); 62 | 63 | runner = srunner_create(iodine); 64 | srunner_run_all(runner, CK_NORMAL); 65 | failed = srunner_ntests_failed(runner); 66 | 67 | srunner_free(runner); 68 | 69 | return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 70 | } 71 | -------------------------------------------------------------------------------- /tests/test.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #ifndef __TEST_H__ 19 | #define __TEST_H__ 20 | 21 | TCase *test_base32_create_tests(void); 22 | TCase *test_base64_create_tests(void); 23 | TCase *test_common_create_tests(void); 24 | TCase *test_dns_create_tests(void); 25 | TCase *test_encoding_create_tests(void); 26 | TCase *test_read_create_tests(void); 27 | TCase *test_login_create_tests(void); 28 | TCase *test_user_create_tests(void); 29 | TCase *test_fw_query_create_tests(void); 30 | 31 | char *va_str(const char *, ...); 32 | 33 | #if (CHECK_MAJOR_VERSION == 0 && \ 34 | ((CHECK_MINOR_VERSION == 9 && CHECK_MICRO_VERSION < 2) || \ 35 | (CHECK_MINOR_VERSION < 9))) 36 | #define tcase_set_timeout(...) 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /tests/user.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2014 Erik Ekman , 3 | * 2006-2009 Bjorn Andersson 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "common.h" 27 | #include "encoding.h" 28 | #include "user.h" 29 | #include "test.h" 30 | 31 | START_TEST(test_init_users) 32 | { 33 | in_addr_t ip; 34 | char givenip[16]; 35 | int i; 36 | int count; 37 | 38 | ip = inet_addr("127.0.0.1"); 39 | count = init_users(ip, 27); 40 | for (i = 0; i < count; i++) { 41 | ck_assert(users[i].id == i); 42 | ck_assert(users[i].q.id == 0); 43 | ck_assert(users[i].inpacket.len == 0); 44 | ck_assert(users[i].outpacket.len == 0); 45 | snprintf(givenip, sizeof(givenip), "127.0.0.%d", i + 2); 46 | ck_assert(users[i].tun_ip == inet_addr(givenip)); 47 | } 48 | } 49 | END_TEST 50 | 51 | START_TEST(test_find_user_by_ip) 52 | { 53 | in_addr_t ip; 54 | unsigned int testip; 55 | 56 | ip = inet_addr("127.0.0.1"); 57 | init_users(ip, 27); 58 | users[0].conn = CONN_DNS_NULL; 59 | 60 | testip = (unsigned int) inet_addr("10.0.0.1"); 61 | ck_assert(find_user_by_ip(testip) == -1); 62 | 63 | testip = (unsigned int) inet_addr("127.0.0.2"); 64 | ck_assert(find_user_by_ip(testip) == -1); 65 | 66 | users[0].active = 1; 67 | 68 | testip = (unsigned int) inet_addr("127.0.0.2"); 69 | ck_assert(find_user_by_ip(testip) == -1); 70 | 71 | users[0].last_pkt = time(NULL); 72 | 73 | testip = (unsigned int) inet_addr("127.0.0.2"); 74 | ck_assert(find_user_by_ip(testip) == -1); 75 | 76 | users[0].authenticated = 1; 77 | 78 | testip = (unsigned int) inet_addr("127.0.0.2"); 79 | ck_assert(find_user_by_ip(testip) == 0); 80 | } 81 | END_TEST 82 | 83 | START_TEST(test_all_users_waiting_to_send) 84 | { 85 | in_addr_t ip; 86 | 87 | ip = inet_addr("127.0.0.1"); 88 | init_users(ip, 27); 89 | 90 | ck_assert(all_users_waiting_to_send() == 1); 91 | 92 | users[0].conn = CONN_DNS_NULL; 93 | users[0].active = 1; 94 | 95 | ck_assert(all_users_waiting_to_send() == 1); 96 | 97 | users[0].last_pkt = time(NULL); 98 | users[0].outpacket.len = 0; 99 | 100 | ck_assert(all_users_waiting_to_send() == 0); 101 | 102 | #ifdef OUTPACKETQ_LEN 103 | users[0].outpacketq_filled = 1; 104 | #else 105 | users[0].outpacket.len = 44; 106 | #endif 107 | 108 | ck_assert(all_users_waiting_to_send() == 1); 109 | } 110 | END_TEST 111 | 112 | START_TEST(test_find_available_user) 113 | { 114 | in_addr_t ip; 115 | int i; 116 | 117 | ip = inet_addr("127.0.0.1"); 118 | init_users(ip, 27); 119 | 120 | for (i = 0; i < USERS; i++) { 121 | users[i].authenticated = 1; 122 | users[i].authenticated_raw = 1; 123 | ck_assert(find_available_user() == i); 124 | ck_assert(users[i].authenticated == 0); 125 | ck_assert(users[i].authenticated_raw == 0); 126 | } 127 | 128 | for (i = 0; i < USERS; i++) { 129 | ck_assert(find_available_user() == -1); 130 | } 131 | 132 | users[3].active = 0; 133 | 134 | ck_assert(find_available_user() == 3); 135 | ck_assert(find_available_user() == -1); 136 | 137 | users[3].last_pkt = 55; 138 | 139 | ck_assert(find_available_user() == 3); 140 | ck_assert(find_available_user() == -1); 141 | } 142 | END_TEST 143 | 144 | START_TEST(test_find_available_user_small_net) 145 | { 146 | in_addr_t ip; 147 | int i; 148 | 149 | ip = inet_addr("127.0.0.1"); 150 | init_users(ip, 29); /* this should result in 5 enabled users */ 151 | 152 | for (i = 0; i < 5; i++) { 153 | ck_assert(find_available_user() == i); 154 | } 155 | 156 | for (i = 0; i < USERS; i++) { 157 | ck_assert(find_available_user() == -1); 158 | } 159 | 160 | users[3].active = 0; 161 | 162 | ck_assert(find_available_user() == 3); 163 | ck_assert(find_available_user() == -1); 164 | 165 | users[3].last_pkt = 55; 166 | 167 | ck_assert(find_available_user() == 3); 168 | ck_assert(find_available_user() == -1); 169 | } 170 | END_TEST 171 | 172 | TCase * 173 | test_user_create_tests(void) 174 | { 175 | TCase *tc; 176 | 177 | tc = tcase_create("User"); 178 | tcase_add_test(tc, test_init_users); 179 | tcase_add_test(tc, test_find_user_by_ip); 180 | tcase_add_test(tc, test_all_users_waiting_to_send); 181 | tcase_add_test(tc, test_find_available_user); 182 | tcase_add_test(tc, test_find_available_user_small_net); 183 | 184 | return tc; 185 | } 186 | --------------------------------------------------------------------------------