├── .gitignore ├── COPYRIGHT ├── DONATE ├── LICENSE ├── Make.sh ├── README ├── THANKS ├── contrib ├── jsw │ └── urcbot │ │ └── urcbot.py └── seekingfor │ └── urc2server_rfc1459.py ├── db └── urchub │ ├── i2p │ └── 7kmkqzx5egdannxhqt4b3fkqbo7jdjphwcf2viiph7qdqm3wlmaa.b32.i2p │ │ ├── owner │ │ └── port │ ├── icann │ ├── josephswilliams.com │ │ ├── owner │ │ └── port │ └── urc.freeanons.info │ │ ├── owner │ │ └── port │ └── tor │ ├── allyour4nert7pkh.onion │ ├── owner │ └── port │ ├── freeanonine7mgki.onion │ ├── owner │ └── port │ ├── hppikcru545manbi.onion │ ├── owner │ └── port │ └── ntwrkhhtqv73vwd4.onion │ ├── owner │ └── port ├── doc ├── README.bak.txt ├── URC.txt └── topology.txt ├── env ├── addr ├── motd ├── path ├── port └── serv ├── git-commit ├── git-push-github ├── gitd ├── install-daemontools.sh ├── install-libsodium.sh ├── install-libtai.sh ├── install-nacl.sh ├── install-ucspi-ssl.sh ├── install-ucspi-tcp.sh ├── run ├── run.log ├── run.urc2sd ├── run.urc2sd-tor ├── run.urcd-curvecp ├── run.urcd-ssl ├── scripts ├── add-curvecpconnect ├── add-curvecphubconnect ├── add-curvecphublisten ├── add-curvecplisten ├── add-curvecprecv ├── add-curvecpsend ├── add-hubconnect ├── add-hublisten ├── add-tcpconnect ├── add-tcplisten ├── add-tcprecv ├── add-tcpsend ├── add-torconnect ├── add-torhubconnect ├── add-torsend ├── add-udprecv ├── add-udpsend ├── add-urchub ├── add-urcstream2hub ├── scrubsocketdir └── urcd.sh ├── src ├── base16.h ├── check-nacl.h ├── check-sodium.h ├── check-taia.c ├── cryptoserv.c ├── curvecpserver.c ├── dprintf.h ├── keypair.c ├── liburc.c ├── liburc.h ├── nacltaia.c ├── sign_keypair.c ├── socket_bind.c ├── tai_dec.h ├── tai_inc.h ├── taia96n.pyx ├── ucspi-client2server.c ├── ucspi-server2client.c ├── ucspi-socks4aclient.c ├── ucspi-stream.c ├── urc-udprecv.c ├── urc-udpsend.c ├── urc2sd.pyx ├── urccache-failover.c ├── urccache.c ├── urcd.pyx ├── urcd.pyx.test ├── urchub.c ├── urchubstream.c ├── urcrecv.c ├── urcrecv.pyx ├── urcsend.c ├── urcsend.pyx ├── urcstream.c ├── urcstream.pyx └── urcstream2hub.c └── stdin.cryptoserv /.gitignore: -------------------------------------------------------------------------------- 1 | env 2 | log 3 | conf 4 | build 5 | urcd 6 | urc.db 7 | urc2sd 8 | urchub 9 | urcrecv 10 | urcsend 11 | urccache 12 | urcstream 13 | urchubstream 14 | urcstream2hub 15 | socket 16 | supervise 17 | stdin 18 | stdout 19 | channels 20 | auto_cmd 21 | nick 22 | ucspi-client2server 23 | ucspi-socks4aclient 24 | ucspi-stream 25 | libtai-* 26 | nacl-* 27 | check-taia 28 | nacltaia.so 29 | sign_keypair 30 | keypair 31 | conf-cc 32 | ucspi-server2client 33 | urc-udpsend 34 | urc-udprecv 35 | libsodium-0.6.0.tar.gz 36 | libsodium-0.6.0 37 | ucspi-tcp-0.88.tar.gz 38 | ucspi-tcp-0.88.tar 39 | ucspi-tcp-0.88 40 | cryptoservroot/ 41 | cryptoserv 42 | taia96n.so 43 | taia96n.py 44 | liburc.so 45 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyleft (c) 2015 Joseph S. Williams 2 | -------------------------------------------------------------------------------- /DONATE: -------------------------------------------------------------------------------- 1 | BTC: 15FKo4HjiNmY1f9Z4kojqmgakjyf6YG4dn 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | URCd is an anonymous, decentralized, cipherchat suite with an IRCd interface :-) 2 | 3 | Copyright (C) 2015 Joseph S. Williams 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | -------------------------------------------------------------------------------- /Make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -v 2 | 3 | 4 | # URCd requires user urcd 5 | if ! su urcd -c exit 0 ; then 6 | useradd urcd 7 | fi 8 | 9 | 10 | # Ivo's libnacl.so will break NaCl softwares 11 | if [ -e '/usr/lib/libnacl.so' ]; then 12 | echo $0': fatal error: move /usr/lib/libnacl.so temporarily' 1>&2 13 | exit 255 14 | fi 15 | 16 | 17 | # you can add gcc options to conf-cc 18 | touch conf-cc 19 | 20 | 21 | # configure a suitable python development library 22 | if ! which python-config; then 23 | if ! which python2.7-config; then 24 | echo $0': fatal error: no suitable python development files exist' 1>&2 25 | exit 255 26 | fi 27 | python_config=python2.7-config 28 | else python_config=python-config 29 | fi 30 | 31 | PYTHON_INCLUDE=`$python_config --includes` || exit 1 32 | PYTHON_LIBRARY=`$python_config --libs` || exit 1 33 | 34 | 35 | # OpenBSD and NetBSD need these paths 36 | export CPATH="/usr/pkg/include:/usr/local/include:$CPATH" 37 | export LIBRARY_PATH="/usr/pkg/lib:/usr/local/lib:$LIBRARY_PATH" 38 | 39 | 40 | # Support libsodium fanboys 41 | if gcc src/check-nacl.h -o /dev/null 2>/dev/null ; then 42 | src='src' 43 | nacl='nacl' 44 | test -e /usr/lib/randombytes.o && \ 45 | randombytes=/usr/lib/randombytes.o 46 | test -e /usr/pkg/lib/randombytes.o && \ 47 | randombytes=/usr/pkg/lib/randombytes.o 48 | test -e /usr/local/lib/randombytes.o && \ 49 | randombytes=/usr/local/lib/randombytes.o 50 | if [ -z $randombytes ]; then 51 | echo $0': fatal error: randombytes.o not found' 1>&2 52 | exit 255 53 | fi 54 | elif gcc src/check-sodium.h -o /dev/null 2>/dev/null ; then 55 | src='libsodium_src' 56 | nacl='sodium' 57 | rm -rf $src 58 | mkdir -p $src 59 | ### *BSD's sed doesn't have -i ### 60 | for i in `ls src/` ; do 61 | sed 's|#include $src/$i 62 | done 63 | else 64 | echo $0': fatal error: no suitable NaCl library exists' 1>&2 65 | exit 255 66 | fi 67 | 68 | 69 | # compile c programs 70 | gcc `cat conf-cc` $src/urchub.c -o urchub || exit 1 71 | gcc `cat conf-cc` $src/urc-udpsend.c -o urc-udpsend || exit 1 72 | gcc `cat conf-cc` $src/urc-udprecv.c -o urc-udprecv || exit 1 73 | gcc `cat conf-cc` $src/ucspi-stream.c -o ucspi-stream || exit 1 74 | gcc `cat conf-cc` $src/urchubstream.c -o urchubstream || exit 1 75 | gcc `cat conf-cc` $src/cryptoserv.c -o cryptoserv -l $nacl || exit 1 76 | gcc `cat conf-cc` $src/urcstream2hub.c -o urcstream2hub -l tai || exit 1 77 | gcc `cat conf-cc` $src/ucspi-client2server.c -o ucspi-client2server || exit 1 78 | gcc `cat conf-cc` $src/ucspi-server2client.c -o ucspi-server2client || exit 1 79 | gcc `cat conf-cc` $src/ucspi-socks4aclient.c -o ucspi-socks4aclient || exit 1 80 | gcc `cat conf-cc` $src/keypair.c -o keypair -l $nacl $randombytes || exit 1 81 | gcc `cat conf-cc` $src/sign_keypair.c -o sign_keypair -l $nacl $randombytes || exit 1 82 | gcc -O2 -fPIC -DPIC $src/liburc.c -shared $PYTHON_INCLUDE -o liburc.so $PYTHON_LIBRARY -l tai -l $nacl || exit 1 83 | gcc -O2 -fPIC -DPIC $src/nacltaia.c -shared $PYTHON_INCLUDE -o nacltaia.so $PYTHON_LIBRARY -l tai -l $nacl $randombytes || exit 1 84 | 85 | 86 | # compile urccache.c and check for errors 87 | gcc `cat conf-cc` $src/check-taia.c -o check-taia -l tai -l $nacl || exit 1 88 | 89 | if ! $(./check-taia >/dev/null) ; then 90 | echo $0': fatal error: (security) potential cache error 00' 1>&2 91 | exit 255 92 | else 93 | gcc `cat conf-cc` $src/urccache.c -o urccache -l tai -l $nacl $randombytes || exit 1 94 | printf '' | ./urccache `pwd`/$src/ 95 | if [ $? != 1 ] ; then 96 | echo $0': fatal error: (security) potential cache error 01' 1>&2 97 | exit 255 98 | fi 99 | fi 100 | 101 | 102 | # if cython is not installed use python scripts and exit 103 | if ! which cython 2>/dev/null ; then 104 | cp $src/urcd.pyx urcd || exit 1 105 | chmod +x urcd || exit 1 106 | cp $src/urc2sd.pyx urc2sd || exit 1 107 | chmod +x urc2sd || exit 1 108 | cp $src/taia96n.pyx taia96n.py || exit 1 109 | rm -rf libsodium_src 110 | exit 0 111 | fi 112 | 113 | 114 | # compile cython programs 115 | mkdir -p build || exit 1 116 | 117 | cython --embed $src/urcd.pyx -o build/urcd.c || exit 1 118 | gcc `cat conf-cc` -O2 -c build/urcd.c $PYTHON_INCLUDE -o build/urcd.o || exit 1 119 | gcc `cat conf-cc` -O1 -o urcd build/urcd.o $PYTHON_LIBRARY || exit 1 120 | 121 | cython --embed $src/urc2sd.pyx -o build/urc2sd.c || exit 1 122 | gcc `cat conf-cc` -O2 -c build/urc2sd.c $PYTHON_INCLUDE -o build/urc2sd.o || exit 1 123 | gcc `cat conf-cc` -O1 -o urc2sd build/urc2sd.o $PYTHON_LIBRARY || exit 1 124 | 125 | cython $src/taia96n.pyx -o build/taia96n.c || exit 1 126 | gcc `cat conf-cc` -O2 -shared -pthread -fPIC -fwrapv -Wall \ 127 | -fno-strict-aliasing $PYTHON_INCLUDE build/taia96n.c -o taia96n.so || exit 1 128 | 129 | 130 | # clean up 131 | rm -rf build libsodium_src || exit 1 132 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | URCd: 2 | 10,000 genomes of human lizard hybrid soldiers being sent server to server 3 | between Angola and Luxembourg with some 70's style casual sex peering 4 | arrangement. 5 | 6 | if you want a real description view doc/* 7 | 8 | depends: 9 | NaCl or libsodium, libtai, ucspi-tcp, 10 | python(>=2.6), python-dev(>=2.6), 11 | daemontools, sh, gcc 12 | 13 | your clock needs to be as reasonably accurate, possibly by using something like 14 | ntp, otherwise your messages could be dropped from the network. 15 | 16 | recommends: 17 | NaCl instead of libsodium, 18 | cython(>=0.18.0) 19 | 20 | install: 21 | # install dependencies, if you haven't already: 22 | ./install-daemontools.sh 23 | ./install-ucspi-tcp.sh 24 | 25 | # URCd with ssl. 26 | # if you actually get it to work let me know :-/ 27 | # depends on openssl, libssl-dev, perl, libperl-dev 28 | ./install-ucspi-ssl.sh 29 | 30 | # this also patches libtai for 64-bit shared objects 31 | ./install-libtai.sh 32 | 33 | # recommended over ./install-libsodium.sh: 34 | ./install-nacl.sh 35 | 36 | # OpenBSD: 37 | echo '-ftrampolines' > conf-cc 38 | 39 | ./Make.sh 40 | 41 | # edit the network/hostmask 42 | $editor env/serv 43 | 44 | # edit the motd 45 | $editor env/motd 46 | 47 | ln -s `pwd` /service/urcd 48 | 49 | echo "`pwd`/urc.db" > env/URCDB 50 | svstat /service/urcd 51 | 52 | ### create your urchub, you only need to do this once 53 | ./scripts/add-urchub 54 | 55 | CryptoServ: 56 | ln -s stdin.cryptoserv stdin 57 | 58 | hub2hub: 59 | ./scripts/add-hublisten local.urc.example.tld 6789 /service/urcd-hub0/socket/ 60 | 61 | ### add peers. i recommend between 2 and 4 at the most 62 | ./scripts/add-hubconnect remote.urc.example.tld 6789 /service/urcd-hub0/socket/ 63 | 64 | no censorship (security): 65 | URC networks are censorship resistant. i recommend URCSIGN and/or URCCRYPTOBOX 66 | to ignore spam and trolls. URCd will replace the user field with VERIFIED-Nick 67 | for users with valid authentication or signature verification. All other user 68 | fields will be replaced with URCD-Nick. e.g.: 69 | 70 | Nick!URCD-Nick@server 71 | Nick!VERIFIED-Nick@server 72 | 73 | irssi ("ban/except"): 74 | /ignore *!*@* ALL 75 | /ignore -except friend!*@* ALL 76 | /ignore -except *!VERIFIED-*@* ALL 77 | 78 | xchat ("ban/except"): 79 | /ignore *!*@* ALL 80 | /ignore friend!*@* ALL UNIGNORE 81 | /ignore *!VERIFIED-*@* ALL UNIGNORE 82 | 83 | Contact: 84 | Joseph S. Williams, yhpargotpyrc at gmail. Please write URCd in the subject 85 | so that I will notice it and not accidentally delete it or mark it as spam. 86 | 87 | Thanks: 88 | Thank you for using URCd. If you appreciate this project, please consider 89 | running a public URC hub, or sending a small donation. Like other darknets, 90 | URC is a stronger, safer network the more people that actively participate 91 | in building reliable nodes. Small donations help me financially, thus giving 92 | me more time to focus on this project. 93 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | Thank you to everyone that supported, encouraged, tested, debugged, donated, 2 | reported bugs, and believed in me and the URC project. This project was inspired 3 | by the AnoNet crew, and the original authors of Ricochet and the UDPMSG family 4 | of protocols that were designed for decentralized, anonymous chat. I also 5 | received a great deal of testing and support from members of FreeAnons, and some 6 | other friendly hackers that I've met online and in the real world. I wrote this 7 | project to give the people of the world, especially activists, a safer place to 8 | express themselves and their ideas among one another in a safe place, where they 9 | can be free to talk without fear of violence or physical harm, and communicate 10 | among fellow citizens of the world without being censored, or being targeted by 11 | sharing their ideas with the public. Without you, URC could not have existed, 12 | and for that I am tremendously thankful. If you appreciate this project and 13 | everything it has to offer, please consider running a public urchub, and/or 14 | a urchub that is accessible to you and your peers. Like Tor, I2P, Anonet, and 15 | other decentralized darknets, URC is stronger and safer the more nodes that are 16 | available to transmit traffic. I love you all and it is my hope you get the 17 | most from this software, and are able to use it to make the world a better place 18 | for all of us. 19 | 20 | In solidarity, 21 | 22 | Joseph S. Williams 23 | 24 | 25 | A special thanks to Epoch, LulzPrincess, SeekingFor, Ivo, Psi, Talamon, Kieko, 26 | Nyx, SomeRandomNick, RedAcor, and others that had my back and were by my side 27 | throughout this project. 28 | 29 | Also a special thanks to Daniel J. Bernstein for all of his amazing works that 30 | made this project capable. You're a brilliant man, with incredible talent. 31 | -------------------------------------------------------------------------------- /contrib/jsw/urcbot/urcbot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Usage: tcpclient $urchub_addr $urchub_port python urcbot.py 3 | 4 | import liburc 5 | import sys 6 | import os 7 | import re 8 | 9 | RE = 'a-zA-Z0-9^(\)\-_{\}[\]|\\\\' 10 | re_PRIVMSG = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[~:#'+RE+'.]+ PRIVMSG [#&!+]?['+RE+']+ :.*$',re.IGNORECASE).search 11 | 12 | while 1: 13 | buff = os.read(6,2+12+4+8) 14 | if len(buff) < 2+12+4+8: break 15 | while len(buff[2+12+4+8:]) != ord(buff[0])*256 + ord(buff[1]): 16 | b = os.read(6,ord(buff[0])*256 + ord(buff[1]) - len(buff[2+12+4+8:])) 17 | if not b: sys.exit(0) 18 | buff += b 19 | buff = buff[2+12+4+8:] 20 | 21 | if re_PRIVMSG(buff): 22 | src = buff[1:].split('!',1)[0] 23 | dst = buff.split(' ',3)[2] 24 | msg = buff.split(' :',1)[1] 25 | if msg.lower()[:5] == '!ping': 26 | buff = liburc.urchub_fmt(':bot!bot@bot PRIVMSG '+dst+' :pong\n') 27 | os.write(7,buff) 28 | -------------------------------------------------------------------------------- /contrib/seekingfor/urc2server_rfc1459.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # urc2server_rfc1459 v0.1 3 | # dirty code, you have been warned 4 | import unicodedata 5 | import collections 6 | import subprocess 7 | import liburc 8 | import codecs 9 | import select 10 | import socket 11 | import signal 12 | import time 13 | import pwd 14 | import sys 15 | import re 16 | import os 17 | from hashlib import sha1 18 | 19 | if not os.path.exists('env/LINKNAME') or not os.path.exists('env/LINKPASS'): 20 | exit(525) 21 | 22 | LINKNAME = open('env/LINKNAME','rb').read().split('\n')[0] 23 | LINKPASS = open('env/LINKPASS','rb').read().split('\n')[0] 24 | RE = 'a-zA-Z0-9^(\)\-_{\}[\]|.' 25 | re_SPLIT = re.compile(' +',re.IGNORECASE).split 26 | re_LINK_NICK = re.compile('^NICK ['+RE+']+ :.*$', re.IGNORECASE).search 27 | re_LINK_KILL = re.compile('^KILL ['+RE+']+ :.*$', re.IGNORECASE).search 28 | re_LINK_PRIVMSG_NOTICE_TOPIC = re.compile('^:['+RE+']+!urc2serverRFC1459@' + LINKNAME + ' ((PRIVMSG)|(NOTICE)|(TOPIC)) [&#]['+RE+']+ :.*$',re.IGNORECASE).search 29 | re_LINK_PRIVMSG_PRIVATE = re.compile('^:['+RE+']+!urc2serverRFC1459@' + LINKNAME + ' ((PRIVMSG)|(NOTICE)|(TOPIC)) ['+RE+']+ :.*$',re.IGNORECASE).search 30 | re_LINK_PART = re.compile('^:['+RE+']+!urc2serverRFC1459@' + LINKNAME + ' PART [&#]['+RE+']+( :)?',re.IGNORECASE).search 31 | re_LINK_QUIT = re.compile('^:['+RE+']+!urc2serverRFC1459@' + LINKNAME + ' QUIT( :)?',re.IGNORECASE).search 32 | #re_LINK_PING = re.compile('^PING :?.+$',re.IGNORECASE).search 33 | re_LINK_JOIN = re.compile('^:['+RE+']+!urc2serverRFC1459@' + LINKNAME + ' JOIN [&#]['+RE+']+$',re.IGNORECASE).search 34 | re_LINK_KICK = re.compile('^:.+ KICK [&#]['+RE+']+ ['+RE+']+',re.IGNORECASE).search 35 | re_BUFFER_CTCP_DCC = re.compile('\x01(?!ACTION )',re.IGNORECASE).sub 36 | re_BUFFER_COLOUR = re.compile('(\x03[0-9][0-9]?((?<=[0-9]),[0-9]?[0-9]?)?)|[\x02\x03\x0f\x1d\x1f]',re.IGNORECASE).sub 37 | re_URC_PRIVMSG_NOTICE_TOPIC = re.compile('^:['+RE+']+![~'+RE+']+@['+RE+']+ ((PRIVMSG)|(NOTICE)|(TOPIC)) [#&]['+RE+']+ :.*$',re.IGNORECASE).search 38 | re_URC_PRIVMSG_PRIVATE = re.compile('^:['+RE+']+![~'+RE+']+@['+RE+']+ ((PRIVMSG)|(NOTICE)|(TOPIC)) ['+RE+']+ :.*$',re.IGNORECASE).search 39 | re_URC_JOIN = re.compile('^:['+RE+']+![~'+RE+']+@['+RE+']+ JOIN :[&#]['+RE+']+.*$', re.IGNORECASE).search 40 | re_URC_PART = re.compile('^:['+RE+']+![~'+RE+'.]+@['+RE+'.]+ PART [&#]['+RE+']+.*$',re.IGNORECASE).search 41 | re_URC_QUIT = re.compile('^:['+RE+']+![~'+RE+'.]+@['+RE+'.]+ QUIT :.*$',re.IGNORECASE).search 42 | re_LINK_INTERNAL = re.compile('^:'+LINKNAME+' ',re.IGNORECASE).sub 43 | 44 | LIMIT = float(open('env/LIMIT','rb').read().split('\n')[0]) if os.path.exists('env/LIMIT') else 1 45 | COLOUR = int(open('env/COLOUR','rb').read().split('\n')[0]) if os.path.exists('env/COLOUR') else 0 46 | UNICODE = int(open('env/UNICODE','rb').read().split('\n')[0]) if os.path.exists('env/UNICODE') else 0 47 | DEBUG = int(open('env/DEBUG','rb').read().split('\n')[0]) if os.path.exists('env/DEBUG') else 0 48 | PRESENCE = int(open('env/PRESENCE','rb').read().split('\n')[0]) if os.path.exists('env/PRESENCE') else 0 49 | 50 | 51 | user = str(os.getpid()) 52 | def sock_close(sn,sf): 53 | try: 54 | os.remove(str(os.getpid())) 55 | except: 56 | pass 57 | if sn: sys.exit(0) 58 | 59 | signal.signal(signal.SIGHUP,sock_close) 60 | signal.signal(signal.SIGINT,sock_close) 61 | signal.signal(signal.SIGTERM,sock_close) 62 | signal.signal(signal.SIGCHLD,sock_close) 63 | 64 | rd = 0 65 | if os.access('stdin',1): 66 | p = subprocess.Popen(['./stdin'],stdout=subprocess.PIPE) 67 | rd = p.stdout.fileno() 68 | del p 69 | 70 | wr = 1 71 | if os.access('stdout',1): 72 | p = subprocess.Popen(['./stdout'],stdin=subprocess.PIPE) 73 | wr = p.stdin.fileno() 74 | del p 75 | 76 | uid, gid = pwd.getpwnam('urcd')[2:4] 77 | os.chdir(sys.argv[1]) 78 | os.chroot(os.getcwd()) 79 | os.setgid(gid) 80 | os.setuid(uid) 81 | root = os.getcwd() 82 | del uid, gid 83 | 84 | sock=socket.socket(socket.AF_UNIX,socket.SOCK_DGRAM) 85 | sock_close(0,0) 86 | sock.bind(str(os.getpid())) 87 | sock.setblocking(0) 88 | sd=sock.fileno() 89 | 90 | poll=select.poll() 91 | poll.register(rd,select.POLLIN|select.POLLPRI) 92 | poll.register(sd,select.POLLIN) 93 | poll=poll.poll 94 | 95 | client_revents=select.poll() 96 | client_revents.register(rd,select.POLLIN|select.POLLPRI) 97 | client_revents=client_revents.poll 98 | 99 | server_revents=select.poll() 100 | server_revents.register(sd,select.POLLIN) 101 | server_revents=server_revents.poll 102 | 103 | def try_read(fd,buffer_len): 104 | try: 105 | return os.read(fd,buffer_len) 106 | except: 107 | sock_close(15,0) 108 | 109 | def try_write(fd,buffer): 110 | try: 111 | os.write(fd,buffer) 112 | os.write(2,'[out] ' + buffer) 113 | except: 114 | sock_close(15,0) 115 | 116 | def sock_write(buffer): 117 | buffer = liburc.urchub_fmt(buffer) 118 | try: sock.sendto(buffer,'hub') 119 | except: pass 120 | # os.write(2,'[sockwrite] ' + buffer) 121 | # buffer = buffer[:-1] + ' ' + str(int(time.time())) 122 | # check = sha1(buffer).hexdigest()[:10] 123 | # buffer = buffer + ' ' + check + ' urc-integ\n' 124 | # for path in os.listdir(root): 125 | # try: 126 | # if path != user: sock.sendto(buffer,path) 127 | # except: 128 | # pass 129 | 130 | try_write(wr, 131 | 'PASS ' + LINKPASS + '\n' 132 | 'SERVER urc2serverLocal 1\n' 133 | ) 134 | 135 | 136 | nicks=dict() 137 | tmpNicks=dict() 138 | localnicks=list() 139 | channels=list() 140 | lastCheck = time.time() 141 | inactiveInterval = 3 * 60 * 60 142 | while 1: 143 | now = time.time() 144 | if now - lastCheck > 60: 145 | #os.write(2,'checking for inactivity..\n') 146 | tmpNicks=dict() 147 | for nick in nicks: 148 | if now - nicks[nick][1] > inactiveInterval: 149 | try_write(wr, ':' + nicks[nick][0] + ' QUIT :Inactivity (3 hours)\n') 150 | if DEBUG: try_write(wr, ':urc2server PRIVMSG #status :nick removed because of inactivity: ' + nicks[nick][0] + '\n') 151 | else: 152 | tmpNicks[nick] = nicks[nick] 153 | nicks = tmpNicks 154 | lastCheck = now 155 | poll(-1) 156 | 157 | if client_revents(0): 158 | 159 | buffer = str() 160 | while 1: 161 | byte = try_read(rd,1) 162 | if byte == '': sock_close(15,0) 163 | if byte == '\n': break 164 | if byte != '\r' and len(buffer)<768: buffer += byte 165 | 166 | os.write(2,'[in] ' + buffer + '\n') 167 | buffer=re_LINK_INTERNAL('', buffer) 168 | if buffer[0] != ':': 169 | if re.search('^PING .*$', buffer): 170 | try_write(wr, 'PONG' + buffer[4:] + '\n') 171 | elif re.search('^SERVER .*$', buffer): 172 | channels.append('#status') 173 | try_write(wr, 174 | 'NICK urc2server :1\n' 175 | ':urc2server USER serverlink urc2server urc2server :real name\n' 176 | ':urc2server JOIN #status\n' 177 | ':urc2server PRIVMSG #status :Link established\n' 178 | 'NICK dummy :1\n' 179 | ':dummy USER dummy urc2server urc2server :real name\n' 180 | ) 181 | elif re_LINK_NICK(buffer): 182 | nick = buffer.split(' ')[1] 183 | if not nick.lower() in localnicks: 184 | localnicks.append(nick.lower()) 185 | if DEBUG: try_write(wr,':urc2server PRIVMSG #status :local nick ' + nick.lower() + ' added: ' + buffer + '\n') 186 | else: 187 | try_write(wr,':urc2server PRIVMSG #status :local nick ' + nick.lower() + ' is already in localnicks. wtf?: ' + buffer + '\n') 188 | elif re_LINK_KILL(buffer): 189 | nick = buffer.split(' ')[1] 190 | if nick.lower() in nicks: 191 | del nicks[nick.lower()] 192 | if nick.lower() in localnicks: 193 | localnicks.remove(nick.lower()) 194 | try_write(wr,':urc2server PRIVMSG #status :nick killed: ' + buffer + '\n') 195 | elif not re.search('^PASS .*$', buffer): 196 | try_write(wr,':urc2server PRIVMSG #status :unknown command from irc server: ' + buffer + '\n') 197 | continue 198 | 199 | buffer = buffer.split(' ', 1)[0] + '!urc2serverRFC1459@' + LINKNAME + ' ' + buffer.split(' ', 1)[1] 200 | #os.write(2,'[got] ' + buffer+'\n') 201 | if re_LINK_PRIVMSG_NOTICE_TOPIC(buffer): 202 | #os.write(2, ' last message is PRIVMSG_NOTICE_TOPIC\n') 203 | #if buffer[1:].split('!',1)[0] == nick: continue 204 | sock_write(buffer+'\n') 205 | 206 | elif re_LINK_PART(buffer): 207 | pass 208 | #if len(buffer.split(' :'))<2: buffer += ' :' 209 | if PRESENCE: sock_write(buffer + '\n') 210 | 211 | elif re_LINK_QUIT(buffer): 212 | nick = buffer.split('!', 1)[0][1:] 213 | if nick.lower() in localnicks: 214 | try: 215 | if DEBUG: try_write(wr,':urc2server PRIVMSG #status :local nick ' + nick + ' removed\n') 216 | localnicks.remove(nick.lower()) 217 | except Exception as e: 218 | try_write(wr,':urc2server PRIVMSG #status :exception while removing local nick ' + nick + ': ' + e + '\n') 219 | else: 220 | try_write(wr,':urc2server PRIVMSG #status :nick not in localnicks. wtf? ' + buffer + '\n') 221 | #if len(buffer.split(' :'))<2: buffer += ' :' 222 | if PRESENCE: sock_write(buffer + '\n') 223 | 224 | elif re_LINK_JOIN(buffer): 225 | chan = buffer.split(" ")[2] 226 | if chan not in channels: 227 | try_write(wr, ':dummy JOIN ' + chan + '\n') 228 | channels.append(chan) 229 | if PRESENCE: sock_write(buffer.split(' JOIN ', 1)[0] + ' JOIN :' + buffer.split(' JOIN ', 1)[1] + '\n') 230 | 231 | elif re_LINK_KICK(buffer): 232 | #if len(buffer.split(' :'))<2: buffer += ' :' 233 | sock_write(buffer+'\n') 234 | 235 | elif re_LINK_PRIVMSG_PRIVATE(buffer): 236 | sock_write(buffer+'\n') 237 | 238 | #elif re.search('^:['+RE+']+![~'+RE+'.]+@['+RE+'.]+ INVITE '+re.escape(nick).upper()+' :#['+RE+']+$',buffer.upper()): 239 | # dst = buffer[1:].split(':',1)[1].lower() 240 | # if not dst in channels: try_write(wr,'JOIN '+dst+'\n') 241 | 242 | 243 | while server_revents(0): 244 | 245 | time.sleep(LIMIT) 246 | 247 | buffer = try_read(sd,1024).split('\n',1)[0][2+12+4+8:] 248 | if not buffer: continue 249 | #os.write(2, 'socket-in: ' + buffer + '\n') 250 | parts = buffer.split(' ') 251 | if parts[-1] == 'urc-integ': 252 | try: 253 | timestamp, check = int(parts[-3]), parts[-2] 254 | length = len(parts[-3]) + len(parts[-2]) + len(parts[-1]) + 3 255 | buffer = buffer[:-length] 256 | if parts[1] == 'PRIVMSG': 257 | if sha1(buffer + ' ' + parts[-3]).hexdigest()[:10] == check: 258 | status = ' \x0309[v]\x0f' 259 | else: 260 | status = ' \x0305[check failed]\x0f' 261 | if buffer[-1] == '\x01': 262 | buffer = buffer[:-1] + status + '\x01' 263 | else: 264 | buffer += status 265 | del status 266 | del length, timestamp, check 267 | except Exception as e: 268 | pass 269 | 270 | elif len(parts[-1]) == 10: 271 | try: 272 | timestamp, check = int(parts[-2]), parts[-1] 273 | length = len(parts[-2])+len(parts[-1]) + 2 274 | buffer = buffer[:-length] 275 | if parts[1] == 'PRIVMSG': 276 | if sha1(buffer + ' ' + parts[-2]).hexdigest()[:10] == check: 277 | status = ' \x0309[v]\x0f' 278 | else: 279 | status = ' \x0305[check failed]\x0f' 280 | if buffer[-1] == '\x01': 281 | buffer = buffer[:-1] + status + '\x01' 282 | else: 283 | buffer += status 284 | del status 285 | del length, timestamp, check 286 | except Exception as e: 287 | pass 288 | del parts 289 | 290 | buffer = re_BUFFER_CTCP_DCC('',buffer) + '\x01' if '\x01ACTION ' in buffer.upper() else buffer.replace('\x01','') 291 | if not COLOUR: buffer = re_BUFFER_COLOUR('',buffer) 292 | if not UNICODE: 293 | buffer = codecs.ascii_encode(unicodedata.normalize('NFKD',unicode(buffer,'utf-8','replace')),'ignore')[0] 294 | buffer = ''.join(byte for byte in buffer if 127 > ord(byte) > 31 or byte in ['\x01','\x02','\x03','\x0f','\x1d','\x1f']) 295 | buffer += '\n' 296 | #os.write(2, 'socket-done: ' + buffer) 297 | 298 | #os.write(2, '[sock_read] ' + buffer) 299 | if re_URC_PRIVMSG_NOTICE_TOPIC(buffer) or re_URC_PRIVMSG_PRIVATE(buffer): 300 | dst = re_SPLIT(buffer,3)[2].lower() 301 | if re_URC_PRIVMSG_PRIVATE(buffer) and dst.lower() not in localnicks: continue 302 | nick = buffer.split('!', 1)[0][1:] 303 | while nick in localnicks: nick = nick + "_" 304 | host = buffer.split(' ', 1)[0].split('@', 1)[1] 305 | if nick.lower() not in nicks: 306 | try_write(wr, 'NICK ' + nick + ' :1\n') 307 | try_write(wr, ':' + nick + ' USER remote ' + host + ' noIdea :real name\n') 308 | nicks[nick.lower()] = list() 309 | nicks[nick.lower()].append(nick) 310 | nicks[nick.lower()].append(time.time()) 311 | if DEBUG: try_write(wr,':urc2server PRIVMSG #status :nick added: ' + nick + '!remote@' + host + '\n') 312 | else: 313 | nicks[nick.lower()][1] = time.time(); 314 | if DEBUG: try_write(wr,':urc2server PRIVMSG #status :nick activity refreshed: ' + nick.lower() + '\n') 315 | if dst[0] in ['#','&']: try_write(wr, ':' + nick + ' JOIN ' + dst + ' :1\n') 316 | try_write(wr, ':' + nick + ' ' + buffer.split(' ', 1)[1]) 317 | elif re_URC_PART(buffer): 318 | nick = buffer.split('!', 1)[0][1:] 319 | if nick.lower() in nicks: 320 | dst = buffer.split(' ')[2] 321 | if DEBUG: try_write(wr,':urc2server PRIVMSG #status :' + nick + ' parted from channel ' + dst + '\n') 322 | try_write(wr, ':' + nick + ' ' + buffer.split(' ', 1)[1]) 323 | elif re_URC_QUIT(buffer): 324 | nick = buffer.split('!', 1)[0][1:] 325 | if nick.lower() in nicks: 326 | if DEBUG: try_write(wr,':urc2server PRIVMSG #status :' + nick + ' quit\n') 327 | try_write(wr, ':' + nick + ' ' + buffer.split(' ', 1)[1]) 328 | del nicks[nick.lower()] 329 | elif re_URC_JOIN(buffer): 330 | nick = buffer.split('!', 1)[0][1:] 331 | dst = buffer.split(' ')[2][1:] 332 | if not nick.lower() in nicks: 333 | while nick in localnicks: nick = nick + "_" 334 | host = buffer.split(' ', 1)[0].split('@', 1)[1] 335 | try_write(wr, 'NICK ' + nick + ' :1\n') 336 | try_write(wr, ':' + nick + ' USER remote ' + host + ' noIdea :real name\n') 337 | nicks[nick.lower()] = list() 338 | nicks[nick.lower()].append(nick) 339 | nicks[nick.lower()].append(time.time()) 340 | if DEBUG: try_write(wr,':urc2server PRIVMSG #status :' + nick.lower() + ' added\n') 341 | if DEBUG: try_write(wr,':urc2server PRIVMSG #status :' + nick + ' joined ' + dst + '\n') 342 | try_write(wr, ':' + nick + ' ' + buffer.split(' ', 1)[1]) 343 | 344 | -------------------------------------------------------------------------------- /db/urchub/i2p/7kmkqzx5egdannxhqt4b3fkqbo7jdjphwcf2viiph7qdqm3wlmaa.b32.i2p/owner: -------------------------------------------------------------------------------- 1 | jsw 2 | -------------------------------------------------------------------------------- /db/urchub/i2p/7kmkqzx5egdannxhqt4b3fkqbo7jdjphwcf2viiph7qdqm3wlmaa.b32.i2p/port: -------------------------------------------------------------------------------- 1 | 6789 2 | -------------------------------------------------------------------------------- /db/urchub/icann/josephswilliams.com/owner: -------------------------------------------------------------------------------- 1 | jsw 2 | -------------------------------------------------------------------------------- /db/urchub/icann/josephswilliams.com/port: -------------------------------------------------------------------------------- 1 | 6789 2 | -------------------------------------------------------------------------------- /db/urchub/icann/urc.freeanons.info/owner: -------------------------------------------------------------------------------- 1 | lulzprincess 2 | -------------------------------------------------------------------------------- /db/urchub/icann/urc.freeanons.info/port: -------------------------------------------------------------------------------- 1 | 6789 2 | -------------------------------------------------------------------------------- /db/urchub/tor/allyour4nert7pkh.onion/owner: -------------------------------------------------------------------------------- 1 | psi 2 | -------------------------------------------------------------------------------- /db/urchub/tor/allyour4nert7pkh.onion/port: -------------------------------------------------------------------------------- 1 | 4666 2 | -------------------------------------------------------------------------------- /db/urchub/tor/freeanonine7mgki.onion/owner: -------------------------------------------------------------------------------- 1 | lulzprincess 2 | -------------------------------------------------------------------------------- /db/urchub/tor/freeanonine7mgki.onion/port: -------------------------------------------------------------------------------- 1 | 6789 2 | -------------------------------------------------------------------------------- /db/urchub/tor/hppikcru545manbi.onion/owner: -------------------------------------------------------------------------------- 1 | epoch 2 | -------------------------------------------------------------------------------- /db/urchub/tor/hppikcru545manbi.onion/port: -------------------------------------------------------------------------------- 1 | 4666 2 | -------------------------------------------------------------------------------- /db/urchub/tor/ntwrkhhtqv73vwd4.onion/owner: -------------------------------------------------------------------------------- 1 | jsw 2 | -------------------------------------------------------------------------------- /db/urchub/tor/ntwrkhhtqv73vwd4.onion/port: -------------------------------------------------------------------------------- 1 | 6789 2 | -------------------------------------------------------------------------------- /doc/README.bak.txt: -------------------------------------------------------------------------------- 1 | urcd: 2 | af_unix relay chat daemon and 3 | af_unix relay chat daemon accessories... 4 | 5 | for more information regarding this software 6 | and the URC protocols, `less doc/URC'. 7 | 8 | depends: 9 | NaCl or libsodium, libtai, ucspi-tcp, 10 | python(>=2.6), python-dev(>=2.6), 11 | daemontools, sh, gcc 12 | 13 | recommends: 14 | NaCl instead of libsodium, 15 | cython(>=0.18.0) 16 | 17 | todo: 18 | fix hostmasks in urcd 19 | 20 | create URCHUB/URCLOCAL 21 | 22 | consider crypto modes for cryptoserv 23 | 24 | implement ban/except for clients without regex ignore. 25 | 26 | add a global hostmask option for users sending messages into 27 | urc from an ircnet for urc2sd. 28 | 29 | implement presence notifications for the ircd side in urc2sd. 30 | 31 | add encrypted channels to urc2sd. 32 | 33 | quick install (not recommended): 34 | 35 | # install dependencies, if you haven't already 36 | ./install-ucspi-tcp.sh 37 | ./install-libtai.sh 38 | 39 | # recommended over ./install-libsodium.sh 40 | ./install-nacl.sh 41 | 42 | useradd urcd 43 | 44 | $editor env/* 45 | 46 | # OpenBSD 47 | echo '-ftrampolines' > conf-cc 48 | 49 | # if python2.6 50 | sed 's/\.7/.6/g' Make.sh | sh -v 51 | 52 | # elif python2.7 53 | ./Make.sh 54 | ./bin/urcd.sh $ntwrk 55 | 56 | install (recommended): 57 | 58 | # install dependencies, if you haven't already 59 | ./install-daemontools.sh 60 | ./install-ucspi-tcp.sh 61 | ./install-libtai.sh 62 | 63 | # recommended over ./install-libsodium.sh 64 | ./install-nacl.sh 65 | 66 | useradd urcd 67 | 68 | # OpenBSD 69 | echo '-ftrampolines' > conf-cc 70 | 71 | # if python2.6 72 | sed 's/\.7/.6/g' Make.sh | sh -v 73 | 74 | # elif python2.7 75 | ./Make.sh 76 | 77 | # edit the network/hostmask 78 | $editor env/serv 79 | 80 | # edit the motd 81 | $editor env/motd 82 | 83 | ln -s `pwd` /service/urcd 84 | ./bin/add-urchub 85 | 86 | sleep 4 87 | svstat /service/urcd 88 | 89 | ### see the hub2hub section below it is ### 90 | ### recommended to connect to 3 urchubs ### 91 | 92 | adding curvecp: 93 | mkdir -p /services/urcd-curvecp 94 | 95 | ln -s `pwd`/env /services/urcd-curvecp/env 96 | ln -s `pwd`/urcd /services/urcd-curvecp/urcd 97 | ln -s `pwd`/run.urcd-curvecp /services/urcd-curvecp/run 98 | 99 | curvecpmakekey /services/urcd-curvecp/curvecp 100 | 101 | find /services/urcd-curvecp/curvecp -type d -exec chmod 700 {} \; 102 | find /services/urcd-curvecp/curvecp -type f -exec chmod 600 {} \; 103 | chown urcd /services/urcd-curvecp/curvecp -R 104 | 105 | ln -s /services/urcd-curvecp /service/urcd-curvecp 106 | 107 | sleep 4 108 | svstat /service/urcd-curvecp 109 | 110 | echo "PUBKEY: `curvecpprintkey /services/urcd-curvecp/curvecp`" 111 | 112 | curvecp + irc client (test): 113 | 114 | tcpserver 127.0.0.1 6667 \ 115 | curvecpclient irc.d3v11.ano `curvecpprintkey /services/urcd-curvecp/curvecp` \ 116 | `cat env/addr` `cat env/port` 01110101011100100110001101100100 \ 117 | curvecpmessage -c ./ucspi-stream & 118 | 119 | irssi -c 127.0.0.1 120 | 121 | interface: 122 | place an executable program in the cwd 123 | of urcd named 'stdin'. the program reads 124 | stdin from the irc client. anything your 125 | program writes to stdout will be written 126 | to urcd 127 | 128 | place an executable program in the cwd 129 | of urcd named 'stdout'. the program reads 130 | stdin from urcd. anything your program 131 | writes to stdout will be written to the 132 | irc client 133 | 134 | for urc2sd follow the same process. happy 135 | hacking. 136 | 137 | no censorship (security): 138 | URC networks are censorship resistant. i 139 | recommend URCSIGN and/or URCCRYPTOBOX to 140 | ignore spam and trolls. URCd will replace 141 | the user field with VERIFIED for users with 142 | valid authentication or signature verification. 143 | All other user fields will be replaced with 144 | URCD. e.g.: 145 | 146 | nick!URCD@server 147 | nick!VERIFIED@server 148 | 149 | irssi ("ban/except"): 150 | /ignore *!*@* ALL 151 | /ignore -except friend!*@* ALL 152 | /ignore -except *!VERIFIED@* ALL 153 | 154 | xchat ("ban/except"): 155 | /ignore *!*@* ALL 156 | /ignore friend!*@* ALL UNIGNORE 157 | /ignore *!VERIFIED@* ALL UNIGNORE 158 | 159 | URCSIGN (prototype, subject to change): 160 | ./sign_keypair 161 | 162 | # (global) save your seckey/pubkey and secure them 163 | $editor env/URCSIGNPUBKEY 164 | $editor env/URCSIGNSECKEY 165 | chmod 600 env/URCSIGNSECKEY 166 | 167 | # use a specific seckey for a destination, or override global 168 | mkdir -p urcsignseckeydir 169 | echo urcsignseckeydir > env/URCSIGNSECKEYDIR 170 | echo $seckey > urcsignseckeydir/\#channel 171 | chmod 600 urcsignseckeydir/ 172 | 173 | # save your friends' pubkeys and secure them 174 | mkdir -p urcsigndb/ 175 | chmod 600 urcsigndb/ 176 | echo $pubkey > urcsigndb/$nick 177 | echo urcsigndb/ > env/URCSIGNDB 178 | 179 | # use a specific pubkey for a destination, or override global 180 | mkdir -p urcsignpubkeydir 181 | echo urcsignpubkeydir > env/URCSIGNPUBKEYDIR 182 | echo $pubkey > urcsignpubkeydir/\#channel/nick 183 | chmod 600 urcsignpubkeydir/ 184 | 185 | # urcd will replace the user field with VERIFIED for valid 186 | # signatures and replace all other user fields with URCD. 187 | # see "no censorship" above. 188 | 189 | URCCRYPTOBOX: 190 | # urcd can provide secret and encrypted PM 191 | 192 | ./keypair 193 | echo $seckey > env/URCCRYPTOBOXSECKEY 194 | mkdir -p urccryptoboxdir/ 195 | echo urccryptoboxdir > env/URCCRYPTOBOXDIR 196 | echo $pubkey > urccryptoboxdir/$nick 197 | chmod 600 urccryptoboxdir/ 198 | 199 | # use a specific seckey for a destination, or override global 200 | mkdir -p urccryptoboxseckeydir/ 201 | echo urccryptoboxseckeydir > env/URCCRYPTOBOXSECKEYDIR 202 | echo $seckey > urccryptoboxseckeydir/$nick 203 | chmod 600 urccryptoboxseckeydir/ 204 | 205 | # urcd will replace the user field with VERIFIED for valid 206 | # authentication and replace all other user fields with URCD. 207 | # see "no censorship" above. 208 | 209 | URCCRYPTOBOXPFS: 210 | # urcd can provide secret perfect forward secrecy for encrypted PM 211 | # for destinations already configured for URCCRYPTOBOX. urcd will 212 | # send and error notice when unable to decrypt a session box. simply 213 | # respond to your friend to exchange session keys. if you want to 214 | # change session keys, simply /reconnect. urcd will not store any 215 | # session cryptography. both parties need to have this enabled to work. 216 | 217 | echo urccryptoboxpfs/ > env/URCCRYPTOBOXPFS 218 | mkdir -p urccryptoboxpfs/ 219 | chmod 600 urccryptoboxpfs/ 220 | touch urccryptoboxpfs/$nick 221 | 222 | URCSECRETBOX: 223 | urcd can provide secret and encrypted channels 224 | using a 64 byte hexadecimal key 225 | 226 | ./keypair # you only need the seckey 227 | mkdir -p urcsecretboxdir/ 228 | echo urcsecretboxdir > env/URCSECRETBOXDIR 229 | echo $seckey > urcsecretboxdir/\#channel 230 | chmod 600 urcsecretboxdir/ 231 | 232 | clients can also create channel encryption temporarily 233 | by submitting passwords to urcd. 234 | e.g.: 235 | 236 | /JOIN #channel password 237 | /MODE #channel +k password 238 | 239 | urcd PASS command (prototype, subject to change): 240 | remote clients can set or override URCSIGNSECKEY and/or 241 | URCCRYPTOBOXSECKEY by sending NaCl secret keys to urcd in 242 | hexadecimal format using the PASS command. there are three 243 | acceptable formats: 244 | 245 | 0.) a 128 byte key will set URCSIGNSECKEY only. 246 | 247 | 1.) a 64 byte key will set URCCRYPTOBOXSECKEY only. 248 | 249 | 2.) a 192 byte key will set URCCRYPTOBOXSECKEY using the first 250 | 64 bytes, and set URCSIGNSECKEY using the last 128 bytes. 251 | 252 | hub2hub: 253 | test -e /services/urcd-hub0/ || ./bin/add-urchub 254 | ./bin/add-urcstream2hub /service/urcd/socket/ /service/urcd-hub0/socket/ 255 | ./bin/add-hublisten your.urcd.ano 6789 /service/urcd-hub0/socket/ 256 | ./bin/add-hubconnect peer.urcd.ano 6789 /service/urcd-hub0/socket/ 257 | 258 | CryptoServ (requires NaCl): 259 | # stdin.cryptoserv will create cryptoservroot/urcsigndb 260 | # cryptoservroot/urccryptoboxdir, and cryptoservroot/urccryptoboxpfs 261 | # and point env/URCCRYPTOBOXDIR, env/URCCRYPTOBOXPFS, and 262 | # env/URCSIGNDB accordingly. 263 | 264 | ln -s stdin.cryptoserv stdin 265 | 266 | urc2sd: 267 | #urc2sd follows a similar convention as urcd by using a format 268 | #that distinguishes signed messages from nonverified messages. 269 | #i.e: signed messages appear as: "nick!sign@server> msg", 270 | #while nonsigned messages appear as "nick!urcd@server> msg". 271 | #urc2sd filters traffic coming from the urc network reliably 272 | #this way by using the ban and except masks set by the chanops 273 | #on the the ircnet's channels. 274 | 275 | mkdir -p /services/urc2sd 276 | 277 | ln -s `pwd`/urc2sd /services/urc2sd/urc2sd 278 | ln -s `pwd`/ucspi-client2server /services/urc2sd/ucspi-client2server 279 | 280 | # default 281 | ln -s `pwd`/run.urc2sd /services/urc2sd/run 282 | 283 | # tor 284 | ln -s `pwd`/run.urc2sd-tor /services/urc2sd/run 285 | ln -s `pwd`/ucspi-socks4aclient /services/urc2sd/ucspi-socks4aclient 286 | 287 | printf $addr > /services/urc2sd/addr 288 | printf $port > /services/urc2sd/port 289 | printf '/services/urcd-hub0/socket/' > /services/urc2sd/path 290 | printf 'urcd' > /services/urc2sd/nick 291 | printf '#channel' > /services/urc2sd/channels 292 | 293 | touch /services/urc2sd/auto_cmd 294 | 295 | ln -s /services/urc2sd /service/urc2sd 296 | 297 | POLICY and ISUPPORT: 298 | these values are filenames inside env/ and contain different types of data. 299 | 300 | IDLE: 301 | integer argument with a default of 2048 seconds. this value dictates how long 302 | remote clients can idle before their presence is dropped. 303 | 304 | PING: 305 | integer argument with a default of 16 seconds. this value dictates the ping 306 | intervals to a client, and the amount of time a client has to perform 307 | a connection. if PING is activated and the client doesn't respond within 308 | the specified time before TIMEOUT, the client is dropped. a 0 value will 309 | disable this feature. 310 | 311 | URCDB: 312 | default is empty. adding a /path/to/urc.db will tell urcd where to store a 313 | database. the database stores information from the network. this prevents 314 | losing this information between connections. (security) set chmod 600 on 315 | this file after it is created. e.g.: /topic, /names, and /list. 316 | 317 | WARNING: 318 | using this option on public urcd's, or sharing a database from a private 319 | urcd can reveal /topic, /names, and /list to unprivileged clients. 320 | 321 | FLOOD: 322 | integer argument with a default threshold of 8. every write to the network 323 | by a client increments the flood counter. if the flood counter breaches the 324 | threshold the client will lose ability to write to the network until the 325 | counter returns below the threshold value. a 0 value will disable this 326 | feature. 327 | 328 | LIMIT: 329 | float argument default is 1.0. this is the maximum rate in which a client 330 | can write to the network. 331 | 332 | EXPIRY: 333 | integer argument with a default of 32 days. this is how long a CryptoServ 334 | account has until it is deleted from inactivity. setting this value to 0 335 | will disable account expirations. 336 | 337 | COLOUR: 338 | integer default is 0. changing this value to 1 will allow colour encoding 339 | to pass to the client. 340 | 341 | UNICODE: 342 | integer default is 0. changing this value to 1 will allow unicode encoding 343 | to pass to the client. 344 | 345 | NICKLEN: 346 | integer default is 32. this is the maximum byte length of acceptable nick's 347 | on the network. 348 | 349 | TIMEOUT: 350 | integer default is 256. this value represents the allowed time a client 351 | can remain silent before their connection is dropped. this value also 352 | represents how often URCDB is synchronized if enabled. 353 | 354 | PRESENCE: 355 | integer default is 0. changing this value to 1 will announce JOIN, PART, 356 | and QUIT messages from the client to the network. 357 | 358 | TOPICLEN: 359 | integer default is 512. this is the maximum byte length of acceptable 360 | topics. 361 | 362 | CHANLIMIT: 363 | integer default is 64. this value represents the maximum amount of channels 364 | and the maximum amount of users that can participate in channels. 365 | 366 | CHANNELLEN: 367 | integer default is 64. this value represents the maximum byte length of 368 | channels on the network. 369 | 370 | PADDING: 371 | integer default is 255. this value represents the block sizes of encrypted 372 | packets. setting a 0 value will disable this feature, however it is not 373 | recommended. 374 | 375 | BROADCAST: 376 | integer default is 0. setting this value to 1 enables UDP broadcasts in 377 | urc-udpsend and urc-udprecv. 378 | 379 | logging URC services: 380 | mkdir -p /path/to/urcd-service/log/ 381 | ln -s run.log /path/to/urcd-service/log/run 382 | supervise /path/to/urcd-service/log 2>/dev/null & disown 383 | sleep 4 384 | svstat /path/to/urcd-service/log 385 | svc -t /path/to/urcd-service/ 386 | -------------------------------------------------------------------------------- /doc/URC.txt: -------------------------------------------------------------------------------- 1 | Description: 2 | An IRC style, private, security aware, open source project called URC. 3 | URC is supported by multiple daemons and programs in this suite for building, 4 | connecting, and/or bridging existing URC networks. If configured and understood 5 | properly, URC can be as easy as using the IRC client you favor, while being 6 | as private and secure as enterprise, military, and/or critical systems. In 7 | example, Alice can connect to her local URCd with her IRC client and listen to 8 | channels without anyone knowing she is present until she sends a message. If 9 | Alice sends Bob an encrypted private message while enjoying URC, the message 10 | will be delivered to Bob without anyone knowing exactly when Alice sent the 11 | message, to whom the message was delivered, the contents of the message, nor 12 | details, such as the size. URC can also support similar encrypted conferences 13 | in the password protected channels, or chat privately or publically among 14 | friends. The cryptography in URC also allows clients to verify who they are 15 | among other clients if necessary. 16 | 17 | 18 | Advantages: 19 | Anonymity - URC doesn't care about IP or Ident, and doesn't reveal this 20 | information to other users on the network. The server/hostmask section of a 21 | URCLINE is always a hostmask chosen by the user. When a client sends a URC 22 | packet across the network, the sender's physical location is protected, by 23 | scattering the packet throughout the network in a randomly chosen order, i.e. 24 | the receiver is also protected. 25 | 26 | No Government or Censorship - In the URC network, you decide the policies for 27 | yourself, rather than someone else choosing them for you. 28 | 29 | NO Presence - URCd, by default, does not announce JOIN, PART, or QUIT messages, 30 | therefore a user's activities and timing are protected. 31 | 32 | Plausible Deniability - URC packets that are not signed cannot prove a specific 33 | user created a message. Admins using URCd and CryptoServ also have a unique 34 | advantage, in that they can deny knowing a secret key because the keys can be 35 | sent remotely and are not stored on the server. 36 | 37 | NO NickServ/Chanserv - NickServ and ChanServ are replaced by signatures and 38 | encryption, that come optional to the user. 39 | 40 | NO CTCP/DCC - URCd automatically blocks both of these protocols before they can 41 | access an IRC client, preventing many leaks and exploits. 42 | 43 | NO Encoding - URCd automatically blocks colour and unicode unless the 44 | administrator allows encoding. This is due to a number of exploits in the past 45 | associated with parsing. 46 | 47 | AntiSurveillance - Encrypted URC packets do not reveal the source or 48 | destination of a packet. Instead they rely on NaCl's highspeed Poly1305, or 49 | encrypted signatures for authentication and verification. Thus, an attacker 50 | sniffing the network cannot target specific conversations because they contain 51 | no identifying marks compared against other encrypted traffic. Only user's with 52 | the correct keys can discover this information. By default, all encrypted 53 | packets are padded to protect against other side channels. 54 | 55 | Security Aware - URC is written in a small amount of open source C and Python 56 | code. URC daemons only function inside of a chroot jail with only the 57 | privileges necessary to run, and includes a simple urc_jail function with 58 | LibURC to make this easy to setup. URC supports the new record setting 59 | Networking and Cryptographic library (NaCl), rather than older, bloated, and 60 | slower libraries of the past. URC daemons also support CurveCP and TOR rather 61 | than SSL and TLS for links and encrypted connections. The current URCd software 62 | is however flexible enough to wrap the URCHUB protocol with other security 63 | layers. 64 | 65 | Simple API and Modularity - URCd allows the user to "hack" his or her 66 | conversation with their local daemon with any programming language, so long as 67 | the user can read and write with stdin and stdout, and can parse URCLINE 68 | (simplified IRC lines). URCd also ships with LibURC, a library for creating 69 | plaintext, encrypted, and signed URC packets from IRC lines. LibURC is a very 70 | simple library, that is written in C, and contains wrappers for Python, and 71 | soon other languages as well. URCd utilizes the wisdom of the Unix philosophy 72 | in its design, so that it's flexible, legible, and modular with interchangeable 73 | components. 74 | 75 | Stateless - URC is a stateless broadcast protocol that can easily use a variety 76 | of networks to send data, where each hop is a similar to a radio hub or signal 77 | repeater. This keeps overhead low and simplicity unlocks room for expansion and 78 | scalability. Demands like cpu and memory requirements can be kept to a minimum. 79 | 80 | Scalability - URC can span multiple networks, such as LAN, WLAN, VPN, TOR, I2P, 81 | and other networks, by using UDP broadcasts, multicast groups, and TCP streams. 82 | Other protocols can easily integrate URC into existing networks as well. 83 | 84 | Taia96n - LibURC's implementation can easily be modified to provide nano second 85 | accuracy, but this is not necessary. Taia96n is a 96 bit timestamp, accurate to 86 | roughly the first 60 bits in network byte order. Masking the last 36 bits 87 | allows URC nodes to mitigate the risk of leaking clockskew and other side 88 | channel attacks. The randomization of the last 36 bits also increases the 89 | entropy for the cryptographic nonce bytes used in the URCHUB protocol. This 90 | protocol will not expire within the next few billion years. 91 | 92 | No Trust - The URC protocol and supporting softwares take a different approach 93 | to an often overlooked point of failure used on many crypto and communication 94 | systems. URC does not need a third party to establish private, and secure 95 | communications over a decentralized network. For example, URC does not require, 96 | nor allow another server to verify the authenticity of a client's messages, nor 97 | does the protocol require or allow remote systems to overide or alter the 98 | policies on someone's local URCd. 99 | 100 | Entropy - LibURC ships with it's own secure randombytes implementation 101 | that is powered by NaCl's crypto_stream function, providing strong and reliable 102 | entropy, suitable in chroot environments. A nonce and a one time secret key are 103 | derived using the strongest nonblocking available RNG and crypto_hash_sha512 to 104 | generate an arbitrary amount of random data without depleting the system's 105 | entropy pool. Should the onboard RNG ever fail, the LibURC randombytes function 106 | will not. the implementation has a secure failover using variable information 107 | from the system clock and other status information. 108 | 109 | 110 | URCLINE: 111 | A URCLINE is similar to a line of IRC. These lines are wrapped and 112 | distributed using the URCHUB protocol. 113 | 114 | PRIVMSG, NOTICE, TOPIC, INVITE will send a message to URC node(s). These 115 | lines SHOULD have a similar effect as IRC equivalents. 116 | 117 | :nick!user@server PRIVMSG #channel :message\n 118 | :nick!user@server NOTICE #channel :message\n 119 | :nick!user@server TOPIC #channel :message\n 120 | :nick!user@server INVITE nick :#channel\n 121 | 122 | JOIN, PART, QUIT, KICK can be used by listeners to learn presence. 123 | There's no mandate for a URCd daemon to announce presence, as this can 124 | be learned through natural message traffic. Currently presence is only 125 | default in URC2sd to sync with URCd and to announce censorship from IRCd 126 | admins. 127 | 128 | :nick!user@server PART #channel :message\n 129 | :nick!user@server QUIT :message\n 130 | :nick!user@server JOIN :#channel\n 131 | :oper!user@server KICK #channel nick :message\n 132 | 133 | URCHUB: 134 | URCHUB is the default protocol for transporting URC packets across the 135 | network. The first field is a 16bit length (LEN) in network byte order. 136 | While 16bit LEN can represent 65535 bytes of data the MTU of URC is 1024 137 | bytes, or one kilobyte. The second field of URCHUB is taia96n, a 12 byte 138 | timestamp in network byte order that is accurate to nano seconds. The 139 | third field is a 32bit CMD and is currently used to distinguish types of 140 | packets. The last 24 bits of CMD SHOULD remain NULL until future usages 141 | are necessary. The fourth field are 64bits of random data that ensures 142 | uniqueness of a packet. The fifth field is the payload and it's size 143 | MUST be reflected by the 16bit LEN field. Generally this field is a 144 | URCLINE, but can also contain binary or alternative data. 145 | 146 | | 16bit LEN | 96bit taia96n | \0\0\0\0 | 64bit random | URCLINE | 147 | 148 | By default CMD is NULL unless stated otherwise. 149 | 150 | URCHUB/URCSIGN: 151 | | 16bit LEN | 96bit taia96n | \1\0\0\0 | 64bit random | URCLINE | 512bit 152 | SIGNATURE | 153 | 154 | SIGNATURE is the 64 signature bytes from the crypto_sign function in 155 | NaCl's API. The entire message is used to derive SIGNATURE with CMD set 156 | to prevent signatures from being replayed in other protocols of URC. 157 | 158 | URCHUB/URCSECRETBOX: 159 | | 16bit LEN | 96bit taia96n | \2\0\0\0 | 64bit random | CRYPTO_SECRETBOX | 160 | 161 | CRYPTO_SECRETBOX is a combination of poly1305 (MAC) and xsalsa20 (stream 162 | cipher) that is used to encrypt the URCLINE. The taia96n label, CMD, and 163 | random bytes are used as the NONCE, and the secret key is chosen prior 164 | to encryption. 165 | 166 | URCHUB/URCSIGNSECRETBOX: 167 | | 16bit LEN | 96bit taia96n | \3\0\0\0 | 64bit random | CRYPTO_SECRETBOX | 168 | 169 | A packet is signed the same manner described in URCSIGN before 170 | encryption, to prevent signature replays, and side channels. 171 | 172 | URCHUB/URCCRYPTOBOX: 173 | | 16bit LEN | 96bit taia96n | \4\0\0\0 | 64bit random | CRYPTO_BOX | 174 | 175 | CRYPTO_BOX is a combination of curve25519 (DH), poly1305 (MAC), and 176 | xsalsa20 (stream cipher) that is used to encrypt the URCLINE. The 177 | taia96n label, CMD, and random bytes are used as the NONCE. The secret 178 | key is derived from a curve25519 diffie-hellman key exchange. 179 | 180 | URCHUB/URCCRYPTOBOX/PFS: 181 | | 16bit LEN | 96bit taia96n | \5\0\0\0 | 64bit random | [ CRYPTO_BOX1 182 | |CRYPTO_BOX0| ] | 183 | 184 | CRYPTO_BOX1 is derived using the same method as URCHUB/URCCRYPTOBOX and 185 | contains a 32 byte temporary public key from the sender followed by the 186 | encrypted URCLINE. NONCE bytes are the same in CRYPTO_BOX0 and 187 | CRYPTO_BOX1. 188 | 189 | Download and Install: 190 | 191 | Upstream: 192 | git clone git://josephswilliams.com/urcd.git /usr/local/src/urcd 193 | 194 | GitHub: 195 | git clone git://github.com/JosephSWilliams/urcd /usr/local/src/urcd 196 | 197 | Tor: 198 | torify git clone git://ntwrkhhtqv73vwd4.onion/urcd.git /usr/local/src/urcd 199 | 200 | Simply follow the instructions in the urcd/README. Feel free to contact me 201 | if you have complaints or suggestions. Happy hacking :-). 202 | -------------------------------------------------------------------------------- /doc/topology.txt: -------------------------------------------------------------------------------- 1 | /* 2 | This document decribes the magick of URC routing. 3 | */ 4 | 5 | 6 | A node will consist of a urchub that SHOULD accept public connections and a 7 | private URCd on localhost. Hosting a seperate public URCd is optional. IRC 8 | clients connect to a URCd, that acts as an IRC server by translating URC packets 9 | that travel a URC network of urchubs. When an IRC client sends a message to 10 | URCd, it converts it to a urchub format and broadcasts it across the network. 11 | There are a number of factors that ensure messages can remain as private as 12 | possible while mechanisms in urchub protocols allow noise to be filtered easily. 13 | Noise can be defined messages like spam, or messages from unverified sources, or 14 | unencrypted clients. If you are interested in cryptography and URC primitives 15 | then view doc/URC. 16 | 17 | 18 | ------------------ 19 | | | | | 20 | | | | | 21 | -------- ---- 22 | | ----- --- 23 | |----- --- 24 | ------------ 25 | /* example URC network */ 26 | 27 | 28 | In the above example, an IRC client sending a message to URCd, is able to 29 | reach every other IRC client connected to a URCd on any URC node. Messages 30 | sent from a URC node to a urchub, are broadcasted to each other urchub connected 31 | to it, and each correct IRC client once it is translated by URCd. URC allows 32 | messages to seemlessly flow among multiple networks, such as Tor, i2p, 33 | Anonet, and other networks without additional software or configurations if 34 | there is at least one route between each client. A client connected to any URC 35 | node in the example above could send a message that would be available to each 36 | IRC client connected to another URC node. Every URC node using the URCd software 37 | suite has builtin protection mechanisms against flood, DoS/DDOS, and exploits. 38 | Countermeasures are taken in URC's timing, encryption, authentication, and 39 | signature algorithms to maximize privacy. 40 | 41 | 42 | /* example program map */ 43 | 44 | 45 | ircclient 46 | | 47 | <------. ircclient | 48 | | *------> ircd <- urc2sd -. 49 | v | 50 | urchubstream -. | 51 | | | 52 | urcd -> urchub/urccache -> urchubstream | 53 | | \ | 54 | | ircclient ---------> urcd -> urchub/urccache 55 | | | 56 | *-> ircclient urchubstream 57 | *-> ircclient | 58 | v 59 | 60 | 61 | The urchub is the cornerstone of any URC node. Data flows among all the hubs 62 | on the network, and each packet reaches each node. URC does not restrict you 63 | from methods of communication. If you find that URC is difficult to traffic 64 | with your network and/or particular software, please complain so that *I* can 65 | fix it, or at least point you in the right direction. I make no guarantees, 66 | however URC has a history of little to no issues here. 67 | 68 | URC's cache detects duplicate packets and instructs the hub to discard them. 69 | The cache communicates to the hub via pipe and the other URC programs use 70 | AF_UNIX, SOCK_DGRAM. Multiple protocols in the transport layer can carry URC 71 | packets between urchubs. 72 | -------------------------------------------------------------------------------- /env/addr: -------------------------------------------------------------------------------- 1 | 127.0.0.1 -------------------------------------------------------------------------------- /env/motd: -------------------------------------------------------------------------------- 1 | 2 | "I have tried everything from voting petitions to peaceful 3 | protest and have found that those in power do not want the 4 | truth to be exposed. When we speak truth to power we are 5 | ignored at best and brutally suppressed at worst. We are 6 | confronting a power structure that does not respect its own 7 | system of checks and balances, never mind the rights of it’s 8 | own citizens or the international community." - Jeremy Hammond 9 | 10 | "Information is power. But like all power, there are those who 11 | want to keep it for themselves. The world’s entire scientific 12 | and cultural heritage, published over centuries in books and 13 | journals, is increasingly being digitized and locked up by a 14 | handful of private corporations." - Aaron Swartz 15 | 16 | "Ten years ago it would have been infeasible for tens of 17 | thousands of individuals with no physical connection or 18 | central leadership to conceive, announce, and implement a 19 | massive act of civil disobedience against a significant 20 | Western power, crippling a portion of its online 21 | infrastructure in the process - and to do all of this in a 22 | matter of days, and without anyone involved having to contend 23 | with the tear-gas-and-horseback response with which states 24 | have traditionally been in the habit of contending with mass 25 | action. But such a thing as this is happening today, and having 26 | been done once will almost certainly be done again - repeatedly, 27 | increasingly, and with potentially significant consequences for 28 | the nation-state and implications regarding that which will 29 | perhaps someday come to replace it." - Barrett Brown 30 | -------------------------------------------------------------------------------- /env/path: -------------------------------------------------------------------------------- 1 | /service/urcd-hub0/socket/ 2 | -------------------------------------------------------------------------------- /env/port: -------------------------------------------------------------------------------- 1 | 6667 -------------------------------------------------------------------------------- /env/serv: -------------------------------------------------------------------------------- 1 | irc.urcd.ano 2 | -------------------------------------------------------------------------------- /git-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | git add -f \ 3 | git-commit \ 4 | git-push-github \ 5 | .gitignore \ 6 | gitd \ 7 | Make.sh \ 8 | run \ 9 | run.log \ 10 | run.urcd-curvecp \ 11 | run.urc2sd \ 12 | run.urc2sd-tor \ 13 | src \ 14 | README \ 15 | install-*.sh \ 16 | db \ 17 | contrib/ \ 18 | doc/ \ 19 | stdin.cryptoserv \ 20 | COPYRIGHT \ 21 | THANKS \ 22 | LICENSE \ 23 | DONATE 24 | 25 | TZ=UTC git commit --date="`date -u +'%s'`" 26 | test -x /usr/lib/git-core/git-update-server-info && /usr/lib/git-core/git-update-server-info 27 | -------------------------------------------------------------------------------- /git-push-github: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # bet you wish you had the passwd 3 | 4 | torify git push https://github.com/JosephSWilliams/urcd.git master 5 | -------------------------------------------------------------------------------- /gitd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | repodir="$(dirname $0)" 3 | touch "$repodir"/.git/git-daemon-export-ok 4 | exec git daemon --listen="$(cat "$repodir"/conf/gitd_ip)" --base-path="$(cat "$repodir"/conf/gitd_basepath)" --reuseaddr 5 | -------------------------------------------------------------------------------- /install-daemontools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### is this really necessary? ### 4 | mkdir -p /package 5 | chmod 1755 /package 6 | cd /package 7 | 8 | ### download and unpack daemontools ### 9 | if which wget 2>/dev/null 1>&2; then 10 | retr=wget 11 | elif which curl 2>/dev/null 1>&2; then 12 | retr="curl -O" 13 | elif which ftp 2>/dev/null 1>&2; then 14 | retr="ftp" 15 | else 16 | echo "could not find any appropiate way to download sources, no wget, curl or ftp in PATH"; 17 | exit 1; 18 | fi 19 | $retr http://cr.yp.to/daemontools/daemontools-0.76.tar.gz 20 | gunzip daemontools-0.76.tar 21 | tar -xpf daemontools-0.76.tar 22 | rm -f daemontools-0.76.tar 23 | cd admin/daemontools-0.76 24 | 25 | ### workaround libc bug ### 26 | sed -i 's/gcc/gcc -include errno.h/' src/conf-cc 27 | 28 | ### compile and install ### 29 | package/install 30 | 31 | ### workaround debian/ubuntu ### 32 | if which apt-get; then 33 | sed -i 's/^exit 0/\/command\/svscanboot \&\n\nexit 0/' /etc/rc.local 34 | ### i don't think we need a reboot to bootstrap daemontools ### 35 | /command/svscanboot 2>/dev/null & disown 36 | chmod +x /etc/rc.local 37 | fi 38 | 39 | ### we want this directory ### 40 | mkdir -p /services/ 41 | -------------------------------------------------------------------------------- /install-libsodium.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if which wget 2>/dev/null 1>&2; then 4 | retr=wget 5 | elif which curl 2>/dev/null 1>&2; then 6 | retr="curl -O" 7 | elif which ftp 2>/dev/null 1>&2; then 8 | retr="ftp" 9 | else 10 | echo "could not find any appropiate way to download sources, no wget, curl or ftp in PATH"; 11 | exit 1; 12 | fi 13 | 14 | rm -rf libsodium-0.6.0 15 | [ -f libsodium-0.6.0.tar.gz ] || $retr http://download.libsodium.org/libsodium/releases/libsodium-0.6.0.tar.gz 16 | tar xzf libsodium-0.6.0.tar.gz 17 | 18 | cd libsodium-0.6.0 19 | 20 | ./configure && make && make install 21 | -------------------------------------------------------------------------------- /install-libtai.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Workaround script for creating shared objects on 64-bit 3 | # architectures with libtai. 4 | 5 | # OpenBSD: check for nroff (groff) 6 | if ! which nroff 1>/dev/null; then 7 | echo 'fatal error: need to install nroff (groff)' 8 | exit 1 9 | fi 10 | 11 | if which wget 2>/dev/null 1>&2; then 12 | retr=wget 13 | elif which curl 2>/dev/null 1>&2; then 14 | retr="curl -O" 15 | elif which ftp 2>/dev/null 1>&2; then 16 | retr="ftp" 17 | else 18 | echo "could not find any appropiate way to download sources, no wget, curl or ftp in PATH"; 19 | exit 1; 20 | fi 21 | 22 | rm -rf libtai-0.60 23 | [ -f libtai-0.60.tar.gz ] || $retr http://cr.yp.to/libtai/libtai-0.60.tar.gz 24 | tar xzf libtai-0.60.tar.gz 25 | 26 | cd libtai-0.60 27 | 28 | if ! sed -i 's/$/ -fPIC/' conf-* 2>/dev/null; then 29 | for item in $(ls conf-*); do 30 | sed 's/$/ -fPIC/' $item > $item{new} 31 | mv $item{new} $item 32 | done 33 | fi 34 | 35 | make 36 | 37 | cp libtai.a /usr/lib/libtai.a 38 | cp *.h /usr/include/ 39 | cp leapsecs.dat /etc/leapsecs.dat 40 | -------------------------------------------------------------------------------- /install-nacl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Workaround script for creating shared objects on 64-bit 3 | # architectures with NaCl. Much thanks to Ivo Smits for 4 | # doing a lot of the work. Thanks to SeekingFor, some 5 | # strange anonymous type person, for OpenBSD support. 6 | 7 | if which wget 2>/dev/null 1>&2; then 8 | retr=wget 9 | elif which curl 2>/dev/null 1>&2; then 10 | retr="curl -O" 11 | elif which ftp 2>/dev/null 1>&2; then 12 | retr=ftp 13 | else 14 | echo "could not find any appropiate way to download sources, no wget, curl or ftp in PATH"; 15 | exit 1; 16 | fi 17 | rm -rf nacl-20110221 18 | [ -f nacl-20110221.tar.bz2 ] || $retr http://hyperelliptic.org/nacl/nacl-20110221.tar.bz2 19 | bunzip2 < nacl-20110221.tar.bz2 | tar -xf - 20 | 21 | # Use my patched copy of curvecpserver.c 22 | # sets env $CURVECPCLIENTPUBKEY from a curvecpclient 23 | # clientlongtermpk for programs to check client authentication. 24 | # I hope we'll see this in the main distribution. ucspi-tcp 25 | # style environment variables with *.cdb rules would be nice :-) 26 | # (I replaced all the \tabs with 2 spaces, eww tab) 27 | cat src/curvecpserver.c > nacl-20110221/curvecp/curvecpserver.c 28 | 29 | # Use my patched copy of socket_bind.c 30 | # if AF_UNSPEC fails then try using AF_INET 31 | cat src/socket_bind.c > nacl-20110221/curvecp/socket_bind.c 32 | 33 | cd nacl-20110221 34 | 35 | # ./do will compile an alternative MAC implementation 36 | # that works with shared objects. 37 | rm -r crypto_onetimeauth/poly1305/amd64 38 | 39 | # android patch 40 | echo 'gcc' >> okcompilers/c 41 | 42 | # patch the library for making shared objects on 64 bit 43 | # architectures by compiling with PIC. 44 | if ! sed -i "s/$/ -fPIC/" okcompilers/c 2>/dev/null; then 45 | sed "s/$/ -fPIC/" okcompilers/c > okcompilers/c{new} 46 | mv okcompilers/c{new} okcompilers/c 47 | fi 48 | echo "Starting to compile and benchmark NaCl so it will use the best available implementations for your specific hardware. This might take some time." 49 | ./do 50 | 51 | gcc okcompilers/abiname.c -o abiname 52 | ABINAME="$(./abiname "" | cut -b 2-)" 53 | BUILDDIR="build/$(hostname | sed 's/\..*//' | tr -cd '[a-z][A-Z][0-9]')" 54 | 55 | # install nacl/build in meaningful directories 56 | mkdir -p /usr/include/nacl 57 | cp -i "${BUILDDIR}/bin/"* /usr/bin/ 58 | cp -i "${BUILDDIR}/lib/${ABINAME}/"* /usr/lib/ 59 | cp -i "${BUILDDIR}/include/${ABINAME}/"* /usr/include/nacl/ 60 | -------------------------------------------------------------------------------- /install-ucspi-ssl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ### is this really necessary? ### 4 | mkdir -p /package 5 | chmod 1755 /package 6 | cd /package 7 | 8 | if which wget 2>/dev/null 1>&2; then 9 | retr=wget 10 | elif which curl 2>/dev/null 1>&2; then 11 | retr="curl -O" 12 | elif which ftp 2>/dev/null 1>&2; then 13 | retr="ftp" 14 | else 15 | echo "could not find any appropiate way to download sources, no wget, curl or ftp in PATH"; 16 | exit 1; 17 | fi 18 | 19 | $retr http://www.fehcom.de/ipnet/ucspi-ssl/ucspi-ssl-0.95b.tgz 20 | tar -xf ucspi-ssl-0.95b.tgz 21 | cd host/superscript.com/net/ucspi-ssl-0.95b 22 | 23 | ### compile and install ### 24 | package/install 25 | -------------------------------------------------------------------------------- /install-ucspi-tcp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if which wget 2>/dev/null 1>&2; then 4 | retr=wget 5 | elif which curl 2>/dev/null 1>&2; then 6 | retr="curl -O" 7 | elif which ftp 2>/dev/null 1>&2; then 8 | retr="ftp" 9 | else 10 | echo "could not find any appropiate way to download sources, no wget, curl or ftp in PATH"; 11 | exit 1; 12 | fi 13 | 14 | $retr http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz 15 | gunzip ucspi-tcp-0.88.tar 16 | tar -xf ucspi-tcp-0.88.tar 17 | cd ucspi-tcp-0.88/ 18 | sed -i 's/^gcc/gcc -include errno.h/' conf-cc 19 | make 20 | make setup check 21 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | exec tcpserver -H -R -l `cat env/addr` `cat env/addr` `cat env/port` ./urcd `cat env/path` 2>&1 3 | -------------------------------------------------------------------------------- /run.log: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | mkdir -p main/ 3 | chown urcd main/ 4 | exec setuidgid urcd multilog t ./main 5 | -------------------------------------------------------------------------------- /run.urc2sd: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | exec tcpclient `cat addr` `cat port` ./ucspi-client2server ./urc2sd `cat path` 2>&1 3 | -------------------------------------------------------------------------------- /run.urc2sd-tor: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | exec tcpclient 127.0.0.1 9050 ./ucspi-socks4aclient `cat addr` `cat port` ./ucspi-client2server ./urc2sd `cat path` 2>&1 3 | -------------------------------------------------------------------------------- /run.urcd-curvecp: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | exec curvecpserver `cat env/serv` curvecp `cat env/addr` `cat env/port` 01110101011100100110001101100100 curvecpmessage ./urcd `cat env/path` 2>&1 3 | -------------------------------------------------------------------------------- /run.urcd-ssl: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | export DHFILE="env/urcd.pem" 4 | export KEYFILE="env/urcd.key" 5 | export CERTFILE="env/urcd.crt" 6 | 7 | exec sslserver -H -R -l `cat env/addr` `cat env/addr` `cat env/port` ./urcd `cat env/path` 2>&1 8 | -------------------------------------------------------------------------------- /scripts/add-curvecpconnect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $5 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-curvecpconnect-"$1:$2" || exit 1 7 | 8 | printf $4 > /services/urcd-curvecpconnect-"$1:$2"/serv || exit 1 9 | 10 | printf $5 > /services/urcd-curvecpconnect-"$1:$2"/pubkey || exit 1 11 | 12 | printf \ 13 | "#!/bin/sh -e 14 | export TCPCLIENT=1 15 | exec curvecpclient \`cat serv\` \`cat pubkey\` $1 $2 01110101011100100110001101100100 curvecpmessage -c ./urcstream $3\n" > \ 16 | /services/urcd-curvecpconnect-"$1:$2"/run || exit 17 | 18 | chmod +x /services/urcd-curvecpconnect-"$1:$2"/run || exit 1 19 | 20 | test -L /services/urcd-curvecpconnect-"$1:$2"/urcstream || \ 21 | ln -s `pwd`/urcstream /services/urcd-curvecpconnect-"$1:$2"/urcstream || \ 22 | exit 1 23 | 24 | test -L /service/urcd-curvecpconnect-"$1:$2" || \ 25 | ln -s /services/urcd-curvecpconnect-"$1:$2" \ 26 | /service/urcd-curvecpconnect-"$1:$2" || \ 27 | exit 1 28 | -------------------------------------------------------------------------------- /scripts/add-curvecphubconnect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $5 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-curvecphubconnect-"$1:$2" || exit 1 7 | 8 | printf $4 > /services/urcd-curvecphubconnect-"$1:$2"/serv || exit 1 9 | 10 | printf $5 > /services/urcd-curvecphubconnect-"$1:$2"/pubkey || exit 1 11 | 12 | printf \ 13 | "#!/bin/sh -e 14 | export TCPCLIENT=1 15 | exec curvecpclient \`cat serv\` \`cat pubkey\` $1 $2 01110101011100100110001101100100 curvecpmessage -c ./urchubstream $3\n" > \ 16 | /services/urcd-curvecphubconnect-"$1:$2"/run || exit 17 | 18 | chmod +x /services/urcd-curvecphubconnect-"$1:$2"/run || exit 1 19 | 20 | test -L /services/urcd-curvecphubconnect-"$1:$2"/urcstream || \ 21 | ln -s `pwd`/urchubstream /services/urcd-curvecphubconnect-"$1:$2"/urchubstream || \ 22 | exit 1 23 | 24 | test -L /service/urcd-curvecphubconnect-"$1:$2" || \ 25 | ln -s /services/urcd-curvecphubconnect-"$1:$2" \ 26 | /service/urcd-curvecphubconnect-"$1:$2" || \ 27 | exit 1 28 | -------------------------------------------------------------------------------- /scripts/add-curvecphublisten: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-curvecphublisten-"$1:$2" || exit 1 7 | 8 | test -L /services/urcd-curvecphublisten-"$1:$2"/serv || \ 9 | ln -s `pwd`/env/serv /services/urcd-curvecphublisten-"$1:$2"/serv || \ 10 | exit 1 11 | 12 | curvecpmakekey /services/urcd-curvecphublisten-"$1:$2"/curvecp || exit 1 13 | 14 | find /services/urcd-curvecphublisten-"$1:$2"/curvecp -type d -exec chmod 700 {} \; 15 | find /services/urcd-curvecphublisten-"$1:$2"/curvecp -type f -exec chmod 600 {} \; 16 | chown urcd /services/urcd-curvecphublisten-"$1:$2"/curvecp -R 17 | 18 | printf \ 19 | "#!/bin/sh -e 20 | exec curvecpserver \`cat serv\` curvecp $1 $2 01110101011100100110001101100100 curvecpmessage ./urchubstream $3\n" > \ 21 | /services/urcd-curvecphublisten-"$1:$2"/run || exit 22 | 23 | chmod +x /services/urcd-curvecphublisten-"$1:$2"/run || exit 1 24 | 25 | test -L /services/urcd-curvecphublisten-"$1:$2"/urchubstream || \ 26 | ln -s `pwd`/urchubstream /services/urcd-curvecphublisten-"$1:$2"/urchubstream || \ 27 | exit 1 28 | 29 | test -L /service/urcd-curvecphublisten-"$1:$2" || \ 30 | ln -s /services/urcd-curvecphublisten-"$1:$2" \ 31 | /service/urcd-curvecphublisten-"$1:$2" || \ 32 | exit 1 33 | 34 | printf \ 35 | "PUBKEY: `curvecpprintkey /services/urcd-curvecphublisten-"$1:$2"/curvecp`\n" 36 | -------------------------------------------------------------------------------- /scripts/add-curvecplisten: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-curvecplisten-"$1:$2" || exit 1 7 | 8 | test -L /services/urcd-curvecplisten-"$1:$2"/serv || \ 9 | ln -s `pwd`/env/serv /services/urcd-curvecplisten-"$1:$2"/serv || \ 10 | exit 1 11 | 12 | curvecpmakekey /services/urcd-curvecplisten-"$1:$2"/curvecp || exit 1 13 | 14 | find /services/urcd-curvecplisten-"$1:$2"/curvecp -type d -exec chmod 700 {} \; 15 | find /services/urcd-curvecplisten-"$1:$2"/curvecp -type f -exec chmod 600 {} \; 16 | chown urcd /services/urcd-curvecplisten-"$1:$2"/curvecp -R 17 | 18 | printf \ 19 | "#!/bin/sh -e 20 | exec curvecpserver \`cat serv\` curvecp $1 $2 01110101011100100110001101100100 curvecpmessage ./urcstream $3\n" > \ 21 | /services/urcd-curvecplisten-"$1:$2"/run || exit 22 | 23 | chmod +x /services/urcd-curvecplisten-"$1:$2"/run || exit 1 24 | 25 | test -L /services/urcd-curvecplisten-"$1:$2"/urcstream || \ 26 | ln -s `pwd`/urcstream /services/urcd-curvecplisten-"$1:$2"/urcstream || \ 27 | exit 1 28 | 29 | test -L /service/urcd-curvecplisten-"$1:$2" || \ 30 | ln -s /services/urcd-curvecplisten-"$1:$2" \ 31 | /service/urcd-curvecplisten-"$1:$2" || \ 32 | exit 1 33 | 34 | printf \ 35 | "PUBKEY: `curvecpprintkey /services/urcd-curvecplisten-"$1:$2"/curvecp`\n" 36 | -------------------------------------------------------------------------------- /scripts/add-curvecprecv: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-curvecprecv-"$1:$2" || exit 1 7 | 8 | test -L /services/urcd-curvecprecv-"$1:$2"/serv || \ 9 | ln -s `pwd`/env/serv /services/urcd-curvecprecv-"$1:$2"/serv || \ 10 | exit 1 11 | 12 | curvecpmakekey /services/urcd-curvecprecv-"$1:$2"/curvecp || exit 1 13 | 14 | find /services/urcd-curvecprecv-"$1:$2"/curvecp -type d -exec chmod 700 {} \; 15 | find /services/urcd-curvecprecv-"$1:$2"/curvecp -type f -exec chmod 600 {} \; 16 | chown urcd /services/urcd-curvecprecv-"$1:$2"/curvecp -R 17 | 18 | printf \ 19 | "#!/bin/sh -e 20 | exec curvecpserver \`cat serv\` curvecp $1 $2 01110101011100100110001101100100 curvecpmessage ./urcrecv $3\n" > \ 21 | /services/urcd-curvecprecv-"$1:$2"/run || exit 22 | 23 | chmod +x /services/urcd-curvecprecv-"$1:$2"/run || exit 1 24 | 25 | test -L /services/urcd-curvecprecv-"$1:$2"/urcrecv || \ 26 | ln -s `pwd`/urcrecv /services/urcd-curvecprecv-"$1:$2"/urcrecv || \ 27 | exit 1 28 | 29 | test -L /service/urcd-curvecprecv-"$1:$2" || \ 30 | ln -s /services/urcd-curvecprecv-"$1:$2" \ 31 | /service/urcd-curvecprecv-"$1:$2" || \ 32 | exit 1 33 | 34 | printf \ 35 | "PUBKEY: `curvecpprintkey /services/urcd-curvecprecv-"$1:$2"/curvecp`\n" 36 | -------------------------------------------------------------------------------- /scripts/add-curvecpsend: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $5 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-curvecpsend-"$1:$2" || exit 1 7 | 8 | printf $4 > /services/urcd-curvecpsend-"$1:$2"/serv || exit 1 9 | 10 | printf $5 > /services/urcd-curvecpsend-"$1:$2"/pubkey || exit 1 11 | 12 | printf \ 13 | "#!/bin/sh -e 14 | export TCPCLIENT=1 15 | exec curvecpclient \`cat serv\` \`cat pubkey\` $1 $2 01110101011100100110001101100100 curvecpmessage -c ./urcsend $3\n" > \ 16 | /services/urcd-curvecpsend-"$1:$2"/run || exit 17 | 18 | chmod +x /services/urcd-curvecpsend-"$1:$2"/run || exit 1 19 | 20 | test -L /services/urcd-curvecpsend-"$1:$2"/urcsend || \ 21 | ln -s `pwd`/urcsend /services/urcd-curvecpsend-"$1:$2"/urcsend || \ 22 | exit 1 23 | 24 | test -L /service/urcd-curvecpsend-"$1:$2" || \ 25 | ln -s /services/urcd-curvecpsend-"$1:$2" \ 26 | /service/urcd-curvecpsend-"$1:$2" || \ 27 | exit 1 28 | -------------------------------------------------------------------------------- /scripts/add-hubconnect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-hubconnect-"$1:$2" || exit 1 7 | 8 | printf '#!/bin/sh -e\n' > \ 9 | /services/urcd-hubconnect-"$1:$2"/run || exit 1 10 | 11 | printf 'export TCPCLIENT=1\n' >> \ 12 | /services/urcd-hubconnect-"$1:$2"/run || exit 1 13 | 14 | printf "exec tcpclient -H -R $1 $2 ./urchubstream $3\n" >> \ 15 | /services/urcd-hubconnect-"$1:$2"/run || exit 1 16 | 17 | chmod +x /services/urcd-hubconnect-"$1:$2"/run || exit 1 18 | 19 | test -L /services/urcd-hubconnect-"$1:$2"/urchubstream || \ 20 | ln -s `pwd`/urchubstream /services/urcd-hubconnect-"$1:$2"/urchubstream || \ 21 | exit 1 22 | 23 | test -L /service/urcd-hubconnect-"$1:$2" || \ 24 | ln -s /services/urcd-hubconnect-"$1:$2" \ 25 | /service/urcd-hubconnect-"$1:$2" || \ 26 | exit 1 27 | -------------------------------------------------------------------------------- /scripts/add-hublisten: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-hublisten-"$1:$2" || exit 1 7 | 8 | printf '#!/bin/sh -e\n' > \ 9 | /services/urcd-hublisten-"$1:$2"/run || exit 1 10 | 11 | printf "exec tcpserver -H -R $1 $2 ./urchubstream $3\n" >> \ 12 | /services/urcd-hublisten-"$1:$2"/run || exit 1 13 | 14 | chmod +x /services/urcd-hublisten-"$1:$2"/run || exit 1 15 | 16 | test -L /services/urcd-hublisten-"$1:$2"/urchubstream || \ 17 | ln -s `pwd`/urchubstream /services/urcd-hublisten-"$1:$2"/urchubstream || \ 18 | exit 1 19 | 20 | test -L /service/urcd-hublisten-"$1:$2" || \ 21 | ln -s /services/urcd-hublisten-"$1:$2" \ 22 | /service/urcd-hublisten-"$1:$2" || \ 23 | exit 1 24 | -------------------------------------------------------------------------------- /scripts/add-tcpconnect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-tcpconnect-"$1:$2" || exit 1 7 | 8 | printf '#!/bin/sh -e\n' > \ 9 | /services/urcd-tcpconnect-"$1:$2"/run || exit 1 10 | 11 | printf 'export TCPCLIENT=1\n' >> \ 12 | /services/urcd-tcpconnect-"$1:$2"/run || exit 1 13 | 14 | printf "exec tcpclient -H -R $1 $2 ./urcstream $3\n" >> \ 15 | /services/urcd-tcpconnect-"$1:$2"/run || exit 1 16 | 17 | chmod +x /services/urcd-tcpconnect-"$1:$2"/run || exit 1 18 | 19 | test -L /services/urcd-tcpconnect-"$1:$2"/urcstream || \ 20 | ln -s `pwd`/urcstream /services/urcd-tcpconnect-"$1:$2"/urcstream || \ 21 | exit 1 22 | 23 | test -L /service/urcd-tcpconnect-"$1:$2" || \ 24 | ln -s /services/urcd-tcpconnect-"$1:$2" \ 25 | /service/urcd-tcpconnect-"$1:$2" || \ 26 | exit 1 27 | -------------------------------------------------------------------------------- /scripts/add-tcplisten: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-tcplisten-"$1:$2" || exit 1 7 | 8 | printf '#!/bin/sh -e\n' > \ 9 | /services/urcd-tcplisten-"$1:$2"/run || exit 1 10 | 11 | printf "exec tcpserver -H -R $1 $2 ./urcstream $3\n" >> \ 12 | /services/urcd-tcplisten-"$1:$2"/run || exit 1 13 | 14 | chmod +x /services/urcd-tcplisten-"$1:$2"/run || exit 1 15 | 16 | test -L /services/urcd-tcplisten-"$1:$2"/urcstream || \ 17 | ln -s `pwd`/urcstream /services/urcd-tcplisten-"$1:$2"/urcstream || \ 18 | exit 1 19 | 20 | test -L /service/urcd-tcplisten-"$1:$2" || \ 21 | ln -s /services/urcd-tcplisten-"$1:$2" \ 22 | /service/urcd-tcplisten-"$1:$2" || \ 23 | exit 1 24 | -------------------------------------------------------------------------------- /scripts/add-tcprecv: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-tcprecv-"$1:$2" || exit 1 7 | 8 | printf '#!/bin/sh -e\n' > \ 9 | /services/urcd-tcprecv-"$1:$2"/run || exit 1 10 | 11 | printf "exec tcpserver -H -R $1 $2 ./urcrecv $3\n" >> \ 12 | /services/urcd-tcprecv-"$1:$2"/run || exit 1 13 | 14 | chmod +x /services/urcd-tcprecv-"$1:$2"/run || exit 1 15 | 16 | test -L /services/urcd-tcprecv-"$1:$2"/urcrecv || \ 17 | ln -s `pwd`/urcrecv /services/urcd-tcprecv-"$1:$2"/urcrecv || \ 18 | exit 1 19 | 20 | test -L /service/urcd-tcprecv-"$1:$2" || \ 21 | ln -s /services/urcd-tcprecv-"$1:$2" \ 22 | /service/urcd-tcprecv-"$1:$2" || \ 23 | exit 1 24 | -------------------------------------------------------------------------------- /scripts/add-tcpsend: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-tcpsend-"$1:$2" || exit 1 7 | 8 | printf '#!/bin/sh -e\n' > \ 9 | /services/urcd-tcpsend-"$1:$2"/run || exit 1 10 | 11 | printf "exec tcpclient -H -R $1 $2 ./urcsend $3\n" >> \ 12 | /services/urcd-tcpsend-"$1:$2"/run || exit 1 13 | 14 | chmod +x /services/urcd-tcpsend-"$1:$2"/run || exit 1 15 | 16 | test -L /services/urcd-tcpsend-"$1:$2"/urcsend || \ 17 | ln -s `pwd`/urcsend /services/urcd-tcpsend-"$1:$2"/urcsend || \ 18 | exit 1 19 | 20 | test -L /service/urcd-tcpsend-"$1:$2" || \ 21 | ln -s /services/urcd-tcpsend-"$1:$2" \ 22 | /service/urcd-tcpsend-"$1:$2" || \ 23 | exit 1 24 | -------------------------------------------------------------------------------- /scripts/add-torconnect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-torconnect-"$1:$2" || exit 1 7 | 8 | test -L /services/urcd-torconnect-"$1:$2"/ucspi-socks4aclient || \ 9 | ln -s `pwd`/ucspi-socks4aclient /services/urcd-torconnect-"$1:$2"/ucspi-socks4aclient || exit 1 10 | 11 | printf '#!/bin/sh -e\n' > \ 12 | /services/urcd-torconnect-"$1:$2"/run || exit 1 13 | 14 | printf 'export TCPCLIENT=1\n' >> \ 15 | /services/urcd-torconnect-"$1:$2"/run || exit 1 16 | 17 | printf "exec tcpclient -H -R 127.0.0.1 9050 ./ucspi-socks4aclient $1 $2 ./urcstream $3\n" >> \ 18 | /services/urcd-torconnect-"$1:$2"/run || exit 1 19 | 20 | chmod +x /services/urcd-torconnect-"$1:$2"/run || exit 1 21 | 22 | test -L /services/urcd-torconnect-"$1:$2"/urcstream || \ 23 | ln -s `pwd`/urcstream /services/urcd-torconnect-"$1:$2"/urcstream || \ 24 | exit 1 25 | 26 | test -L /service/urcd-torconnect-"$1:$2" || \ 27 | ln -s /services/urcd-torconnect-"$1:$2" \ 28 | /service/urcd-torconnect-"$1:$2" || \ 29 | exit 1 30 | -------------------------------------------------------------------------------- /scripts/add-torhubconnect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-torhubconnect-"$1:$2" || exit 1 7 | 8 | 9 | test -L /services/urcd-torhubconnect-"$1:$2"/ucspi-socks4aclient || \ 10 | ln -s `pwd`/ucspi-socks4aclient /services/urcd-torhubconnect-"$1:$2"/ucspi-socks4aclient || exit 1 11 | 12 | printf '#!/bin/sh -e\n' > \ 13 | /services/urcd-torhubconnect-"$1:$2"/run || exit 1 14 | 15 | printf 'export TCPCLIENT=1\n' >> \ 16 | /services/urcd-torhubconnect-"$1:$2"/run || exit 1 17 | 18 | printf "exec tcpclient -H -R 127.0.0.1 9050 ./ucspi-socks4aclient $1 $2 ./urchubstream $3\n" >> \ 19 | /services/urcd-torhubconnect-"$1:$2"/run || exit 1 20 | 21 | chmod +x /services/urcd-torhubconnect-"$1:$2"/run || exit 1 22 | 23 | test -L /services/urcd-torhubconnect-"$1:$2"/urchubstream || \ 24 | ln -s `pwd`/urchubstream /services/urcd-torhubconnect-"$1:$2"/urchubstream || \ 25 | exit 1 26 | 27 | test -L /service/urcd-torhubconnect-"$1:$2" || \ 28 | ln -s /services/urcd-torhubconnect-"$1:$2" \ 29 | /service/urcd-torhubconnect-"$1:$2" || \ 30 | exit 1 31 | -------------------------------------------------------------------------------- /scripts/add-torsend: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-torsend-"$1:$2" || exit 1 7 | 8 | test -L /services/urcd-torsend-"$1:$2"/ucspi-socks4aclient || \ 9 | ln -s `pwd`/ucspi-socks4aclient /services/urcd-torsend-"$1:$2"/ucspi-socks4aclient || exit 1 10 | 11 | printf '#!/bin/sh -e\n' > \ 12 | /services/urcd-torsend-"$1:$2"/run || exit 1 13 | 14 | printf "exec tcpclient -H -R 127.0.0.1 9050 ./ucspi-socks4aclient $1 $2 ./urcsend $3\n" >> \ 15 | /services/urcd-torsend-"$1:$2"/run || exit 1 16 | 17 | chmod +x /services/urcd-torsend-"$1:$2"/run || exit 1 18 | 19 | test -L /services/urcd-torsend-"$1:$2"/urcsend || \ 20 | ln -s `pwd`/urcsend /services/urcd-torsend-"$1:$2"/urcsend || \ 21 | exit 1 22 | 23 | test -L /service/urcd-torsend-"$1:$2" || \ 24 | ln -s /services/urcd-torsend-"$1:$2" \ 25 | /service/urcd-torsend-"$1:$2" || \ 26 | exit 1 27 | -------------------------------------------------------------------------------- /scripts/add-udprecv: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-udprecv-"$1:$2" || exit 1 7 | 8 | printf '#!/bin/sh -e\n' > \ 9 | /services/urcd-udprecv-"$1:$2"/run || exit 1 10 | 11 | printf "exec ./urc-udprecv $1 $2 $3\n" >> \ 12 | /services/urcd-udprecv-"$1:$2"/run || exit 1 13 | 14 | chmod +x /services/urcd-udprecv-"$1:$2"/run || exit 1 15 | 16 | test -L /services/urcd-udprecv-"$1:$2"/urc-udprecv || \ 17 | ln -s `pwd`/urc-udprecv /services/urcd-udprecv-"$1:$2"/urc-udprecv || \ 18 | exit 1 19 | 20 | test -L /service/urcd-udprecv-"$1:$2" || \ 21 | ln -s /services/urcd-udprecv-"$1:$2" \ 22 | /service/urcd-udprecv-"$1:$2" || \ 23 | exit 1 24 | -------------------------------------------------------------------------------- /scripts/add-udpsend: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z $3 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | mkdir -p /services/urcd-udpsend-"$1:$2" || exit 1 7 | 8 | printf '#!/bin/sh -e\n' > \ 9 | /services/urcd-udpsend-"$1:$2"/run || exit 1 10 | 11 | printf "exec ./urc-udpsend $1 $2 $3\n" >> \ 12 | /services/urcd-udpsend-"$1:$2"/run || exit 1 13 | 14 | chmod +x /services/urcd-udpsend-"$1:$2"/run || exit 1 15 | 16 | test -L /services/urcd-udpsend-"$1:$2"/urc-udpsend || \ 17 | ln -s `pwd`/urc-udpsend /services/urcd-udpsend-"$1:$2"/urc-udpsend || \ 18 | exit 1 19 | 20 | test -L /service/urcd-udpsend-"$1:$2" || \ 21 | ln -s /services/urcd-udpsend-"$1:$2" \ 22 | /service/urcd-udpsend-"$1:$2" || \ 23 | exit 1 24 | -------------------------------------------------------------------------------- /scripts/add-urchub: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | n=`ls /services/ | grep urcd-hub | wc -l | sed 's/ //g'` 4 | mkdir -p /services/urcd-hub$n 5 | mkdir -p /services/urcd-hub$n/socket/ 6 | 7 | chown urcd /services/urcd-hub$n/socket/ 8 | 9 | echo '#!/bin/sh -e' > /services/urcd-hub$n/run 10 | echo 'ulimit -s 8192' >> /services/urcd-hub$n/run 11 | echo 'exec ./urchub ./urccache `pwd`/socket/' >> /services/urcd-hub$n/run 12 | chmod +x /services/urcd-hub$n/run 13 | 14 | test -L /services/urcd-hub$n/urchub || ln -s `pwd`/urchub /services/urcd-hub$n/urchub 15 | test -L /services/urcd-hub$n/urccache || ln -s `pwd`/urccache /services/urcd-hub$n/urccache 16 | test -L /service/urcd-hub$n || ln -s /services/urcd-hub$n /service/urcd-hub$n 17 | 18 | sleep 4 19 | svstat /service/urcd-hub$n 20 | -------------------------------------------------------------------------------- /scripts/add-urcstream2hub: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | [ -z $2 ] && \ 3 | echo $0' ' 1>&2 && \ 4 | exit 64 5 | 6 | n=`ls /services | grep urcd-stream2hub | wc -l` 7 | 8 | mkdir -p /services/urcd-stream2hub$n 9 | mkdir -p /services/urcd-stream2hub$n/env 10 | 11 | echo '0.0' > /services/urcd-stream2hub$n/env/LIMIT 12 | 13 | echo '#!/bin/sh -e' > /services/urcd-stream2hub$n/run 14 | echo "exec ./urcstream2hub $2 ./urcstream $1" >> /services/urcd-stream2hub$n/run 15 | chmod +x /services/urcd-stream2hub$n/run 16 | 17 | test -L /services/urcd-stream2hub$n/urcstream || \ 18 | ln -s `pwd`/urcstream /services/urcd-stream2hub$n/urcstream 19 | 20 | test -L /services/urcd-stream2hub$n/urcstream2hub || \ 21 | ln -s `pwd`/urcstream2hub /services/urcd-stream2hub$n/urcstream2hub 22 | 23 | test -L /service/urcd-stream2hub$n || \ 24 | ln -s /services/urcd-stream2hub$n /service/urcd-stream2hub$n 25 | 26 | sleep 4 27 | svstat /service/urcd-stream2hub$n 28 | -------------------------------------------------------------------------------- /scripts/scrubsocketdir: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ -z "$1" ] || ! [ -e "$1" ]; then 3 | echo $0': ' 4 | exit 64 5 | fi 6 | for i in `ls "$1"`; do 7 | [ "$i" == "hub" ] && continue 8 | [ -e "/proc/$i/" ] || setuidgid urcd rm "$1/$i" 9 | done 10 | -------------------------------------------------------------------------------- /scripts/urcd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $(id -u) != 0 ]; then 4 | echo 'fatal error: root privileges required' 1>&2 5 | exit 1 6 | fi 7 | 8 | path="`pwd`/socket/" 9 | mkdir -p "$path" 10 | chown urcd "$path" 11 | 12 | if ! pidof urchub 1>/dev/null ; then 13 | ./urchub ./urccache "$path" & 14 | fi 15 | 16 | if ! pidof urchubstream 1>/dev/null ; then 17 | addr=(db/urchub/tor/*) 18 | addr="${addr[RANDOM % ${#addr[@]}]}" 19 | port=`cat $addr/port` 20 | addr=`basename $addr` 21 | tcpclient -H -R 127.0.0.1 9050 ./ucspi-socks4aclient $addr $port ./urchubstream "$path" 22 | fi 23 | 24 | exec tcpserver -H -R -l `cat env/addr` `cat env/addr` `cat env/port` ./urcd `cat env/path` 25 | -------------------------------------------------------------------------------- /src/base16.h: -------------------------------------------------------------------------------- 1 | int base16_encode(unsigned char *a, unsigned char *b, int blen) 2 | { 3 | 4 | int i = 0; 5 | int alen = 0; 6 | 7 | for(i=0;i> 4; 11 | if (a[alen] < 10) a[alen] += 48; else a[alen] += 87; 12 | ++alen; 13 | 14 | a[alen] = b[i] % 16; 15 | if (a[alen] < 10) a[alen] += 48; else a[alen] += 87; 16 | ++alen; 17 | 18 | } 19 | 20 | return alen; 21 | 22 | } 23 | 24 | int base16_decode(unsigned char *b, unsigned char *a, int alen) 25 | { 26 | 27 | int i = 0; 28 | int blen = 0; 29 | 30 | for(i=0;i 47) && (a[i]<58)) b[blen] = a[i] - 48 << 4; 34 | else if ((a[i] > 96) && (a[i] < 103)) b[blen] = a[i] - 87 << 4; 35 | else if ((a[i] > 64) && (a[i] < 71)) b[blen] = a[i] - 55 << 4; 36 | else return blen; 37 | if (++i == alen) return blen; 38 | 39 | if ((a[i] > 47) && (a[i]<58)) b[blen] += a[i] - 48; 40 | else if ((a[i] > 96) && (a[i] < 103)) b[blen] += a[i] - 87; 41 | else if ((a[i] > 64) && (a[i] < 71)) b[blen] += a[i] - 55; 42 | else return blen; 43 | ++blen; 44 | 45 | } 46 | 47 | return blen; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/check-nacl.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /src/check-sodium.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /src/check-taia.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "tai_dec.h" 9 | #include "tai_inc.h" 10 | 11 | main() 12 | { 13 | 14 | unsigned char slow[16] = {0}; 15 | unsigned char norm[16] = {0}; 16 | unsigned char fast[16] = {0}; 17 | 18 | taia_now(norm); 19 | 20 | taia_pack(norm,norm); 21 | 22 | memcpy(slow,norm,16); 23 | memcpy(fast,norm,16); 24 | 25 | tai_dec(slow,slow,"\0\0\0\0\0\0\0\x80"); 26 | tai_inc(fast,fast,"\0\0\0\0\0\0\0\x80"); 27 | 28 | write(1,slow,16); 29 | write(1,norm,16); 30 | write(1,fast,16); 31 | 32 | int i; 33 | 34 | for (i=0;i<16;++i) 35 | { 36 | if (slow[i] < norm[i]) break; 37 | if (slow[i] > norm[i]) exit(1); 38 | } if (!crypto_verify_16(slow,norm)) exit(2); 39 | 40 | for (i=0;i<16;++i) 41 | { 42 | if (norm[i] < fast[i]) exit(0); 43 | if (norm[i] > fast[i]) exit(3); 44 | } if (!crypto_verify_16(norm,fast)) exit(4); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/cryptoserv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "base16.h" 21 | 22 | #define USAGE "./cryptoserv /path/to/sockets/ /path/to/root/\n" 23 | 24 | #ifndef UNIX_PATH_MAX 25 | #ifdef __NetBSD__ 26 | #define UNIX_PATH_MAX 104 27 | #else 28 | #define UNIX_PATH_MAX 108 29 | #endif 30 | #endif 31 | 32 | int itoa(char *s, int n, int slen) 33 | { 34 | if (snprintf(s,slen,"%d",n)<0) return -1; 35 | return 0; 36 | } 37 | 38 | void randombytes(char *bytes) {} // override: hack crypto_*_keypair functions 39 | 40 | void lower( 41 | unsigned char *buffer0, 42 | unsigned char *buffer1, 43 | int buffer1_len 44 | ) { 45 | int i; 46 | for(i=0;i64)&&(buffer1[i]<91)) { 48 | buffer0[i] = buffer1[i] + 32; 49 | } 50 | else buffer0[i] = buffer1[i]; 51 | } 52 | } 53 | 54 | main(int argc, char *argv[]) 55 | { 56 | 57 | if (argc<3) { 58 | write(2,USAGE,strlen(USAGE)); 59 | exit(1); 60 | } 61 | 62 | struct passwd *urcd = getpwnam("urcd"); 63 | struct sockaddr_un s; 64 | struct dirent *file; 65 | struct stat stats; 66 | 67 | DIR *directory; 68 | 69 | unsigned char buffer3[1024*2] = {0}; 70 | unsigned char buffer2[1024*2] = {0}; 71 | unsigned char buffer1[1024*2] = {0}; 72 | unsigned char buffer0[1024*2] = {0}; 73 | unsigned char identifiednick[256]; 74 | unsigned char path[512]; 75 | unsigned char hex[192]; 76 | unsigned char pk0[32]; 77 | unsigned char pk1[32]; 78 | unsigned char sk[64]; 79 | 80 | float LIMIT; 81 | 82 | long logintime; 83 | long starttime; 84 | long EXPIRY; 85 | 86 | int identifiednicklen; 87 | int loginattempts = 0; 88 | int identified = 0; 89 | int oldnicklen = 0; 90 | int informed = 0; 91 | int nicklen = 0; 92 | int identval=0; 93 | int sfd = -1; 94 | int NICKLEN; 95 | int fd; 96 | int i; 97 | 98 | fd = open("env/LIMIT",0); 99 | if (fd>0) 100 | { 101 | if (read(fd,buffer0,1024)>0) LIMIT = atof(buffer0); 102 | else LIMIT = 1.0; 103 | } else LIMIT = 1.0; 104 | close(fd); 105 | 106 | bzero(buffer0,1024); 107 | 108 | fd = open("env/EXPIRY",0); 109 | if (fd>0) 110 | { 111 | if (read(fd,buffer0,1024)>0) EXPIRY = atol(buffer0) * 24L * 60L * 60L; 112 | else EXPIRY = 32L * 24L * 60L * 60L; 113 | } else EXPIRY = 32L * 24L * 60L * 60L; 114 | close(fd); 115 | 116 | fd = open("env/NICKLEN",0); 117 | if (fd>0) 118 | { 119 | if (read(fd,buffer0,1024)>0) NICKLEN = atoi(buffer0) & 255; 120 | else NICKLEN = 32; 121 | } else NICKLEN = 32; 122 | close(fd); 123 | 124 | bzero(&s,sizeof(s)); 125 | s.sun_family = AF_UNIX; 126 | 127 | if ((i=strlen(argv[1])) > UNIX_PATH_MAX) exit(2); 128 | memcpy(s.sun_path,argv[1],i); 129 | 130 | if (((sfd=socket(AF_UNIX,SOCK_DGRAM,0))<0) 131 | || (itoa(s.sun_path+i,getppid(),UNIX_PATH_MAX-i)<0) 132 | || (connect(sfd,(struct sockaddr *)&s,sizeof(s))<0) 133 | || (setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i))<0)) 134 | { 135 | write(2,USAGE,strlen(USAGE)); 136 | exit(3); 137 | } 138 | 139 | if ((!urcd) 140 | || (chdir(argv[2])) 141 | || (chroot(argv[2])) 142 | || (setgroups(0,'\x00')) 143 | || (setgid(urcd->pw_gid)) 144 | || (setuid(urcd->pw_uid))) 145 | { 146 | write(2,USAGE,strlen(USAGE)); 147 | exit(4); 148 | } 149 | 150 | starttime = time((long *)0); 151 | logintime = starttime; 152 | 153 | fcntl(0,F_SETFL,fcntl(0,F_GETFL,0)&~O_NONBLOCK); 154 | 155 | memcpy(buffer2+2+12+4+8,":CryptoServ!URCD@service NOTICE ",32); 156 | 157 | if (EXPIRY) { 158 | memcpy(path,"urcsigndb/",10); 159 | if (!(directory=opendir("urcsigndb/"))) exit(5); 160 | while ((file=readdir(directory))) 161 | { 162 | if (file->d_name[0] == '.') continue; 163 | bzero(path+10,-10+512); 164 | memcpy(path+10,file->d_name,strlen(file->d_name)); 165 | stat(path,(struct stat *)&stats); 166 | if (time((long *)0) - stats.st_atime >= EXPIRY) remove(path); 167 | } closedir(directory); 168 | 169 | memcpy(path,"urccryptoboxdir/",16); 170 | if (!(directory=opendir("urccryptoboxdir/"))) exit(6); 171 | while ((file=readdir(directory))) 172 | { 173 | if (file->d_name[0] == '.') continue; 174 | bzero(path+16,-16+512); 175 | memcpy(path+16,file->d_name,strlen(file->d_name)); 176 | stat(path,(struct stat *)&stats); 177 | if (time((long *)0) - stats.st_atime >= EXPIRY) remove(path); 178 | } closedir(directory); 179 | /* 180 | memcpy(path,"urccryptoboxpfs/",16); 181 | if (!(directory=opendir("urccryptoboxpfs/"))) exit(6); 182 | while ((file=readdir(directory))) 183 | { 184 | if (file->d_name[0] == '.') continue; 185 | bzero(path+16,-16+512); 186 | memcpy(path+16,file->d_name,strlen(file->d_name)); 187 | stat(path,(struct stat *)&stats); 188 | if (time((long *)0) - stats.st_atime >= EXPIRY) remove(path); 189 | } closedir(directory);*/ 190 | } 191 | 192 | while (1) 193 | { 194 | 195 | for (i=0;i<1024;++i) 196 | { 197 | if (read(0,buffer0+i,1)<1) exit(7); 198 | if (buffer0[i] == '\r') --i; 199 | if (buffer0[i] == '\n') break; 200 | } if (buffer0[i] != '\n') continue; 201 | ++i; 202 | 203 | lower(buffer1,buffer0,i); 204 | 205 | if ((loginattempts)&&(time((long *)0)-logintime>256)) { 206 | logintime = time((long *)0); 207 | --loginattempts; 208 | } 209 | 210 | /// NICK 211 | if ((i>=7)&&(!memcmp("nick ",buffer1,5))) { /* not reliable */ 212 | nicklen=-5+i-1; 213 | for (;nicklen>0;--nicklen) { 214 | if ((buffer1[5+nicklen] == '.') || (buffer1[5+nicklen] == '/')) { 215 | nicklen=oldnicklen; 216 | goto client_write; 217 | } 218 | } 219 | nicklen=-5+i-1; 220 | if (nicklen<=NICKLEN) { 221 | memcpy(buffer2+2+12+4+8+32,buffer1+5,nicklen); 222 | memcpy(buffer2+2+12+4+8+32+nicklen," :",2); 223 | oldnicklen = nicklen; 224 | } 225 | else nicklen = 0; 226 | } else if (nicklen) { 227 | if ((i>=20)&&(!memcmp("privmsg cryptoserv :",buffer1,20))) { 228 | 229 | usleep((int)(LIMIT*1000000)); 230 | 231 | /// IDENTIFY 232 | if ((i>=20+5+1+1)&&(!memcmp("ident",buffer1+20,5))) { 233 | if ((i>=20+9+1+1)&&(!memcmp("identify ",buffer1+20,9))) identval=192; 234 | if ((i>=20+9+1+1)&&(!memcmp("identsig ",buffer1+20,9))) identval=128; 235 | if ((i>=20+9+1+1)&&(!memcmp("identenc ",buffer1+20,9))) identval=64; 236 | // if ((i>=20+9+1+1)&&(!memcmp("identoff ",buffer1+20,9))) identval=0;//dunno how to do this yet. 237 | if (identval == 0) continue; 238 | 239 | if (loginattempts == 4) goto invalid_passwd; 240 | ++loginattempts; 241 | bzero(path,512); 242 | memcpy(path,"urcsigndb/",10); 243 | memcpy(path+10,buffer2+2+12+4+8+32,nicklen); 244 | if (((fd=open(path,O_RDONLY))<0) || (read(fd,hex,64)<64) || (base16_decode(pk0,hex,64)<32)) { 245 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Account does not exist.\n",24); 246 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+24); 247 | close(fd); 248 | continue; 249 | }close(fd); 250 | memcpy(buffer3,buffer0+20+9,-20-9+i-1); 251 | memcpy(buffer3-20-9+i-1,buffer2+2+12+4+8+32,nicklen); 252 | crypto_hash_sha512(sk,buffer3,-20-9+i-1+nicklen); 253 | crypto_sign_keypair(pk1,sk); 254 | if (memcmp(pk0,pk1,32)) { 255 | invalid_passwd: 256 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Invalid passwd.\n",16); 257 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+16); 258 | continue; 259 | } 260 | bzero(path,512); 261 | memcpy(path,"urccryptoboxdir/",16); 262 | memcpy(path+16,buffer2+2+12+4+8+32,nicklen); 263 | if (((fd=open(path,O_RDONLY))<0) || (read(fd,hex,64)<64) || (base16_decode(pk0,hex,64)<32)) { 264 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Account does not exist.\n",24); 265 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+24); 266 | close(fd); 267 | continue; 268 | }close(fd); 269 | crypto_scalarmult_curve25519_base(pk1,sk); 270 | if (memcmp(pk0,pk1,32)) { 271 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Invalid passwd.\n",16); 272 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+16); 273 | continue; 274 | } 275 | base16_encode(hex,sk,32); 276 | base16_encode(hex+64,sk,64); 277 | memcpy(buffer0,"PASS ",5); 278 | memcpy(buffer0+5,hex+((identval==128)?64:0),identval); 279 | memcpy(buffer0+5+identval,"\n",1); 280 | if (write(1,buffer0,5+identval+1)<=0) exit(8); 281 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Success\n",8); 282 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 283 | memcpy(identifiednick,buffer2+2+12+4+8+32,nicklen); 284 | identifiednicklen = nicklen; 285 | loginattempts = 0; 286 | identified = 1; 287 | continue; 288 | } 289 | 290 | /// REGISTER 291 | if ((i>=20+9+1+1)&&(!memcmp("register ",buffer1+20,9))) { 292 | if ((identified) || (time((long *)0)-starttime<128)) goto HELP; 293 | memcpy(buffer3,buffer0+20+9,-20-9+i-1); 294 | memcpy(buffer3-20-9+i-1,buffer2+2+12+4+8+32,nicklen); 295 | crypto_hash_sha512(sk,buffer3,-20-9+i-1+nicklen); 296 | REGISTER: 297 | crypto_sign_keypair(pk0,sk); 298 | bzero(path,512); 299 | memcpy(path,"urcsigndb/",10); 300 | if (identified) memcpy(path+10,identifiednick,identifiednicklen); 301 | else memcpy(path+10,buffer2+2+12+4+8+32,nicklen); 302 | if ((!access(path,F_OK))&&(!identified)) { 303 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Account already exists.\n",24); 304 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+24); 305 | continue; 306 | } 307 | if (((fd=open(path,O_CREAT|O_WRONLY))<0) || (fchmod(fd,S_IRUSR|S_IWUSR))<0) { 308 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Failure\n",8); 309 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 310 | close(fd); 311 | continue; 312 | } 313 | base16_encode(hex,pk0,32); 314 | if (write(fd,hex,64)<64) exit(9); 315 | close(fd); 316 | crypto_scalarmult_curve25519_base(pk0,sk); 317 | bzero(path,512); 318 | memcpy(path,"urccryptoboxdir/",16); 319 | if (identified) memcpy(path+16,identifiednick,identifiednicklen); 320 | else memcpy(path+16,buffer2+2+12+4+8+32,nicklen); 321 | if (((fd=open(path,O_CREAT|O_WRONLY))<0) || (fchmod(fd,S_IRUSR|S_IWUSR))<0) { 322 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Failure\n",8); 323 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 324 | close(fd); 325 | continue; 326 | } 327 | base16_encode(hex,pk0,32); 328 | if (write(fd,hex,64)<64) exit(10); 329 | close(fd); 330 | base16_encode(hex,sk,32); 331 | base16_encode(hex+64,sk,64); 332 | memcpy(buffer0,"PASS ",5); 333 | memcpy(buffer0+5,hex,192); 334 | memcpy(buffer0+5+192,"\n",1); 335 | if (write(1,buffer0,5+192+1)<=0) exit(11); 336 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Success\n",8); 337 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 338 | if (!identified) { 339 | memcpy(identifiednick,buffer2+2+12+4+8+32,nicklen); 340 | identifiednicklen = nicklen; 341 | identified = 1; 342 | } 343 | continue; 344 | } 345 | 346 | /// SET PASSWORD 347 | if ((i>=20+13+1+1)&&(!memcmp("set password ",buffer1+20,13))) { 348 | if (!identified) goto HELP; 349 | memcpy(buffer3,buffer0+20+13,-20-13+i-1); 350 | memcpy(buffer3-20-13+i-1,identifiednick,identifiednicklen); 351 | crypto_hash_sha512(sk,buffer3,-20-13+i-1+identifiednicklen); 352 | goto REGISTER; 353 | } 354 | 355 | /// SET PFS 356 | if ((i>=20+8+2+1)&&(!memcmp("set pfs ",buffer1+20,8))) { 357 | if (!identified) { 358 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"You are not identified.\n",24); 359 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+24); 360 | continue; 361 | } 362 | bzero(path,512); 363 | memcpy(path,"urccryptoboxpfs/",16); 364 | memcpy(path+16,identifiednick,identifiednicklen); 365 | if ((i>=20+8+3+1)&&(!memcmp("off",buffer1+20+8,3))) { 366 | if (remove(path)<0) { 367 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Failure\n",8); 368 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 369 | continue; 370 | } 371 | } else if ((i>=20+8+2+1)&&(!memcmp("on",buffer1+20+8,2))) { 372 | if ((fd=open(path,O_CREAT))<0) { 373 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Failure\n",8); 374 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 375 | close(fd); 376 | continue; 377 | }close(fd); 378 | } else { 379 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Invalid option.\n",16); 380 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+16); 381 | continue; 382 | } 383 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Success\n",8); 384 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 385 | continue; 386 | } 387 | 388 | /// DROP 389 | if ((i>=20+4)&&(!memcmp("drop",buffer1+20,4))) { 390 | if (!identified) goto HELP; 391 | bzero(path,512); 392 | memcpy(path,"urccryptoboxdir/",16); 393 | memcpy(path+16,identifiednick,identifiednicklen); 394 | if (remove(path)<0) { 395 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Failure\n",8); 396 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 397 | } 398 | bzero(path,512); 399 | memcpy(path,"urcsigndb/",10); 400 | memcpy(path+10,identifiednick,identifiednicklen); 401 | if (remove(path)<0) { 402 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Failure\n",8); 403 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 404 | continue; 405 | } 406 | memcpy(buffer0,"PASS ",5); 407 | memcpy(buffer0+5+192,"\n",1); 408 | for (i=0;i<192;++i) buffer0[5+i]='0'; 409 | if (write(1,buffer0,5+192+1)<=0) exit(12); 410 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Success\n",8); 411 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 412 | starttime = time((long *)0); 413 | identified = 0; 414 | continue; 415 | } 416 | 417 | /// LOGOUT 418 | if ((i>=20+6)&&(!memcmp("logout",buffer1+20,6))) { 419 | if (!identified) { 420 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"You are not identified.\n",24); 421 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+24); 422 | continue; 423 | } 424 | memcpy(buffer0,"PASS ",5); 425 | memcpy(buffer0+5+192,"\n",1); 426 | for (i=0;i<192;++i) buffer0[5+i]='0'; 427 | if (write(1,buffer0,5+192+1)<=0) exit(13); 428 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"Success\n",8); 429 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+8); 430 | starttime = time((long *)0); 431 | identified = 0; 432 | continue; 433 | } 434 | 435 | /// HELP 436 | if ((i>=20+4)&&(!memcmp("help",buffer1+20,4))) { 437 | HELP: 438 | informed = 1; 439 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"The following commands will most likely take effect when you and/or your peers /reconnect:\n",91); 440 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+91); 441 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"`REGISTER ' after 128 seconds to create an account.\n",60); 442 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+60); 443 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"`IDENTIFY ' to login to your account and activate URCSIGN and URCCRYPTOBOX.\n",84); 444 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+84); 445 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"`IDENTENC ' to login to your account and activate URCCRYPTOBOX.\n",72); 446 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+72); 447 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"`IDENTSIG ' to login to your account and activate URCSIGN.\n",67); 448 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+67); 449 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"`SET PASSWORD ' changes your password after you REGISTER/IDENTIFY.\n",75); 450 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+75); 451 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"`SET PFS ' toggles perfect forward secrecy for PM after /reconnect\n",76); 452 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+76); 453 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"`DROP' removes your account after you REGISTER/IDENTIFY.\n",57); 454 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+57); 455 | memcpy(buffer2+2+12+4+8+32+nicklen+2,"`LOGOUT' deactivates URCSIGN and URCCRYPTOBOX.\n",47); 456 | write(sfd,buffer2,2+12+4+8+32+nicklen+2+47); 457 | } 458 | 459 | if (!informed) goto HELP; 460 | continue; 461 | } 462 | } 463 | client_write: 464 | if (write(1,buffer0,i)<=0) exit(14); 465 | if ((i>=4)&&(!memcmp("quit",buffer1,4))) { 466 | write(1,"",0); // send EOF 467 | exit(15); 468 | } 469 | } 470 | } 471 | -------------------------------------------------------------------------------- /src/dprintf.h: -------------------------------------------------------------------------------- 1 | /* NetBSD workaround: (thanks epoch) */ 2 | #ifdef HAVE_NBTOOL_CONFIG_H 3 | #include "nbtool_config.h" 4 | #endif 5 | 6 | #if !HAVE_DPRINTF 7 | #include 8 | #ifndef HAVE_NBTOOL_CONFIG_H 9 | #include 10 | #include 11 | #include 12 | #endif 13 | 14 | int dprintf(int fd, const char *format, ...) { 15 | FILE *f; 16 | int d; 17 | va_list ap; 18 | if ((d=dup(fd))==-1) return -1; 19 | if ((f=fdopen(d,"r+"))==NULL) { 20 | close(d); 21 | return -1; 22 | } 23 | va_start(ap,format); 24 | d=vfprintf(f,format,ap); 25 | va_end(ap); 26 | fclose(f); 27 | return d; 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/keypair.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | unsigned char pk [32]; 6 | unsigned char sk [32]; 7 | int i ; 8 | 9 | crypto_box_keypair(pk,sk); 10 | 11 | printf("PUBKEY: "); 12 | for (i=0;i<32;++i) printf("%02x",pk[i]); 13 | printf("\n"); 14 | 15 | printf("SECKEY: "); 16 | for (i=0;i<32;++i) printf("%02x",sk[i]); 17 | printf("\n");} 18 | /* 19 | void randombytes(char *bytes) { 20 | read(0,bytes,32);}*/ 21 | -------------------------------------------------------------------------------- /src/liburc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "liburc.h" 4 | 5 | /* security: enforce compatibility and santize malicious configurations */ 6 | #if crypto_sign_SECRETKEYBYTES != 64 7 | exit(255); 8 | #endif 9 | #if crypto_sign_PUBLICKEYBYTES != 32 10 | exit(255); 11 | #endif 12 | #if crypto_sign_BYTES != 64 13 | exit(255); 14 | #endif 15 | 16 | #define URC_MTU 1024 17 | #define IRC_MTU 512 18 | 19 | /* ImportError: workaround dummy init function (initliburc) */ 20 | PyObject *pyliburc(PyObject *self) { return Py_BuildValue("i", 0); } 21 | 22 | PyObject *pyurc_jail(PyObject *self, PyObject *args, PyObject *kw) { 23 | char *path; 24 | Py_ssize_t pathsize = 0; 25 | static const char *kwlist[] = {"path",0}; 26 | if (!PyArg_ParseTupleAndKeywords( 27 | args, 28 | kw, 29 | "|s#:urc_jail", 30 | (char **)kwlist, 31 | &path, 32 | &pathsize 33 | )) return Py_BuildValue("i", -1); 34 | return Py_BuildValue("i", urc_jail(path)); 35 | } 36 | 37 | PyObject *pyrandombytes(PyObject *self, PyObject *args, PyObject *kw){ 38 | PyObject *bytes; 39 | unsigned char *b; 40 | Py_ssize_t n = 0; 41 | static const char *kwlist[] = {"n",0}; 42 | if (!PyArg_ParseTupleAndKeywords(args, kw, 43 | #if PY_VERSION_HEX < 0x02050000 44 | "|i:randombytes", 45 | #else 46 | "|n:randombytes", 47 | #endif 48 | (char **)kwlist, 49 | &n 50 | )) 51 | return PyBytes_FromStringAndSize("", 0); 52 | b = PyMem_Malloc(n); 53 | if (!b) return PyBytes_FromStringAndSize("", 0); 54 | randombytes(b,n); 55 | bytes = PyBytes_FromStringAndSize((char *)b, n); 56 | PyMem_Free(b); 57 | return bytes; 58 | } 59 | 60 | PyObject *pyurchub_fmt(PyObject *self, PyObject *args, PyObject *kw) { 61 | unsigned char p[1024*2]; 62 | char *b; 63 | Py_ssize_t psize = 0; 64 | Py_ssize_t bsize = 0; 65 | static const char *kwlist[] = {"b",0}; 66 | if (!PyArg_ParseTupleAndKeywords( 67 | args, 68 | kw, 69 | "|s#:urchub_fmt", 70 | (char **)kwlist, 71 | &b, 72 | &bsize 73 | )) return Py_BuildValue("i", -1); 74 | if (bsize > IRC_MTU) return Py_BuildValue("i", -1); 75 | if (urchub_fmt(p,&psize,b,bsize) == -1) return Py_BuildValue("i", -1); 76 | return PyBytes_FromStringAndSize((char *)p, psize); 77 | } 78 | 79 | PyObject *pyurcsign_fmt(PyObject *self, PyObject *args, PyObject *kw) { 80 | unsigned char p[1024*2]; 81 | char *b; 82 | char *sk; 83 | Py_ssize_t psize = 0; 84 | Py_ssize_t bsize = 0; 85 | Py_ssize_t sksize = 0; 86 | static const char *kwlist[] = {"b","sk",0}; 87 | if (!PyArg_ParseTupleAndKeywords( 88 | args, 89 | kw, 90 | "|s#s#:urcsign_fmt", 91 | (char **)kwlist, 92 | &b, 93 | &bsize, 94 | &sk, 95 | &sksize 96 | )) return Py_BuildValue("i", -1); 97 | if (sksize != 64) return Py_BuildValue("i", -1); 98 | if (bsize > IRC_MTU) return Py_BuildValue("i", -1); 99 | if (urcsign_fmt(p,&psize,b,bsize,sk) == -1) return Py_BuildValue("i", -1); 100 | return PyBytes_FromStringAndSize((char *)p, psize); 101 | } 102 | 103 | PyObject *pyurcsign_verify(PyObject *self, PyObject *args, PyObject *kw) { 104 | unsigned char *p; 105 | unsigned char *pk; 106 | Py_ssize_t psize = 0; 107 | Py_ssize_t pksize = 0; 108 | static const char *kwlist[] = {"p", "pk", 0}; 109 | if (!PyArg_ParseTupleAndKeywords( 110 | args, 111 | kw, 112 | "|s#s#:urcsign_verify", 113 | (char **)kwlist, 114 | &p, 115 | &psize, 116 | &pk, 117 | &pksize 118 | )) return Py_BuildValue("i", -1); 119 | if (pksize != 32) return Py_BuildValue("i", -1); 120 | if (urcsign_verify(p,psize,pk) == -1) return Py_BuildValue("i", -1); 121 | return Py_BuildValue("i", 0); 122 | } 123 | 124 | PyObject *pyurcsecretbox_fmt(PyObject *self, PyObject *args, PyObject *kw) { 125 | unsigned char p[1024*2]; 126 | char *b; 127 | char *sk; 128 | Py_ssize_t psize = 0; 129 | Py_ssize_t bsize = 0; 130 | Py_ssize_t sksize = 0; 131 | static const char *kwlist[] = {"b","sk",0}; 132 | if (!PyArg_ParseTupleAndKeywords( 133 | args, 134 | kw, 135 | "|s#s#:urcsecretbox_fmt", 136 | (char **)kwlist, 137 | &b, 138 | &bsize, 139 | &sk, 140 | &sksize 141 | )) return Py_BuildValue("i", -1); 142 | if (sksize != 32) return Py_BuildValue("i", -1); 143 | if (bsize > IRC_MTU) return Py_BuildValue("i", -1); 144 | if (urcsecretbox_fmt(p,&psize,b,bsize,sk) == -1) return Py_BuildValue("i", -1); 145 | return PyBytes_FromStringAndSize((char *)p, psize); 146 | } 147 | 148 | PyObject *pyurcsecretbox_open(PyObject *self, PyObject *args, PyObject *kw) { 149 | unsigned char b[1024*2]; 150 | char *p; 151 | char *sk; 152 | Py_ssize_t bsize = 0; 153 | Py_ssize_t psize = 0; 154 | Py_ssize_t sksize = 0; 155 | static const char *kwlist[] = {"p","sk",0}; 156 | if (!PyArg_ParseTupleAndKeywords( 157 | args, 158 | kw, 159 | "|s#s#:urcsecretbox_open", 160 | (char **)kwlist, 161 | &p, 162 | &psize, 163 | &sk, 164 | &sksize 165 | )) return Py_BuildValue("i", -1); 166 | if (sksize != 32) return Py_BuildValue("i", -1); 167 | if (psize > URC_MTU) return Py_BuildValue("i", -1); 168 | if (urcsecretbox_open(b,&bsize,p,psize,sk) == -1) return Py_BuildValue("i", -1); 169 | return PyBytes_FromStringAndSize((char *)b, bsize); 170 | } 171 | 172 | PyObject *pyurcsignsecretbox_fmt(PyObject *self, PyObject *args, PyObject *kw) { 173 | unsigned char p[1024*2]; 174 | char *b; 175 | char *ssk; 176 | char *csk; 177 | Py_ssize_t psize = 0; 178 | Py_ssize_t bsize = 0; 179 | Py_ssize_t ssksize = 0; 180 | Py_ssize_t csksize = 0; 181 | static const char *kwlist[] = {"b","ssk","csk",0}; 182 | if (!PyArg_ParseTupleAndKeywords( 183 | args, 184 | kw, 185 | "|s#s#s#:urcsignsecretbox_fmt", 186 | (char **)kwlist, 187 | &b, 188 | &bsize, 189 | &ssk, 190 | &ssksize, 191 | &csk, 192 | &csksize 193 | )) return Py_BuildValue("i", -1); 194 | if (ssksize != 64) return Py_BuildValue("i", -1); 195 | if (csksize != 32) return Py_BuildValue("i", -1); 196 | if (bsize > IRC_MTU) return Py_BuildValue("i", -1); 197 | if (urcsignsecretbox_fmt(p,&psize,b,bsize,ssk,csk) == -1) return Py_BuildValue("i", -1); 198 | return PyBytes_FromStringAndSize((char *)p, psize); 199 | } 200 | 201 | PyObject *pyurcsignsecretbox_open(PyObject *self, PyObject *args, PyObject *kw) { 202 | unsigned char b[1024*2]; 203 | char *p; 204 | char *csk; 205 | Py_ssize_t bsize = 0; 206 | Py_ssize_t psize = 0; 207 | Py_ssize_t csksize = 0; 208 | static const char *kwlist[] = {"p","csk",0}; 209 | if (!PyArg_ParseTupleAndKeywords( 210 | args, 211 | kw, 212 | "|s#s#:urcsignsecretbox_open", 213 | (char **)kwlist, 214 | &p, 215 | &psize, 216 | &csk, 217 | &csksize 218 | )) return Py_BuildValue("i", -1); 219 | if (csksize != 32) return Py_BuildValue("i", -1); 220 | if (psize > URC_MTU) return Py_BuildValue("i", -1); 221 | if (urcsignsecretbox_open(b,&bsize,p,psize,csk) == -1) return Py_BuildValue("i", -1); 222 | return PyBytes_FromStringAndSize((char *)b, bsize); 223 | } 224 | 225 | PyObject *pyurcsignsecretbox_verify(PyObject *self, PyObject *args, PyObject *kw) { 226 | unsigned char *p; 227 | unsigned char *pk; 228 | Py_ssize_t psize = 0; 229 | Py_ssize_t pksize = 0; 230 | static const char *kwlist[] = {"p", "pk", 0}; 231 | if (!PyArg_ParseTupleAndKeywords( 232 | args, 233 | kw, 234 | "|s#s#:urcsignsecretbox_verify", 235 | (char **)kwlist, 236 | &p, 237 | &psize, 238 | &pk, 239 | &pksize 240 | )) return Py_BuildValue("i", -1); 241 | if (pksize != 32) return Py_BuildValue("i", -1); 242 | if (urcsignsecretbox_verify(p,psize,pk) == -1) return Py_BuildValue("i", -1); 243 | return Py_BuildValue("i", 0); 244 | } 245 | 246 | PyObject *pyurccryptobox_fmt(PyObject *self, PyObject *args, PyObject *kw) { 247 | unsigned char p[1024*2]; 248 | char *b; 249 | char *pk; 250 | char *sk; 251 | Py_ssize_t psize = 0; 252 | Py_ssize_t bsize = 0; 253 | Py_ssize_t pksize = 0; 254 | Py_ssize_t sksize = 0; 255 | static const char *kwlist[] = {"b","pk","sk",0}; 256 | if (!PyArg_ParseTupleAndKeywords( 257 | args, 258 | kw, 259 | "|s#s#s#:urccryptobox_fmt", 260 | (char **)kwlist, 261 | &b, 262 | &bsize, 263 | &pk, 264 | &pksize, 265 | &sk, 266 | &sksize 267 | )) return Py_BuildValue("i", -1); 268 | if (pksize != 32) return Py_BuildValue("i", -1); 269 | if (sksize != 32) return Py_BuildValue("i", -1); 270 | if (bsize > IRC_MTU) return Py_BuildValue("i", -1); 271 | if (urccryptobox_fmt(p,&psize,b,bsize,pk,sk) == -1) return Py_BuildValue("i", -1); 272 | return PyBytes_FromStringAndSize((char *)p, psize); 273 | } 274 | 275 | PyObject *pyurccryptobox_open(PyObject *self, PyObject *args, PyObject *kw) { 276 | unsigned char b[1024*2]; 277 | char *p; 278 | char *pk; 279 | char *sk; 280 | Py_ssize_t bsize = 0; 281 | Py_ssize_t psize = 0; 282 | Py_ssize_t pksize = 0; 283 | Py_ssize_t sksize = 0; 284 | static const char *kwlist[] = {"p","pk","sk",0}; 285 | if (!PyArg_ParseTupleAndKeywords( 286 | args, 287 | kw, 288 | "|s#s#s#:urccryptobox_open", 289 | (char **)kwlist, 290 | &p, 291 | &psize, 292 | &pk, 293 | &pksize, 294 | &sk, 295 | &sksize 296 | )) return Py_BuildValue("i", -1); 297 | if (pksize != 32) return Py_BuildValue("i", -1); 298 | if (sksize != 32) return Py_BuildValue("i", -1); 299 | if (psize > URC_MTU) return Py_BuildValue("i", -1); 300 | if (urccryptobox_open(b,&bsize,p,psize,pk,sk) == -1) return Py_BuildValue("i", -1); 301 | return PyBytes_FromStringAndSize((char *)b, bsize); 302 | } 303 | 304 | PyObject *pyurccryptoboxpfs_fmt(PyObject *self, PyObject *args, PyObject *kw) { 305 | unsigned char p[1024*2]; 306 | char *b; 307 | char *pk0; 308 | char *sk0; 309 | char *pk1; 310 | char *sk1; 311 | Py_ssize_t psize = 0; 312 | Py_ssize_t bsize = 0; 313 | Py_ssize_t pk0size = 0; 314 | Py_ssize_t sk0size = 0; 315 | Py_ssize_t pk1size = 0; 316 | Py_ssize_t sk1size = 0; 317 | static const char *kwlist[] = {"b","pk0","sk0","pk1","sk1",0}; 318 | if (!PyArg_ParseTupleAndKeywords( 319 | args, 320 | kw, 321 | "|s#s#s#s#s#:urccryptoboxpfs_fmt", 322 | (char **)kwlist, 323 | &b, 324 | &bsize, 325 | &pk0, 326 | &pk0size, 327 | &sk0, 328 | &sk0size, 329 | &pk1, 330 | &pk1size, 331 | &sk1, 332 | &sk1size 333 | )) return Py_BuildValue("i", -1); 334 | if (pk0size != 32) return Py_BuildValue("i", -1); 335 | if (sk0size != 32) return Py_BuildValue("i", -1); 336 | if (pk1size != 32) return Py_BuildValue("i", -1); 337 | if (sk1size != 32) return Py_BuildValue("i", -1); 338 | if (bsize > IRC_MTU) return Py_BuildValue("i", -1); 339 | if (urccryptoboxpfs_fmt(p,&psize,b,bsize,pk0,sk0,pk1,sk1) == -1) return Py_BuildValue("i", -1); 340 | return PyBytes_FromStringAndSize((char *)p, psize); 341 | } 342 | 343 | PyObject *pyurccryptoboxpfs_open(PyObject *self, PyObject *args, PyObject *kw) { 344 | unsigned char b[1024*2]; 345 | unsigned char pk0[32]; 346 | unsigned char zk[32]; 347 | char *p; 348 | char *sk0; 349 | char *pk1; 350 | char *sk1; 351 | Py_ssize_t bsize = 0; 352 | Py_ssize_t psize = 0; 353 | Py_ssize_t sk0size = 0; 354 | Py_ssize_t pk1size = 0; 355 | Py_ssize_t sk1size = 0; 356 | static const char *kwlist[] = {"p","sk0","pk1","sk1",0}; 357 | if (!PyArg_ParseTupleAndKeywords( 358 | args, 359 | kw, 360 | "|s#s#s#s#:urccryptoboxpfs_open", 361 | (char **)kwlist, 362 | &p, 363 | &psize, 364 | &sk0, 365 | &sk0size, 366 | &pk1, 367 | &pk1size, 368 | &sk1, 369 | &sk1size 370 | )) return Py_BuildValue("i", -1); 371 | if (sk0size != 32) return Py_BuildValue("i", -1); 372 | if (pk1size != 32) return Py_BuildValue("i", -1); 373 | if (sk1size != 32) return Py_BuildValue("i", -1); 374 | if (psize > URC_MTU) return Py_BuildValue("i", -1); 375 | if (urccryptoboxpfs_open(b,&bsize,p,psize,pk0,sk0,pk1,sk1) == -1) { 376 | bzero(zk,32); 377 | if (crypto_verify_32(pk0,zk)) return Py_BuildValue("OO", 378 | PyBytes_FromStringAndSize((char *)pk0, 32), 379 | Py_BuildValue("i", -1) 380 | ); 381 | return Py_BuildValue("OO", 382 | Py_BuildValue("i", -1), 383 | Py_BuildValue("i", -1) 384 | ); 385 | } 386 | return Py_BuildValue("OO", 387 | PyBytes_FromStringAndSize((char *)pk0, 32), 388 | PyBytes_FromStringAndSize((char *)b, bsize) 389 | ); 390 | } 391 | 392 | static PyMethodDef Module_methods[] = { 393 | { "liburc", pyliburc, METH_NOARGS }, 394 | { "urc_jail", pyurc_jail, METH_VARARGS|METH_KEYWORDS}, 395 | { "randombytes", pyrandombytes, METH_VARARGS|METH_KEYWORDS}, 396 | { "urchub_fmt", pyurchub_fmt, METH_VARARGS|METH_KEYWORDS}, 397 | { "urcsign_fmt", pyurcsign_fmt, METH_VARARGS|METH_KEYWORDS}, 398 | { "urcsign_verify", pyurcsign_verify, METH_VARARGS|METH_KEYWORDS}, 399 | { "urcsecretbox_fmt", pyurcsecretbox_fmt, METH_VARARGS|METH_KEYWORDS}, 400 | { "urcsecretbox_open", pyurcsecretbox_open, METH_VARARGS|METH_KEYWORDS}, 401 | { "urcsignsecretbox_fmt", pyurcsignsecretbox_fmt, METH_VARARGS|METH_KEYWORDS}, 402 | { "urcsignsecretbox_open", pyurcsignsecretbox_open, METH_VARARGS|METH_KEYWORDS}, 403 | { "urcsignsecretbox_verify", pyurcsignsecretbox_verify, METH_VARARGS|METH_KEYWORDS}, 404 | { "urccryptobox_fmt", pyurccryptobox_fmt, METH_VARARGS|METH_KEYWORDS}, 405 | { "urccryptobox_open", pyurccryptobox_open, METH_VARARGS|METH_KEYWORDS}, 406 | { "urccryptoboxpfs_fmt", pyurccryptoboxpfs_fmt, METH_VARARGS|METH_KEYWORDS}, 407 | { "urccryptoboxpfs_open", pyurccryptoboxpfs_open, METH_VARARGS|METH_KEYWORDS}, 408 | { NULL, NULL} 409 | }; 410 | 411 | void initliburc(){ (void) Py_InitModule("liburc", Module_methods); } 412 | void initurc_jail(){ (void) Py_InitModule("urc_jail", Module_methods); } 413 | void initrandombytes(){ (void) Py_InitModule("randombytes", Module_methods); } 414 | void initurchub_fmt(){ (void) Py_InitModule("urchub_fmt", Module_methods); } 415 | void initurcsign_fmt(){ (void) Py_InitModule("urcsign_fmt", Module_methods); } 416 | void initurcsign_verify(){ (void) Py_InitModule("urcsign_verify", Module_methods); } 417 | void initurcsecretbox_fmt(){ (void) Py_InitModule("urcsecretbox_fmt", Module_methods); } 418 | void initurcsecretbox_open(){ (void) Py_InitModule("urcsecretbox_open", Module_methods); } 419 | void initurccryptobox_fmt(){ (void) Py_InitModule("urccryptobox_fmt", Module_methods); } 420 | void initurccryptobox_open(){ (void) Py_InitModule("urccryptobox_open", Module_methods); } 421 | void initurcsignsecretbox_fmt(){ (void) Py_InitModule("urcsignsecretbox_fmt", Module_methods); } 422 | void initurcsignsecretbox_open(){ (void) Py_InitModule("urcsignsecretbox_open", Module_methods); } 423 | void initurccryptoboxpfs_fmt(){ (void) Py_InitModule("urccryptoboxpfs_fmt", Module_methods); } 424 | void initurccryptoboxpfs_open(){ (void) Py_InitModule("urccryptoboxpfs_open", Module_methods); } 425 | -------------------------------------------------------------------------------- /src/liburc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* security: enforce compatibility and santize malicious configurations */ 18 | #if crypto_secretbox_BOXZEROBYTES != 16 19 | exit(255); 20 | #endif 21 | #if crypto_secretbox_ZEROBYTES != 32 22 | exit(255); 23 | #endif 24 | #if crypto_sign_BYTES != 64 25 | exit(255); 26 | #endif 27 | 28 | #define URC_MTU 1024 29 | #define IRC_MTU 512 30 | 31 | int devurandomfd = -1; 32 | int procstatusfd = -1; 33 | 34 | int urc_jail(char *path) { 35 | if (procstatusfd == -1) procstatusfd = open("/proc/self/status",O_RDONLY); 36 | if (devurandomfd == -1) devurandomfd = open("/dev/arandom",O_RDONLY); 37 | if (devurandomfd == -1) devurandomfd = open("/dev/urandom",O_RDONLY); 38 | struct passwd *urcd = getpwnam("urcd"); 39 | if ((!urcd) 40 | || (chdir(path)) 41 | || (chroot(path)) 42 | || (setgroups(0,'\x00')) 43 | || (setgid(urcd->pw_gid)) 44 | || (setuid(urcd->pw_uid))) 45 | return -1; 46 | return 0; 47 | } 48 | 49 | void randombytes(unsigned char *d, int dlen) { 50 | unsigned char *b = malloc(64 * sizeof(unsigned char)); 51 | static unsigned char buff[1024]; 52 | static unsigned char a[64]; 53 | unsigned char c[64]; 54 | static struct timeval now; 55 | static int i; 56 | if (procstatusfd == -1) procstatusfd = open("/proc/self/status",O_RDONLY); 57 | if (devurandomfd == -1) devurandomfd = open("/dev/arandom",O_RDONLY); 58 | if (devurandomfd == -1) devurandomfd = open("/dev/urandom",O_RDONLY); 59 | if ((devurandomfd == -1) || (read(devurandomfd,a,64) != 64)) { 60 | if (procstatusfd != -1) { 61 | lseek(procstatusfd,0,SEEK_SET); 62 | if (read(procstatusfd,buff,1024) > 0) crypto_hash_sha512(a,buff,1024); 63 | } 64 | for (i=0;i<64;++i) { 65 | gettimeofday(&now,'\x00'); srand(now.tv_usec); a[i]^= (rand() & 255); 66 | if (b) a[i] ^= b[i]; 67 | a[i] ^= c[i]; 68 | } 69 | } 70 | crypto_hash_sha512(c,a,64); 71 | crypto_stream(d,dlen,c,c+24); 72 | if (b) free(b); 73 | } 74 | 75 | int setlen(unsigned char *b, int blen) { 76 | if (blen > URC_MTU) return -1; 77 | b[0] = blen / 256; 78 | b[1] = blen % 256; 79 | return 0; 80 | } 81 | 82 | void taia96n(unsigned char *ts) { 83 | static const long long offset[] = { 84 | -8LL, -7LL, -6LL, -5LL, -4LL, -3LL, -2LL, -1LL, 85 | 8LL, 7LL, 6LL, 5LL, 4LL, 3LL, 2LL, 1LL 86 | }; 87 | static unsigned long long a; 88 | static unsigned char b[1+4]; 89 | randombytes(b,1+4); 90 | tai_now(ts); 91 | a=0ULL; 92 | memcpy(&a,ts,8); 93 | a+=offset[b[0] & 15]; 94 | memcpy(ts,&a,8); 95 | tai_pack(ts,ts); 96 | memcpy(ts+8,b+1,4); 97 | } 98 | 99 | int urchub_fmt(unsigned char *p, int *plen, unsigned char *b, int blen) { 100 | if (blen > IRC_MTU) return -1; 101 | if (setlen(p,blen) == -1) return -1; 102 | taia96n(p+2); 103 | p[14]=0; 104 | p[15]=0; 105 | p[16]=0; 106 | p[17]=0; 107 | randombytes(p+2+12+4,8); 108 | memmove(p+2+12+4+8,b,blen); 109 | *plen=2+12+4+8+blen; 110 | return 0; 111 | } 112 | 113 | int urcsign_fmt(unsigned char *p, int *plen, unsigned char *b, int blen, unsigned char *sk) { 114 | static unsigned long long smlen; 115 | static unsigned char sm[1024*2]; 116 | if (blen > IRC_MTU) return -1; 117 | if (setlen(p,blen+64) == -1) return -1; 118 | taia96n(p+2); 119 | p[14]=1; 120 | p[15]=0; 121 | p[16]=0; 122 | p[17]=0; 123 | randombytes(p+2+12+4,8); 124 | memmove(p+2+12+4+8,b,blen); 125 | if (crypto_sign_edwards25519sha512batch(sm,&smlen,p,(unsigned long long)(2+12+4+8+blen),sk) == -1) return -1; 126 | memmove(p+2+12+4+8+blen,sm,32); 127 | memmove(p+2+12+4+8+blen+32,sm+smlen-32,32); 128 | *plen=2+12+4+8+blen+64; 129 | return 0; 130 | } 131 | 132 | int urcsign_verify(unsigned char *p, int plen, unsigned char *pk) { 133 | static unsigned char sm[1024*2]; 134 | static unsigned char m[1024*2]; 135 | static unsigned long long mlen; 136 | if (p[14] != 1) return -1; 137 | if (plen > URC_MTU) return -1; 138 | memmove(sm,p+plen-64,32); 139 | memmove(sm+32,p,plen-64); 140 | memmove(sm+32+plen-64,p+plen-32,32); 141 | return crypto_sign_edwards25519sha512batch_open(m,&mlen,(const unsigned char *)sm,(unsigned long long)plen,(const unsigned char *)pk); 142 | } 143 | 144 | int urcsecretbox_fmt(unsigned char *p, int *plen, unsigned char *b, int blen, unsigned char *sk) { 145 | static unsigned char m[1024*2]; 146 | static unsigned char c[1024*2]; 147 | static int zlen; 148 | if (blen > IRC_MTU) return -1; 149 | zlen = blen + (256 - blen % 256); 150 | bzero(m,32+zlen); /* http://nacl.cr.yp.to/secretbox.html */ 151 | bzero(c,16); 152 | if (setlen(p,zlen+16) == -1) return -1; 153 | taia96n(p+2); 154 | p[14]=2; 155 | p[15]=0; 156 | p[16]=0; 157 | p[17]=0; 158 | randombytes(p+2+12+4,8); 159 | memmove(m+32,b,blen); 160 | if (crypto_secretbox(c,m,32+zlen,(const unsigned char *)p+2,(const unsigned char *)sk) == -1) return -1; 161 | memmove(p+2+12+4+8,c+16,zlen+16); 162 | *plen=2+12+4+8+zlen+16; 163 | return 0; 164 | } 165 | 166 | int urcsecretbox_open(unsigned char *b, int *blen, unsigned char *p, int plen, unsigned char *sk) { 167 | static unsigned char m[1024*2]; 168 | static unsigned char c[1024*2]; 169 | if (p[14] != 2) return -1; 170 | if (plen > URC_MTU) return -1; 171 | bzero(m,32); /* http://nacl.cr.yp.to/secretbox.html */ 172 | bzero(c,16); 173 | memmove(c+16,p+2+12+4+8,-2-12-4-8+plen); 174 | if (crypto_secretbox_open(m,c,16-2-12-4-8+plen,(const unsigned char *)p+2,(const unsigned char *)sk) == -1) return -1; 175 | memmove(b,m+32,-2-12-4-8+plen-16); 176 | *blen=-2-12-4-8+plen-16; 177 | return 0; 178 | } 179 | 180 | int urcsignsecretbox_fmt(unsigned char *p, int *plen, unsigned char *b, int blen, unsigned char *ssk, unsigned char *csk) { 181 | static unsigned long long smlen; 182 | static unsigned char sm[1024*2]; 183 | static unsigned char m[1024*2]; 184 | static unsigned char c[1024*2]; 185 | static int zlen; 186 | if (blen > IRC_MTU) return -1; 187 | zlen = blen + (256 - blen % 256); 188 | if (setlen(p,zlen+64+16) == -1) return -1; 189 | taia96n(p+2); 190 | p[14]=3; 191 | p[15]=0; 192 | p[16]=0; 193 | p[17]=0; 194 | randombytes(p+2+12+4,8); 195 | memmove(p+2+12+4+8,b,blen); 196 | bzero(p+2+12+4+8+blen,-blen+zlen); 197 | if (crypto_sign(sm,&smlen,p,2+12+4+8+zlen,ssk) == -1) return -1; 198 | memmove(p+2+12+4+8+zlen,sm,32); 199 | memmove(p+2+12+4+8+zlen+32,sm+smlen-32,32); 200 | bzero(m,32); /* http://nacl.cr.yp.to/secretbox.html */ 201 | bzero(c,16); 202 | memmove(m+32,p+2+12+4+8,zlen+64); 203 | if (crypto_secretbox(c,m,32+zlen+64,(const unsigned char *)p+2,(const unsigned char *)csk) == -1) return -1; 204 | memmove(p+2+12+4+8,c+16,zlen+64+16); 205 | *plen=2+12+4+8+zlen+64+16; 206 | return 0; 207 | } 208 | 209 | int urcsignsecretbox_open(unsigned char *b, int *blen, unsigned char *p, int plen, unsigned char *sk) { 210 | static unsigned char m[1024*2]; 211 | static unsigned char c[1024*2]; 212 | if (p[14] != 3) return -1; 213 | if (plen > URC_MTU) return -1; 214 | bzero(m,32); /* http://nacl.cr.yp.to/secretbox.html */ 215 | bzero(c,16); 216 | memmove(c+16,p+2+12+4+8,-2-12-4-8+plen); 217 | if (crypto_secretbox_open(m,c,16-2-12-4-8+plen,(const unsigned char *)p+2,(const unsigned char *)sk) == -1) return -1; 218 | memmove(b,p,2+12+4+8); 219 | memmove(b+2+12+4+8,m+32,-2-12-4-8+plen-16); 220 | *blen=plen-16; 221 | return 0; 222 | } 223 | 224 | int urcsignsecretbox_verify(unsigned char *p, int plen, unsigned char *pk) { 225 | static unsigned long long mlen; 226 | static unsigned char sm[1024*2]; 227 | static unsigned char m[1024*2]; 228 | if (p[14] != 3) return -1; 229 | if (plen > URC_MTU) return -1; 230 | memmove(sm,p+plen-64,32); 231 | memmove(sm+32,p,plen-64); 232 | memmove(sm+32+plen-64,p+plen-32,32); 233 | return crypto_sign_open(m,&mlen,(const unsigned char *)sm,plen,(const unsigned char *)pk); 234 | } 235 | 236 | int urccryptobox_fmt(unsigned char *p, int *plen, unsigned char *b, int blen, unsigned char *pk, unsigned char *sk) { 237 | static unsigned char m[1024*2]; 238 | static unsigned char c[1024*2]; 239 | static int zlen; 240 | if (blen > IRC_MTU) return -1; 241 | zlen = blen + (256 - blen % 256); 242 | bzero(m,32+zlen); /* http://nacl.cr.yp.to/box.html */ 243 | bzero(c,16); 244 | if (setlen(p,zlen+16) == -1) return -1; 245 | taia96n(p+2); 246 | p[14]=4; 247 | p[15]=0; 248 | p[16]=0; 249 | p[17]=0; 250 | randombytes(p+2+12+4,8); 251 | memmove(m+32,b,blen); 252 | if (crypto_box(c,m,32+zlen,(const unsigned char *)p+2,(const unsigned char *)pk,(const unsigned char *)sk) == -1) return -1; 253 | memmove(p+2+12+4+8,c+16,zlen+16); 254 | *plen=2+12+4+8+zlen+16; 255 | return 0; 256 | } 257 | 258 | int urccryptobox_open(unsigned char *b, int *blen, unsigned char *p, int plen, unsigned char *pk, unsigned char *sk) { 259 | static unsigned char m[1024*2]; 260 | static unsigned char c[1024*2]; 261 | if (p[14] != 4) return -1; 262 | if (plen > URC_MTU) return -1; 263 | bzero(m,32); /* http://nacl.cr.yp.to/box.html */ 264 | bzero(c,16); 265 | memmove(c+16,p+2+12+4+8,-2-12-4-8+plen); 266 | if (crypto_box_open(m,c,16-2-12-4-8+plen,(const unsigned char *)p+2,(const unsigned char *)pk,(const unsigned char *)sk) == -1) return -1; 267 | memmove(b,m+32,-2-12-4-8+plen-16); 268 | *blen=-2-12-4-8+plen-16; 269 | return 0; 270 | } 271 | 272 | int urccryptoboxpfs_fmt(unsigned char *p, int *plen, unsigned char *b, int blen, unsigned char *pk0, unsigned char *sk0, unsigned char *pk1, unsigned char *sk1) { 273 | static unsigned char m[1024*2]; 274 | static unsigned char c[1024*2]; 275 | static int zlen; 276 | if (blen > IRC_MTU) return -1; 277 | zlen = blen + (256 - blen % 256); 278 | bzero(m,32+zlen); /* http://nacl.cr.yp.to/box.html */ 279 | bzero(c,16); 280 | if (setlen(p,32+zlen+16+16) == -1) return -1; 281 | taia96n(p+2); 282 | p[14]=5; 283 | p[15]=0; 284 | p[16]=0; 285 | p[17]=0; 286 | randombytes(p+2+12+4,8); 287 | memmove(m+32,b,blen); 288 | if (crypto_box(c,m,32+zlen,(const unsigned char *)p+2,(const unsigned char *)pk0,(const unsigned char *)sk0) == -1) return -1; 289 | crypto_scalarmult_curve25519_base(m+32,sk0); 290 | memmove(m+32+32,c+16,zlen+16); 291 | if (crypto_box(c,m,32+32+zlen+16,(const unsigned char *)p+2,(const unsigned char *)pk1,(const unsigned char *)sk1) == -1) return -1; 292 | memmove(p+2+12+4+8,c+16,32+zlen+16+16); 293 | *plen=2+12+4+8+32+zlen+16+16; 294 | return 0; 295 | } 296 | 297 | int urccryptoboxpfs_open(unsigned char *b, int *blen, unsigned char *p, int plen, unsigned char *pk0, unsigned char *sk0, unsigned char *pk1, unsigned char *sk1) { 298 | static unsigned char m[1024*2]; 299 | static unsigned char c[1024*2]; 300 | bzero(pk0,32); 301 | if (p[14] != 5) return -1; 302 | if (plen > URC_MTU) return -1; 303 | bzero(m,32); /* http://nacl.cr.yp.to/box.html */ 304 | bzero(c,16); 305 | memmove(c+16,p+2+12+4+8,-2-12-4-8+plen); 306 | if (crypto_box_open(m,c,16-2-12-4-8+plen,(const unsigned char *)p+2,(const unsigned char *)pk1,(const unsigned char *)sk1) == -1) return -1; 307 | memmove(pk0,m+32,32); 308 | memmove(c+16,m+32+32,-2-12-4-8-32+plen-16); 309 | if (crypto_box_open(m,c,16-2-12-4-8-32+plen-16,(const unsigned char *)p+2,(const unsigned char *)pk0,(const unsigned char *)sk0) == -1) return -1; 310 | memmove(b,m+32,-2-12-4-8-32+plen-16-16); 311 | *blen=-2-12-4-8-32+plen-16-16; 312 | return 0; 313 | } 314 | -------------------------------------------------------------------------------- /src/nacltaia.c: -------------------------------------------------------------------------------- 1 | /* 2 | this library will eventually be replaced with liburc 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | PyObject *pynacltaia(PyObject *self){ /* hack __init__ */ 14 | return Py_BuildValue("i", 0);} 15 | 16 | PyObject *pytaia_now_pack(PyObject *self){ 17 | PyObject *ret; 18 | unsigned char *tpad; 19 | tpad = PyMem_Malloc(16); 20 | 21 | if (!tpad) 22 | return PyErr_NoMemory(); 23 | 24 | taia_now(tpad); 25 | taia_pack(tpad,tpad); 26 | 27 | ret = PyBytes_FromStringAndSize((char *)tpad,16); 28 | PyMem_Free(tpad); 29 | return ret;} 30 | 31 | PyObject *pytaia_okseconds(PyObject *self, PyObject *args, PyObject *kw){ 32 | unsigned char *t; 33 | Py_ssize_t tsize=0, n=0; 34 | static const char *kwlist[] = {"n","t",0}; 35 | 36 | if (!PyArg_ParseTupleAndKeywords(args, kw, 37 | #if PY_VERSION_HEX < 0x02050000 38 | "|is#:taia_okseconds", 39 | #else 40 | "|ns#:taia_okseconds", 41 | #endif 42 | (char **)kwlist, &n, &t, &tsize)){ 43 | return (PyObject *)0;} 44 | 45 | if (tsize<8) 46 | return Py_BuildValue("i", -1); 47 | 48 | int l = 8, i; 49 | struct timeval now; 50 | gettimeofday(&now,(struct timezone *) 0); 51 | unsigned long long s1 = 4611686018427387914ULL + (unsigned long long) now.tv_sec; 52 | unsigned long long s2 = 0ULL; /* uint64 */ 53 | 54 | for(i=0;i<8;++i) 55 | s2 += (unsigned long long)t[i] << (unsigned long long)(--l << 3); 56 | 57 | if (s1 > s2){ 58 | if ((s1 - s2) > (unsigned long long)n) 59 | return Py_BuildValue("i", 0);} 60 | else { 61 | if ((s2 - s1) > (unsigned long long)n) 62 | return Py_BuildValue("i", 0);} 63 | 64 | return Py_BuildValue("i", 1);} 65 | 66 | PyObject *pytaia_new(PyObject *self, PyObject *args, PyObject *kw){ 67 | unsigned char *t, *u; 68 | Py_ssize_t tsize=0, usize=0; 69 | static const char *kwlist[] = {"t", "u", 0}; 70 | 71 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#:taia_new", (char **)kwlist, &t, &tsize, &u, &usize)){ 72 | return (PyObject *)0;} 73 | 74 | if ((tsize<16)||(usize<16)) 75 | return Py_BuildValue("i", -1); 76 | 77 | int i; 78 | 79 | for(i=0;i<16;++i){ /* simple reverse implementation of taia_less */ 80 | if (t[i]u[i]) 83 | return Py_BuildValue("i", 1);} 84 | 85 | return Py_BuildValue("i", 0);} 86 | 87 | PyObject *pycrypto_box_keypair(PyObject *self){ 88 | PyObject *pypk, *pysk, *pyret; 89 | unsigned char pk[crypto_box_PUBLICKEYBYTES]; 90 | unsigned char sk[crypto_box_SECRETKEYBYTES]; 91 | 92 | crypto_box_keypair(pk, sk); 93 | 94 | pypk = PyBytes_FromStringAndSize((char *)pk, crypto_box_PUBLICKEYBYTES); 95 | 96 | if (!pypk) 97 | return (PyObject *)0; 98 | 99 | pysk = PyBytes_FromStringAndSize((char *)sk, crypto_box_SECRETKEYBYTES); 100 | 101 | if (!pysk){ 102 | Py_DECREF(pypk); 103 | return (PyObject *)0;} 104 | 105 | pyret = PyTuple_New(2); 106 | 107 | if (!pyret){ 108 | Py_DECREF(pypk); 109 | Py_DECREF(pysk); 110 | return (PyObject *)0;} 111 | 112 | PyTuple_SET_ITEM(pyret, 0, pypk); 113 | PyTuple_SET_ITEM(pyret, 1, pysk); 114 | return pyret;} 115 | 116 | PyObject *pycrypto_box_beforenm(PyObject *self, PyObject *args, PyObject *kw){ 117 | PyObject *ret; 118 | char *pk, *sk; 119 | Py_ssize_t pksize=0, sksize=0; 120 | static const char *kwlist[] = {"pk", "sk", 0}; 121 | unsigned char rk[crypto_box_SECRETKEYBYTES]; 122 | 123 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#:crypto_box_beforenm", (char **) kwlist, &pk, &pksize, &sk, &sksize)){ 124 | return (PyObject *)0;} 125 | 126 | if (pksize != crypto_box_PUBLICKEYBYTES) return Py_BuildValue("i", 0); 127 | if (sksize != crypto_box_SECRETKEYBYTES) return Py_BuildValue("i", 0); 128 | if (crypto_box_beforenm(rk,(const unsigned char *) pk,(const unsigned char *) sk)<0) return Py_BuildValue("i", 0); 129 | ret = PyBytes_FromStringAndSize((char *)rk,crypto_box_SECRETKEYBYTES); 130 | return ret;} 131 | 132 | PyObject *pycrypto_box(PyObject *self, PyObject *args, PyObject *kw){ 133 | char *m, *n, *pk, *sk; 134 | Py_ssize_t msize=0, nsize=0, pksize=0, sksize=0; 135 | static const char *kwlist[] = {"m", "n", "pk", "sk", 0}; 136 | unsigned int i; 137 | PyObject *ret; 138 | size_t mlen; 139 | unsigned char *mpad; 140 | unsigned char *cpad; 141 | 142 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#s#s#:crypto_box", (char **) kwlist, &m, &msize, &n, &nsize, &pk, &pksize, &sk, &sksize)){ 143 | return (PyObject *)0;} 144 | 145 | if (nsize != crypto_box_NONCEBYTES) return Py_BuildValue("i", 0); 146 | if (pksize != crypto_box_PUBLICKEYBYTES) return Py_BuildValue("i", 0); 147 | if (sksize != crypto_box_SECRETKEYBYTES) return Py_BuildValue("i", 0); 148 | 149 | mlen = msize + crypto_box_ZEROBYTES; 150 | mpad = PyMem_Malloc(mlen); 151 | 152 | if (!mpad) 153 | return PyErr_NoMemory(); 154 | 155 | cpad = PyMem_Malloc(mlen); 156 | 157 | if (!cpad){ 158 | PyMem_Free(mpad); 159 | return PyErr_NoMemory();} 160 | 161 | for (i = 0;i < crypto_box_ZEROBYTES;++i) mpad[i] = 0; 162 | for (i = crypto_box_ZEROBYTES;i < mlen;++i) mpad[i] = m[i - crypto_box_ZEROBYTES]; 163 | 164 | crypto_box(cpad, mpad, mlen,(const unsigned char *) n,(const unsigned char *) pk,(const unsigned char *) sk); 165 | 166 | ret = PyBytes_FromStringAndSize((char *)cpad + crypto_box_BOXZEROBYTES,mlen - crypto_box_BOXZEROBYTES); 167 | 168 | PyMem_Free(mpad); 169 | PyMem_Free(cpad); 170 | return ret;} 171 | 172 | PyObject *pycrypto_box_open(PyObject *self, PyObject *args, PyObject *kw){ 173 | char *c, *n, *pk, *sk; 174 | Py_ssize_t csize=0, nsize=0, pksize=0, sksize=0; 175 | static const char *kwlist[] = {"c", "n", "pk", "sk", 0}; 176 | unsigned int i; 177 | PyObject *ret; 178 | size_t clen; 179 | unsigned char *mpad; 180 | unsigned char *cpad; 181 | 182 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#s#s#:crypto_box_open", (char **) kwlist, &c, &csize, &n, &nsize, &pk, &pksize, &sk, &sksize)){ 183 | return (PyObject *)0;} 184 | 185 | if (nsize != crypto_box_NONCEBYTES) return Py_BuildValue("i", 0); 186 | if (pksize != crypto_box_PUBLICKEYBYTES) return Py_BuildValue("i", 0); 187 | if (sksize != crypto_box_SECRETKEYBYTES) return Py_BuildValue("i", 0); 188 | 189 | clen = csize + crypto_box_BOXZEROBYTES; 190 | mpad = PyMem_Malloc(clen); 191 | 192 | if (!mpad) 193 | return PyErr_NoMemory(); 194 | 195 | cpad = PyMem_Malloc(clen); 196 | 197 | if (!cpad){ 198 | PyMem_Free(mpad); 199 | return PyErr_NoMemory();} 200 | 201 | for (i = 0;i < crypto_box_BOXZEROBYTES;++i) cpad[i] = 0; 202 | for (i = crypto_box_BOXZEROBYTES;i < clen;++i) cpad[i] = c[i - crypto_box_BOXZEROBYTES]; 203 | 204 | if (crypto_box_open(mpad, cpad, clen, (const unsigned char *) n, (const unsigned char *) pk, (const unsigned char *) sk) != 0){ 205 | PyMem_Free(mpad); 206 | PyMem_Free(cpad); 207 | return Py_BuildValue("i", 0);} 208 | 209 | if (clen < crypto_box_ZEROBYTES){ 210 | PyMem_Free(mpad); 211 | PyMem_Free(cpad); 212 | return Py_BuildValue("i", 0);} 213 | 214 | ret = PyBytes_FromStringAndSize((char *)mpad + crypto_box_ZEROBYTES, clen - crypto_box_ZEROBYTES); 215 | PyMem_Free(mpad); 216 | PyMem_Free(cpad); 217 | return ret;} 218 | 219 | PyObject *pycrypto_secretbox(PyObject *self, PyObject *args, PyObject *kw){ 220 | char *m, *n, *k; 221 | Py_ssize_t msize=0, nsize=0, ksize=0; 222 | static const char *kwlist[] = {"m", "n", "k", 0}; 223 | unsigned int i; 224 | PyObject *ret; 225 | size_t mlen; 226 | unsigned char *mpad; 227 | unsigned char *cpad; 228 | 229 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#s#:crypto_secretbox", (char **) kwlist, &m, &msize, &n, &nsize, &k, &ksize)){ 230 | return (PyObject *)0;} 231 | 232 | if (nsize != crypto_secretbox_NONCEBYTES) return Py_BuildValue("i", 0); 233 | if (ksize != crypto_secretbox_KEYBYTES) return Py_BuildValue("i", 0); 234 | 235 | mlen = msize + crypto_secretbox_ZEROBYTES; 236 | mpad = PyMem_Malloc(mlen); 237 | 238 | if (!mpad) 239 | return PyErr_NoMemory(); 240 | 241 | cpad = PyMem_Malloc(mlen); 242 | 243 | if (!cpad){ 244 | PyMem_Free(mpad); 245 | return PyErr_NoMemory();} 246 | 247 | for (i = 0;i < crypto_secretbox_ZEROBYTES;++i) mpad[i] = 0; 248 | for (i = crypto_secretbox_ZEROBYTES;i < mlen;++i) mpad[i] = m[i - crypto_secretbox_ZEROBYTES]; 249 | 250 | crypto_secretbox(cpad, mpad, mlen, (const unsigned char *) n, (const unsigned char *) k); 251 | 252 | ret = PyBytes_FromStringAndSize((char *)cpad + crypto_secretbox_BOXZEROBYTES, mlen - crypto_secretbox_BOXZEROBYTES); 253 | 254 | PyMem_Free(mpad); 255 | PyMem_Free(cpad); 256 | return ret;} 257 | 258 | PyObject *pycrypto_secretbox_open(PyObject *self, PyObject *args, PyObject *kw){ 259 | char *c, *n, *k; 260 | Py_ssize_t csize=0, nsize=0, ksize=0; 261 | static const char *kwlist[] = {"c", "n", "k", 0}; 262 | unsigned int i; 263 | PyObject *ret; 264 | size_t clen; 265 | unsigned char *mpad; 266 | unsigned char *cpad; 267 | 268 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#s#:crypto_secretbox_open", (char **) kwlist, &c, &csize, &n, &nsize, &k, &ksize)){ 269 | return (PyObject *)0;} 270 | 271 | if (nsize != crypto_secretbox_NONCEBYTES) return Py_BuildValue("i", 0); 272 | if (ksize != crypto_secretbox_KEYBYTES) return Py_BuildValue("i", 0); 273 | 274 | clen = csize + crypto_secretbox_BOXZEROBYTES; 275 | mpad = PyMem_Malloc(clen); 276 | 277 | if (!mpad) 278 | return PyErr_NoMemory(); 279 | 280 | cpad = PyMem_Malloc(clen); 281 | 282 | if (!cpad){ 283 | PyMem_Free(mpad); 284 | return PyErr_NoMemory();} 285 | 286 | for (i = 0;i < crypto_secretbox_BOXZEROBYTES;++i) cpad[i] = 0; 287 | for (i = crypto_secretbox_BOXZEROBYTES;i < clen;++i) cpad[i] = c[i - crypto_secretbox_BOXZEROBYTES]; 288 | 289 | if (crypto_secretbox_open(mpad, cpad, clen, (const unsigned char *) n, (const unsigned char *) k) != 0){ 290 | PyMem_Free(mpad); 291 | PyMem_Free(cpad); 292 | return Py_BuildValue("i", 0);} 293 | 294 | if (clen < crypto_secretbox_ZEROBYTES){ 295 | PyMem_Free(mpad); 296 | PyMem_Free(cpad); 297 | return Py_BuildValue("i", 0);} 298 | 299 | ret = PyBytes_FromStringAndSize((char *)mpad + crypto_secretbox_ZEROBYTES, clen - crypto_secretbox_ZEROBYTES); 300 | PyMem_Free(mpad); 301 | PyMem_Free(cpad); 302 | return ret;} 303 | 304 | PyObject *pycrypto_sign_keypair(PyObject *self){ 305 | PyObject *pypk, *pysk, *pyret; 306 | unsigned char pk[crypto_sign_PUBLICKEYBYTES]; 307 | unsigned char sk[crypto_sign_SECRETKEYBYTES]; 308 | 309 | crypto_sign_keypair(pk, sk); 310 | 311 | pypk = PyBytes_FromStringAndSize((char *)pk, crypto_sign_PUBLICKEYBYTES); 312 | 313 | if (!pypk) 314 | return (PyObject *)0; 315 | 316 | pysk = PyBytes_FromStringAndSize((char *)sk, crypto_sign_SECRETKEYBYTES); 317 | 318 | if (!pysk){ 319 | Py_DECREF(pypk); 320 | return (PyObject *)0;} 321 | 322 | pyret = PyTuple_New(2); 323 | 324 | if (!pyret){ 325 | Py_DECREF(pypk); 326 | Py_DECREF(pysk); 327 | return (PyObject *)0;} 328 | 329 | PyTuple_SET_ITEM(pyret, 0, pypk); 330 | PyTuple_SET_ITEM(pyret, 1, pysk); 331 | return pyret;} 332 | 333 | PyObject *pycrypto_sign(PyObject *self, PyObject *args, PyObject *kw){ 334 | Py_ssize_t m_stringsize=0, sksize=0; 335 | const unsigned char *sk, *m_string; 336 | static const char *kwlist[] = {"m", "sk", 0}; 337 | PyObject *ret; 338 | unsigned long long mlen, smlen; 339 | unsigned char *m; 340 | 341 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#:crypto_sign", (char **) kwlist, (char **)&m_string, &m_stringsize, (char **)&sk, &sksize)){ 342 | return (PyObject *)0;} 343 | 344 | if (sksize != crypto_sign_SECRETKEYBYTES){ 345 | return Py_BuildValue("i", 0);} 346 | 347 | mlen = m_stringsize; 348 | m = PyMem_Malloc(mlen + crypto_sign_BYTES); 349 | 350 | if (!m) 351 | return PyErr_NoMemory(); 352 | 353 | if (crypto_sign(m, &smlen, m_string, mlen, sk) != 0){ 354 | PyMem_Free(m); 355 | return Py_BuildValue("i", 0);} 356 | 357 | ret = PyBytes_FromStringAndSize((char *)m, smlen); 358 | PyMem_Free(m); 359 | return ret;} 360 | 361 | PyObject *pycrypto_sign_open(PyObject *self, PyObject *args, PyObject *kw){ 362 | const unsigned char *sm, *pk; 363 | Py_ssize_t smsize=0, pksize=0; 364 | static const char *kwlist[] = {"sm", "pk", 0}; 365 | PyObject *ret; 366 | unsigned long long smlen, mlen; 367 | unsigned char *m; 368 | 369 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#s#:crypto_sign_open", (char **)kwlist, (char **)&sm, &smsize, (char **)&pk, &pksize)){ 370 | return (PyObject *)0;} 371 | 372 | if (pksize != crypto_sign_PUBLICKEYBYTES){ 373 | return Py_BuildValue("i", 0);} 374 | 375 | smlen = smsize; 376 | m = PyMem_Malloc(smlen); 377 | 378 | if (!m) 379 | return PyErr_NoMemory(); 380 | 381 | if (crypto_sign_open(m, &mlen, sm, smlen, pk) != 0){ 382 | PyMem_Free(m); 383 | return Py_BuildValue("i", 0);} 384 | 385 | ret = PyBytes_FromStringAndSize((char *) m, mlen); 386 | PyMem_Free(m); 387 | return ret;} 388 | 389 | PyObject *pycrypto_hash_sha256(PyObject *self, PyObject *args, PyObject *kw){ 390 | char *m; 391 | Py_ssize_t msize=0; 392 | unsigned char h[crypto_hash_sha256_BYTES]; 393 | static const char *kwlist[] = {"m",0}; 394 | 395 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#:crypto_hash_sha256", (char **)kwlist, &m, &msize)){ 396 | return (PyObject *)0;} 397 | 398 | crypto_hash_sha256(h, (const unsigned char *)m, msize); 399 | 400 | return PyBytes_FromStringAndSize((char *)h, crypto_hash_sha256_BYTES);} 401 | 402 | PyObject *pycrypto_hash_sha512(PyObject *self, PyObject *args, PyObject *kw){ 403 | char *m; 404 | Py_ssize_t msize=0; 405 | unsigned char h[crypto_hash_sha512_BYTES]; 406 | static const char *kwlist[] = {"m",0}; 407 | 408 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#:crypto_hash_sha512", (char **)kwlist, &m, &msize)){ 409 | return (PyObject *)0;} 410 | 411 | crypto_hash_sha512(h, (const unsigned char *)m, msize); 412 | 413 | return PyBytes_FromStringAndSize((char *)h, crypto_hash_sha512_BYTES);} 414 | 415 | static PyMethodDef Module_methods[] = { 416 | {"nacltaia", pynacltaia, METH_NOARGS}, 417 | {"taia_now_pack", pytaia_now_pack, METH_NOARGS}, 418 | {"taia_new", pytaia_new, METH_VARARGS|METH_KEYWORDS}, 419 | {"taia_okseconds", pytaia_okseconds, METH_VARARGS|METH_KEYWORDS}, 420 | {"crypto_box", pycrypto_box, METH_VARARGS|METH_KEYWORDS}, 421 | {"crypto_box_open", pycrypto_box_open, METH_VARARGS|METH_KEYWORDS}, 422 | {"crypto_box_beforenm", pycrypto_box_beforenm, METH_VARARGS|METH_KEYWORDS}, 423 | {"crypto_box_keypair", pycrypto_box_keypair, METH_NOARGS}, 424 | {"crypto_sign", pycrypto_sign, METH_VARARGS|METH_KEYWORDS}, 425 | {"crypto_sign_open", pycrypto_sign_open, METH_VARARGS|METH_KEYWORDS}, 426 | {"crypto_sign_keypair", pycrypto_sign_keypair, METH_NOARGS}, 427 | {"crypto_secretbox", pycrypto_secretbox, METH_VARARGS|METH_KEYWORDS}, 428 | {"crypto_secretbox_open",pycrypto_secretbox_open,METH_VARARGS|METH_KEYWORDS}, 429 | {"crypto_hash_sha256" ,pycrypto_hash_sha256 ,METH_VARARGS|METH_KEYWORDS}, 430 | {"crypto_hash_sha512" ,pycrypto_hash_sha512 ,METH_VARARGS|METH_KEYWORDS}, 431 | {NULL, NULL}}; 432 | 433 | void initnacltaia(){ 434 | (void) Py_InitModule("nacltaia", Module_methods);} 435 | 436 | void inittaia_now_pack(){ 437 | (void) Py_InitModule("taia_now_pack", Module_methods);} 438 | 439 | void inittaia_new(){ 440 | (void) Py_InitModule("taia_new", Module_methods);} 441 | 442 | void inittaia_okseconds(){ 443 | (void) Py_InitModule("taia_okseconds", Module_methods);} 444 | 445 | void initcrypto_box(){ 446 | (void) Py_InitModule("crypto_box", Module_methods);} 447 | 448 | void initcrypto_box_open(){ 449 | (void) Py_InitModule("crypto_box_open", Module_methods);} 450 | 451 | void initcrypto_box_beforenm(){ 452 | (void) Py_InitModule("crypto_box_beforenm", Module_methods);} 453 | 454 | void initcrypto_box_keypair(){ 455 | (void) Py_InitModule("crypto_box_keypair", Module_methods);} 456 | 457 | void initcrypto_sign(){ 458 | (void) Py_InitModule("crypto_sign", Module_methods);} 459 | 460 | void initcrypto_sign_open(){ 461 | (void) Py_InitModule("crypto_sign_open", Module_methods);} 462 | 463 | void initcrypto_sign_keypair(){ 464 | (void) Py_InitModule("crypto_sign_keypair", Module_methods);} 465 | 466 | void initcrypto_secretbox(){ 467 | (void) Py_InitModule("crypto_secretbox", Module_methods);} 468 | 469 | void initcrypto_secretbox_open(){ 470 | (void) Py_InitModule("crypto_secretbox_open", Module_methods);} 471 | 472 | void initcrypto_hash_sha256(){ 473 | (void) Py_InitModule("crypto_hash_sha256", Module_methods);} 474 | 475 | void initcrypto_hash_sha512(){ 476 | (void) Py_InitModule("crypto_hash_sha512", Module_methods);} 477 | -------------------------------------------------------------------------------- /src/sign_keypair.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | unsigned char pk [32]; 6 | unsigned char sk [64]; 7 | int i ; 8 | 9 | crypto_sign_keypair(pk,sk); 10 | 11 | printf("PUBKEY: "); 12 | for (i=0;i<32;++i) printf("%02x",pk[i]); 13 | printf("\n"); 14 | 15 | printf("SECKEY: "); 16 | for (i=0;i<64;++i) printf("%02x",sk[i]); 17 | printf("\n");} 18 | /* 19 | void randombytes(char *bytes) { 20 | read(0,bytes,64);}*/ 21 | -------------------------------------------------------------------------------- /src/socket_bind.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "socket.h" 6 | #include "byte.h" 7 | 8 | int socket_bind(int fd,const unsigned char *ip,const unsigned char *port) 9 | { 10 | struct sockaddr_in sa; 11 | byte_zero(&sa,sizeof sa); 12 | byte_copy(&sa.sin_addr,4,ip); 13 | byte_copy(&sa.sin_port,2,port); 14 | 15 | /* AF_UNSPEC EAFNOSUPPORT -- d3v11 */ 16 | if (bind(fd,(struct sockaddr *) &sa,sizeof sa) < 0) 17 | { 18 | sa.sin_family = AF_INET; 19 | return bind(fd,(struct sockaddr *) &sa,sizeof sa); 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/tai_dec.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | tai_dec(unsigned char *t, unsigned char *u, unsigned char *v) 4 | { 5 | 6 | static int i; 7 | 8 | memmove(t,u,8); 9 | 10 | for (i=7;i>-1;--i) 11 | { 12 | 13 | if ((t[i] >= v[i]) | (!i)){ t[i] -= v[i]; continue; } t[i] -= v[i]; 14 | if ((t[i-1]) | (!i-1)){ --t[i-1]; continue; } --t[i-1]; 15 | if ((t[i-2]) | (!i-2)){ --t[i-2]; continue; } --t[i-2]; 16 | if ((t[i-3]) | (!i-3)){ --t[i-3]; continue; } --t[i-3]; 17 | if ((t[i-4]) | (!i-4)){ --t[i-4]; continue; } --t[i-4]; 18 | if ((t[i-5]) | (!i-5)){ --t[i-5]; continue; } --t[i-5]; 19 | if ((t[i-6]) | (!i-6)){ --t[i-6]; continue; } --t[i-6]; 20 | --t[i-7]; 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/tai_inc.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | tai_inc(unsigned char *t, unsigned char *u, unsigned char *v) 4 | { 5 | 6 | static int i; 7 | 8 | memmove(t,u,8); 9 | 10 | for (i=7;i>-1;--i) 11 | { 12 | 13 | if (!v[i]) continue; 14 | if ((t[i] + v[i] < 256) | (!i)){ t[i] += v[i]; continue; } t[i] += v[i]; 15 | if ((++t[i-1]) | (!i-1)) continue; 16 | if ((++t[i-2]) | (!i-2)) continue; 17 | if ((++t[i-3]) | (!i-3)) continue; 18 | if ((++t[i-4]) | (!i-4)) continue; 19 | if ((++t[i-5]) | (!i-5)) continue; 20 | if ((++t[i-6]) | (!i-6)) continue; 21 | ++t[i-7]; 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/taia96n.pyx: -------------------------------------------------------------------------------- 1 | #/usr/bin/env python 2 | from random import randrange 3 | from time import time 4 | 5 | def taia96n_now(): 6 | now = time() 7 | return { 8 | 'sec':4611686018427387914L+long(now)+randrange(-8,8), 9 | 'nano':randrange(0,4294967295L), 10 | 11 | # uncomment if you need nano second accuracy. i left 12 | # this optional to avoid clockskew leaks (thanks chi) 13 | # 14 | # 'sec':4611686018427387914L+long(now), 15 | # 'nano':long(1000000000*(now%1)+randrange(0,512)), 16 | 17 | # uncomment for djb style taia96n, with nano second 18 | # precision 19 | # 20 | # 'sec':4611686018427387914L+long(now), 21 | # 'nano':long(1000000000*(now%1)+500), 22 | 23 | } 24 | 25 | def tai_pack(s): return str( 26 | chr(s['sec']>>56&255) + 27 | chr(s['sec']>>48&255) + 28 | chr(s['sec']>>40&255) + 29 | chr(s['sec']>>32&255) + 30 | chr(s['sec']>>24&255) + 31 | chr(s['sec']>>16&255) + 32 | chr(s['sec']>>8&255) + 33 | chr(s['sec']&255) 34 | ) 35 | 36 | def taia96n_pack(s): return str( 37 | tai_pack(s)+ 38 | chr(s['nano']>>24&255)+ 39 | chr(s['nano']>>16&255)+ 40 | chr(s['nano']>>8&255)+ 41 | chr(s['nano']&255) 42 | ) 43 | -------------------------------------------------------------------------------- /src/ucspi-client2server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define USAGE "Usage: ucspi-client2server prog [args]\n" 4 | int main (int argc, char **argv) { 5 | if (argc>2) { 6 | dup2(6,0); 7 | dup2(7,1); 8 | execvp(argv[1],argv+1); 9 | } 10 | write(2,USAGE,strlen(USAGE)); 11 | return 255; 12 | } 13 | -------------------------------------------------------------------------------- /src/ucspi-server2client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define USAGE "Usage: ucspi-server2client prog [args]\n" 4 | int main (int argc, char **argv) { 5 | if (argc>2) { 6 | dup2(0,6); 7 | dup2(1,7); 8 | execvp(argv[1],argv+1); 9 | } 10 | write(2,USAGE,strlen(USAGE)); 11 | return 255; 12 | } 13 | -------------------------------------------------------------------------------- /src/ucspi-socks4aclient.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define USAGE "Usage: ucspi-socks4aclient addr port prog [args]\n" 4 | int main(int argc, char **argv){ 5 | 6 | if ((argc<4)||(strlen(argv[1])>256)||(atoi(argv[2])<0)||(atoi(argv[2])>65535)){ 7 | write(2,USAGE,strlen(USAGE)); 8 | return 64;} 9 | 10 | unsigned char packet[512]={0}; 11 | packet[ 0] = '\x04'; 12 | packet[ 1] = '\x01'; 13 | packet[ 2] = atoi(argv[2])/256; 14 | packet[ 3] = atoi(argv[2])%256; 15 | packet[ 7] = '\x01'; 16 | packet[ 8] = 'u'; 17 | packet[ 9] = 'c'; 18 | packet[10] = 's'; 19 | packet[11] = 'p'; 20 | packet[12] = 'i'; 21 | 22 | memmove(&packet[14],argv[1],strlen(argv[1])+1); 23 | if (write(7,packet,14+strlen(argv[1])+1)<14+strlen(argv[1])+1) return 128+111; 24 | bzero(packet,512); 25 | if (read(6,packet,8)<8) return 128+32; 26 | if ((packet[0]!=0)||(packet[1]!=90)) return 128+111; 27 | execvp(argv[3],argv+3);} 28 | -------------------------------------------------------------------------------- /src/ucspi-stream.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int main(){ 5 | 6 | fcntl(0,4,2050); fcntl(1,4,2050); 7 | fcntl(6,4,2050); fcntl(7,4,2050); 8 | 9 | struct pollfd fds[4]; 10 | fds[0].fd=0; fds[0].events=3; 11 | fds[1].fd=6; fds[1].events=3; 12 | fds[2].fd=1; fds[2].events=4; 13 | fds[3].fd=7; fds[3].events=4; 14 | 15 | unsigned char client_buffer[1024]={0}; 16 | unsigned char server_buffer[1024]={0}; 17 | 18 | int client_eagain=0; 19 | int server_eagain=0; 20 | 21 | int in=0, out=0; 22 | 23 | while (1){ 24 | 25 | poll(fds,2,-1); 26 | poll(fds+2,2,0); 27 | 28 | if ((server_eagain)||(fds[0].revents)){ 29 | if (fds[3].revents){ 30 | if (server_eagain<1024){ 31 | in=read(0,&server_buffer[server_eagain],1024-server_eagain); 32 | if (in<1) break;} 33 | else in=0; 34 | out=write(7,server_buffer,server_eagain+in); 35 | if (out<0) break; 36 | if (out 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifndef UNIX_PATH_MAX 15 | #ifdef __NetBSD__ 16 | #define UNIX_PATH_MAX 104 17 | #else 18 | #define UNIX_PATH_MAX 108 19 | #endif 20 | #endif 21 | 22 | int itoa(char *s, int n, int slen) 23 | { 24 | if (snprintf(s,slen,"%d",n)<0) return -1; 25 | return 0; 26 | } 27 | 28 | main(int argc, char **argv) 29 | { 30 | 31 | int udpfd; 32 | struct sockaddr_in udp; 33 | bzero(&udp,sizeof(udp)); 34 | udp.sin_family = AF_INET; 35 | 36 | unsigned char buffer[1024] = {0}; 37 | 38 | int BROADCAST; 39 | int n = open("env/BROADCAST",0); 40 | if (n>0) 41 | { 42 | if (read(n,buffer,1024)>0) BROADCAST = atoi(buffer); 43 | else BROADCAST = 0; 44 | } else BROADCAST = 0; 45 | close(n); 46 | 47 | if ( 48 | (argc<4) 49 | || (!(udp.sin_port=htons(atoi(argv[2])))) 50 | || (!inet_pton(AF_INET,argv[1],&udp.sin_addr)) 51 | || ((udpfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0) 52 | || (setsockopt(udpfd,SOL_SOCKET,SO_REUSEADDR,(int[]){1},sizeof(int))) 53 | || ((BROADCAST) && (setsockopt(udpfd,SOL_SOCKET,SO_BROADCAST,(int[]){1},sizeof(int)))) 54 | || (bind(udpfd,(struct sockaddr *)&udp,sizeof(udp))<0) 55 | ) 56 | { 57 | write(2,USAGE,strlen(USAGE)); 58 | exit(64); 59 | } 60 | 61 | float LIMIT; 62 | n = open("env/LIMIT",0); 63 | if (n>0) 64 | { 65 | if (read(n,buffer,1024)>0) LIMIT = atof(buffer); 66 | else LIMIT = 1.0; 67 | } else LIMIT = 1.0; 68 | close(n); 69 | 70 | struct passwd *urcd = getpwnam("urcd"); 71 | 72 | if ((!urcd) 73 | || (chdir(argv[3])) 74 | || (chroot(argv[3])) 75 | || (setgroups(0,'\x00')) 76 | || (setgid(urcd->pw_gid)) 77 | || (setuid(urcd->pw_uid))) exit(64); 78 | 79 | int sockfd; 80 | struct sockaddr_un sock; 81 | bzero(&sock,sizeof(sock)); 82 | sock.sun_family = AF_UNIX; 83 | 84 | if ((sockfd=socket(AF_UNIX,SOCK_DGRAM,0))<0) exit(1); 85 | if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n=1))<0) exit(2); 86 | if (fcntl(sockfd,F_SETFL,O_NONBLOCK)<0) exit(3); 87 | 88 | struct sockaddr_un hub; 89 | bzero(&hub,sizeof(hub)); 90 | hub.sun_family = AF_UNIX; 91 | memcpy(&hub.sun_path,"hub\0",4); 92 | 93 | while (1) 94 | { 95 | usleep((int)(LIMIT*1000000)); 96 | if ( 97 | ((n=read(udpfd,buffer,1024))<2+12+4+8) 98 | || (n!=2+12+4+8+buffer[0]*256+buffer[1]) 99 | ) continue; 100 | if (sendto(sockfd,buffer,n,MSG_DONTWAIT,(struct sockaddr *)&hub,sizeof(hub))<0) usleep(262144); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/urc-udpsend.c: -------------------------------------------------------------------------------- 1 | #define USAGE "Usage: urc-udpsend addr port /path/to/sockets/\n" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifndef UNIX_PATH_MAX 16 | #ifdef __NetBSD__ 17 | #define UNIX_PATH_MAX 104 18 | #else 19 | #define UNIX_PATH_MAX 108 20 | #endif 21 | #endif 22 | 23 | int itoa(char *s, int n, int slen) 24 | { 25 | if (snprintf(s,slen,"%d",n)<0) return -1; 26 | return 0; 27 | } 28 | 29 | main(int argc, char **argv) 30 | { 31 | 32 | int udpfd; 33 | struct sockaddr_in udp; 34 | bzero(&udp,sizeof(udp)); 35 | udp.sin_family = AF_INET; 36 | 37 | unsigned char buffer[1024] = {0}; 38 | 39 | int BROADCAST; 40 | int n = open("env/BROADCAST",0); 41 | if (n>0) 42 | { 43 | if (read(n,buffer,1024)>0) BROADCAST = atoi(buffer); 44 | else BROADCAST = 0; 45 | } else BROADCAST = 0; 46 | close(n); 47 | 48 | if ( 49 | (argc<4) 50 | || (!(udp.sin_port=htons(atoi(argv[2])))) 51 | || (!inet_pton(AF_INET,argv[1],&udp.sin_addr)) 52 | || ((udpfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0) 53 | || (setsockopt(udpfd,SOL_SOCKET,SO_REUSEADDR,(int[]){1},sizeof(int))) 54 | || ((BROADCAST) && (setsockopt(udpfd,SOL_SOCKET,SO_BROADCAST,(int[]){1},sizeof(int)))) 55 | || (connect(udpfd,(struct sockaddr *)&udp,sizeof(udp))<0) 56 | ) 57 | { 58 | write(2,USAGE,strlen(USAGE)); 59 | exit(64); 60 | } 61 | 62 | int devurandomfd = open("/dev/urandom",O_RDONLY); 63 | if (devurandomfd<0) exit(255); 64 | unsigned char byte[1]; 65 | 66 | char user[UNIX_PATH_MAX] = {0}; 67 | if (itoa(user,getpid(),UNIX_PATH_MAX)<0) exit(1); 68 | 69 | struct passwd *urcd = getpwnam("urcd"); 70 | 71 | if ((!urcd) 72 | || (chdir(argv[3])) 73 | || (chroot(argv[3])) 74 | || (setgroups(0,'\x00')) 75 | || (setgid(urcd->pw_gid)) 76 | || (setuid(urcd->pw_uid))) exit(64); 77 | 78 | int sockfd; 79 | struct sockaddr_un sock; 80 | bzero(&sock,sizeof(sock)); 81 | sock.sun_family = AF_UNIX; 82 | 83 | void sock_close(int signum) 84 | { 85 | unlink(sock.sun_path); 86 | exit(signum); 87 | } signal(SIGINT,sock_close); 88 | signal(SIGHUP,sock_close); 89 | signal(SIGTERM,sock_close); 90 | 91 | if ((sockfd=socket(AF_UNIX,SOCK_DGRAM,0))<0) exit(2); 92 | if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n=1))<0) exit(3); 93 | n = strlen(user); 94 | if (n > UNIX_PATH_MAX) exit(4); 95 | memcpy(&sock.sun_path,user,n); 96 | unlink(sock.sun_path); 97 | if (bind(sockfd,(struct sockaddr *)&sock,sizeof(sock))<0) exit(5); 98 | 99 | struct sockaddr_un path; 100 | path.sun_family = AF_UNIX; 101 | socklen_t path_len = sizeof(struct sockaddr_un); 102 | 103 | struct pollfd fds[1]; 104 | fds[0].fd = sockfd; 105 | fds[0].events = POLLIN | POLLPRI; 106 | 107 | while (1) 108 | { 109 | bzero(path.sun_path,UNIX_PATH_MAX); 110 | n = recvfrom(sockfd,buffer,1024,0,(struct sockaddr *)&path,&path_len); 111 | if (!n) continue; 112 | if (n<0) sock_close(6); 113 | if (!path_len) continue; 114 | if (buffer[n-1] != '\n') continue; 115 | if (read(devurandomfd,byte,1)<1) sock_close(7); 116 | poll(fds,1,byte[0]<<4); 117 | write(udpfd,buffer,n); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/urc2sd.pyx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | USAGE='''\ 4 | urc2sd: help: This NOTICE can be disabled if env/HELP is set \ 5 | to 0. /INVITE adds temporary relay if env/INVITE is set to 1. \ 6 | Contact the urc2sd admin for permenance. ChanOp BAN/EXCEPT \ 7 | masks also filter relay traffic. \ 8 | Thanks for supporting URC, the anonymous decentralized \ 9 | alternative to IRC.\n''' 10 | 11 | from binascii import hexlify 12 | from nacltaia import * 13 | from taia96n import * 14 | import unicodedata 15 | import collections 16 | import subprocess 17 | import codecs 18 | import select 19 | import socket 20 | import signal 21 | import time 22 | import pwd 23 | import sys 24 | import re 25 | import os 26 | 27 | RE = 'a-zA-Z0-9^(\)\-_{\}[\]|\\\\' 28 | re_USER = re.compile('!\S+@',re.IGNORECASE).sub 29 | re_SPLIT = re.compile(' +',re.IGNORECASE).split 30 | re_CLIENT_HELP = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[:#'+RE+'.]+ PRIVMSG [#&!+]['+RE+']+ :['+RE+']+[:,]? help$',re.IGNORECASE).search 31 | re_CLIENT_PRIVMSG_NOTICE_TOPIC = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[:#'+RE+'.]+ ((PRIVMSG)|(NOTICE)|(TOPIC)) [#&!+]['+RE+']+ :.*$',re.IGNORECASE).search 32 | re_CLIENT_PART = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[:#'+RE+'.]+ PART [#&!+]['+RE+']+( :)?',re.IGNORECASE).search 33 | re_CLIENT_QUIT = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[:#'+RE+'.]+ QUIT( :)?',re.IGNORECASE).search 34 | re_CLIENT_PING = re.compile('^PING :?.+$',re.IGNORECASE).search 35 | re_CLIENT_JOIN = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[:#'+RE+'.]+ JOIN :[#&!+]['+RE+']+$',re.IGNORECASE).search 36 | re_CLIENT_KICK = re.compile('^:.+ KICK [#&!+]['+RE+']+ ['+RE+']+',re.IGNORECASE).search 37 | re_CLIENT_CHANMODE = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[:#'+RE+'.]+ MODE [#&!+]['+RE+']+ [-+][be] \S+ ?',re.IGNORECASE).search 38 | re_CLIENT_BAN_EXCEPT = re.compile('^:['+RE+'!@~.]+ ((367)|(348)) ['+RE+']+ [#&!+]['+RE+']+ \S+ ',re.IGNORECASE).search 39 | re_BUFFER_CTCP_DCC = re.compile('\x01(ACTION )?',re.IGNORECASE).sub 40 | re_BUFFER_COLOUR = re.compile('(\x03[0-9][0-9]?((?<=[0-9]),[0-9]?[0-9]?)?)|[\x02\x03\x0f\x1d\x1f]',re.IGNORECASE).sub 41 | re_SERVER_PRIVMSG_NOTICE_TOPIC = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[:#'+RE+'.]{1,256} ((PRIVMSG)|(NOTICE)|(TOPIC)) [#&!+]['+RE+']+ :.*$',re.IGNORECASE).search 42 | 43 | ### some operating systems do not set atime reliably ### 44 | if os.path.exists('env/HELP') \ 45 | and time.time() - os.stat('env/HELP')[7] >= 2048 \ 46 | and int(open('env/HELP','rb').read().split('\n')[0]): 47 | os.utime('env/HELP',(time.time(),time.time())) 48 | HELP = 1 49 | else: HELP = 0 50 | 51 | LIMIT = float(open('env/LIMIT','rb').read().split('\n')[0]) if os.path.exists('env/LIMIT') else 1 52 | INVITE = int(open('env/INVITE','rb').read().split('\n')[0]) if os.path.exists('env/INVITE') else 0 53 | COLOUR = int(open('env/COLOUR','rb').read().split('\n')[0]) if os.path.exists('env/COLOUR') else 0 54 | UNICODE = int(open('env/UNICODE','rb').read().split('\n')[0]) if os.path.exists('env/UNICODE') else 0 55 | TIMEOUT = int(open('env/TIMEOUT','rb').read().split('\n')[0]) if os.path.exists('env/TIMEOUT') else 128 56 | PRESENCE = int(open('env/PRESENCE','rb').read().split('\n')[0]) if os.path.exists('env/PRESENCE') else 0 57 | URCSIGNDB = open('env/URCSIGNDB','rb').read().split('\n')[0] if os.path.exists('env/URCSIGNDB') else str() 58 | CHANLIMIT = int(open('env/CHANLIMIT','rb').read().split('\n')[0]) if os.path.exists('env/CHANLIMIT') else 16 59 | URCSIGNPUBKEYDIR = open('env/URCSIGNPUBKEYDIR','rb').read().split('\n')[0] if os.path.exists('env/URCSIGNPUBKEYDIR') else str() 60 | 61 | ### nacl-20110221's randombytes() not compatible with chroot ### 62 | devurandomfd = os.open("/dev/urandom",os.O_RDONLY) 63 | def randombytes(n): return try_read(devurandomfd,n) 64 | 65 | if URCSIGNDB or URCSIGNPUBKEYDIR: 66 | 67 | ### NaCl's crypto_sign / crypto_sign_open API sucks ### 68 | def _crypto_sign(m,sk): 69 | s = crypto_sign(m,sk) 70 | return s[:32]+s[-32:] 71 | 72 | def _crypto_sign_open(m,s,pk): 73 | return 1 if crypto_sign_open(s[:32]+m+s[32:],pk) != 0 else 0 74 | 75 | if URCSIGNPUBKEYDIR: 76 | urcsignpubkeydb = dict() 77 | for dst in os.listdir(URCSIGNPUBKEYDIR): 78 | dst = dst.lower() 79 | urcsignpubkeydb[dst] = dict() 80 | for src in os.listdir(URCSIGNPUBKEYDIR+'/'+dst): 81 | urcsignpubkeydb[dst][src.lower()] = open(URCSIGNPUBKEYDIR+'/'+dst+'/'+src,'rb').read(64).decode('hex') 82 | 83 | if URCSIGNDB: 84 | urcsigndb = dict() 85 | for src in os.listdir(URCSIGNDB): 86 | urcsigndb[src.lower()] = open(URCSIGNDB+'/'+src,'rb').read(64).decode('hex') 87 | 88 | BAN = dict() 89 | EXCEPT = dict() 90 | seen = time.time() 91 | ping = time.time() 92 | user = str(os.getpid()) 93 | bytes = [(chr(i),i) for i in xrange(0,256)] 94 | nick = open('nick','rb').read().split('\n')[0] 95 | 96 | channels = collections.deque([],CHANLIMIT) 97 | for dst in open('channels','rb').read().lower().split('\n'): 98 | if dst: channels.append(dst) 99 | 100 | auto_cmd = list() 101 | for cmd in open('auto_cmd','rb').read().split('\n'): 102 | if cmd: auto_cmd.append(cmd) 103 | 104 | def sock_close(sn,sf): 105 | try: os.remove(str(os.getpid())) 106 | except: pass 107 | if sn: sys.exit(sn&255) 108 | 109 | signal.signal(signal.SIGHUP,sock_close) 110 | signal.signal(signal.SIGINT,sock_close) 111 | signal.signal(signal.SIGTERM,sock_close) 112 | signal.signal(signal.SIGCHLD,sock_close) 113 | 114 | rd = 0 115 | """ 116 | if os.access('stdin',os.X_OK): 117 | p = subprocess.Popen(['./stdin'],stdout=subprocess.PIPE) 118 | rd = p.stdout.fileno() 119 | del p 120 | 121 | if os.access('stdout',os.X_OK): 122 | p = subprocess.Popen(['./stdout'],stdin=subprocess.PIPE,stdout=subprocess.PIPE) 123 | pipefd = ( p.stdout.fileno(), p.stdin.fileno() ) 124 | del p 125 | else: pipefd = os.pipe() 126 | """ 127 | 128 | ### nacl-20110221's randombytes() not compatible with chroot ### 129 | devurandomfd = os.open("/dev/urandom",os.O_RDONLY) 130 | def randombytes(n): return try_read(devurandomfd,n) 131 | 132 | uid, gid = pwd.getpwnam('urcd')[2:4] 133 | os.chdir(sys.argv[1]) 134 | os.chroot(os.getcwd()) 135 | os.setgroups(list()) 136 | os.setgid(gid) 137 | os.setuid(uid) 138 | root = os.getcwd() 139 | del uid, gid 140 | 141 | sock=socket.socket(socket.AF_UNIX,socket.SOCK_DGRAM) 142 | sock_close(0,0) 143 | sock.bind(str(os.getpid())) 144 | sock.setblocking(0) 145 | sd=sock.fileno() 146 | 147 | poll=select.poll() 148 | poll.register(rd,select.POLLIN|select.POLLPRI) 149 | """poll.register(pipefd[0],select.POLLIN)""" 150 | poll.register(sd,select.POLLIN) 151 | poll=poll.poll 152 | 153 | client_revents=select.poll() 154 | client_revents.register(rd,select.POLLIN|select.POLLPRI) 155 | client_revents=client_revents.poll 156 | 157 | """ 158 | pipe_revents=select.poll() 159 | pipe_revents.register(pipefd[0],select.POLLIN) 160 | pipe_revents=pipe_revents.poll 161 | """ 162 | 163 | server_revents=select.poll() 164 | server_revents.register(sd,select.POLLIN) 165 | server_revents=server_revents.poll 166 | 167 | def try_read(fd,buffer_len): 168 | try: return os.read(fd,buffer_len) 169 | except: sock_close(1,0) 170 | 171 | def try_write(fd,buffer): 172 | try: return os.write(fd,buffer) 173 | except: sock_close(2,0) 174 | 175 | def sock_write(buffer): 176 | buflen = len(buffer) 177 | buffer = chr(buflen>>8)+chr(buflen%256)+taia96n_pack(taia96n_now())+'\x00\x00\x00\x00'+randombytes(8)+buffer 178 | try: sock.sendto(buffer,'hub') 179 | except: pass 180 | 181 | try_write(1,'USER '+nick+' '+nick+' '+nick+' :'+nick+'\nNICK '+nick+'\n') 182 | 183 | def INIT(): 184 | if client_revents(8192): return 185 | global INIT, auto_cmd, channels 186 | INIT = 0 187 | for cmd in auto_cmd: 188 | time.sleep(LIMIT) 189 | try_write(1,cmd+'\n') 190 | for dst in channels: 191 | time.sleep(LIMIT) 192 | try_write(1,'JOIN '+dst+'\n') 193 | if HELP: 194 | time.sleep(LIMIT) 195 | try_write(1,'NOTICE '+dst+' :'+USAGE) 196 | channels = collections.deque([],CHANLIMIT) 197 | del auto_cmd 198 | 199 | while 1: 200 | 201 | if poll(TIMEOUT<<10) and not INIT: time.sleep(LIMIT) 202 | now = time.time() 203 | 204 | if not client_revents(0): 205 | if now - seen >= TIMEOUT: sock_close(3,0) 206 | if now - ping >= TIMEOUT >> 4: 207 | try_write(1,'PING :LAG\n') 208 | ping = now 209 | 210 | else: 211 | buffer, seen, ping = str(), now, now 212 | while 1: 213 | byte = try_read(rd,1) 214 | if byte == '': sock_close(4,0) 215 | if byte == '\n': break 216 | if byte != '\r' and len(buffer)<768: buffer += byte 217 | 218 | if re_CLIENT_HELP(buffer): try_write(1,'NOTICE '+re_SPLIT(buffer,3)[2]+' :'+USAGE) 219 | 220 | if re_CLIENT_PRIVMSG_NOTICE_TOPIC(buffer): 221 | if buffer[1:].split('!',1)[0] != nick: sock_write(buffer+'\n') 222 | 223 | elif PRESENCE and re_CLIENT_PART(buffer): 224 | if len(buffer.split(' :'))<2: buffer += ' :' 225 | sock_write(buffer+'\n') 226 | 227 | elif PRESENCE and re_CLIENT_QUIT(buffer): 228 | if len(buffer.split(' :'))<2: buffer += ' :' 229 | sock_write(buffer+'\n') 230 | 231 | elif re_CLIENT_PING(buffer): try_write(1,'PONG '+re_SPLIT(buffer,1)[1]+'\n') 232 | 233 | elif re_CLIENT_JOIN(buffer): 234 | if PRESENCE: sock_write(buffer+'\n') 235 | dst = buffer.split(' :')[1].lower() 236 | if not dst in channels: 237 | if len(channels) - 1 < CHANLIMIT: 238 | BAN[dst], EXCEPT[dst] = list(), list() 239 | channels.append(dst) 240 | try_write(1,'MODE '+dst+' b\n') 241 | time.sleep(LIMIT) 242 | try_write(1,'MODE '+dst+' e\n') 243 | else: try_write(1,'PART '+dst+' :CHANLIMIT\n') 244 | 245 | elif re.search('^:'+re.escape(nick).upper()+'!.+ NICK ',buffer.upper()): 246 | nick = re_SPLIT(buffer)[2] 247 | re_CLIENT_HELP = re.compile('^:['+RE+']+![~:#'+RE+'.]+@[:#'+RE+'.]+ PRIVMSG [#&!+]['+RE+']+ :['+re.escape(nick)+']+[:,]? help$',re.IGNORECASE).search 248 | 249 | elif re.search('^:.+ 433 .+ '+re.escape(nick),buffer): 250 | nick+='_' 251 | try_write(1,'NICK '+nick+'\n') 252 | 253 | elif re_CLIENT_KICK(buffer): 254 | if len(buffer.split(' :'))<2: buffer += ' :' 255 | sock_write(buffer+'\n') 256 | if re_SPLIT(buffer,4)[3].lower() == nick.lower(): 257 | try_write(1,'JOIN '+re_SPLIT(buffer,4)[2]+'\n') 258 | del EXCEPT[dst], BAN[dst] 259 | channels.remove(dst) 260 | 261 | elif INVITE and len(channels) < CHANLIMIT and re.search('^:['+RE+']+![~'+RE+'.]+@['+RE+'.]+ INVITE '+re.escape(nick).upper()+' :[#&!+]['+RE+']+$',buffer.upper()): 262 | dst = buffer[1:].split(':',1)[1].lower() 263 | if not dst in channels: try_write(1,'JOIN '+dst+'\n') 264 | 265 | elif re_CLIENT_CHANMODE(buffer): 266 | try: 267 | src, cmd, dst = re_SPLIT(buffer,5)[2:5] 268 | dst = re.compile('^'+re.escape(dst).replace('\\*','.*')+'$',re.IGNORECASE).search 269 | src = src.lower() 270 | if cmd[1] == 'b': 271 | BAN[src].append(dst) if cmd[0] == '+' and not dst in BAN[src] else BAN[src].remove(dst) 272 | elif cmd[1] == 'e': 273 | EXCEPT[src].append(dst) if cmd[0] == '+' and not dst in EXCEPT[src] else EXCEPT[src].remove(dst) 274 | except: pass 275 | 276 | elif re_CLIENT_BAN_EXCEPT(buffer): 277 | try: 278 | cmd, src, dst, msg = re_SPLIT(buffer,5)[1:5] 279 | msg = re.compile('^'+re.escape(msg).replace('\\*','.*')+'$',re.IGNORECASE).search 280 | dst = dst.lower() 281 | if cmd == '367': 282 | if not msg in BAN[dst]: BAN[dst].append(msg) 283 | elif cmd == '348': 284 | if not msg in EXCEPT[dst]: EXCEPT.append(msg) 285 | except: pass 286 | 287 | if INIT: 288 | INIT() 289 | continue 290 | 291 | if server_revents(0): 292 | buffer = try_read(sd,2+12+4+8+1024) 293 | 294 | ### URCSIGN ### 295 | if buffer[2+12:2+12+4] == '\x01\x00\x00\x00': 296 | buflen = len(buffer) 297 | try: 298 | src, cmd, dst = re_SPLIT(buffer[2+12+4+8+1:].lower(),3)[:3] 299 | src = src.split('!',1)[0] 300 | except: src, cmd, dst = buffer[2+12+4+8+1:].split('!',1)[0].lower(), str(), str() 301 | 302 | if URCSIGNPUBKEYDIR \ 303 | and dst in urcsignpubkeydb.keys() \ 304 | and src in urcsignpubkeydb[dst].keys(): 305 | try: 306 | if _crypto_sign_open(buffer[:buflen-64],buffer[-64:],urcsignpubkeydb[dst][src]): 307 | buffer = re_USER('!sign@',buffer[2+12+4+8:].split('\n',1)[0],1) 308 | else: buffer = re_USER('!urcd@',buffer[2+12+4+8:].split('\n',1)[0],1) 309 | except: buffer = re_USER('!urcd@',buffer[2+12+4+8:].split('\n',1)[0],1) 310 | elif URCSIGNDB: 311 | try: 312 | if _crypto_sign_open(buffer[:buflen-64],buffer[-64:],urcsigndb[src]): 313 | buffer = re_USER('!sign@',buffer[2+12+4+8:].split('\n',1)[0],1) 314 | else: buffer = re_USER('!urcd@',buffer[2+12+4+8:].split('\n',1)[0],1) 315 | except: buffer = re_USER('!urcd@',buffer[2+12+4+8:].split('\n',1)[0],1) 316 | else: buffer = re_USER('!urcd@',buffer[2+12+4+8:].split('\n',1)[0],1) 317 | 318 | ### URCHUB ### 319 | else: buffer = re_USER('!urcd@',buffer[2+12+4+8:].split('\n',1)[0],1) 320 | 321 | """ 322 | if buffer: try_write(pipefd[1],buffer+'\n') 323 | 324 | if pipe_revents(0): 325 | 326 | buffer = str() 327 | while 1: 328 | byte = try_read(pipefd[0],1) 329 | if byte == '': sock_close(5,0) 330 | if byte == '\n': break 331 | if byte != '\r' and len(buffer)<768: buffer += byte 332 | """ 333 | 334 | action, buffer = (1, re_BUFFER_CTCP_DCC('',buffer) + '\x01') if '\x01ACTION ' in buffer.upper() else (0, re_BUFFER_CTCP_DCC('',buffer)) 335 | if not COLOUR: buffer = re_BUFFER_COLOUR('',buffer) 336 | if not UNICODE: 337 | buffer = codecs.ascii_encode(unicodedata.normalize('NFKD',unicode(buffer,'utf-8','replace')),'ignore')[0] 338 | buffer = ''.join(byte for byte in buffer if 127 > ord(byte) > 31 or byte in ['\x01','\x02','\x03','\x0f','\x1d','\x1f']) 339 | buffer += '\n' 340 | 341 | poll(ord(randombytes(1))<<4) ### may reduce some side channels ### 342 | 343 | if re_SERVER_PRIVMSG_NOTICE_TOPIC(buffer): 344 | dst = re_SPLIT(buffer,3)[2].lower() 345 | if dst in channels: 346 | cmd, src = 1, re_SPLIT(buffer[1:],1)[0] 347 | if buffer.split('!',1)[1].split('@')[0] == 'sign': src = src.split('!',1)[0] + '!*@verified' 348 | else: src = src.split('!',1)[0] + '!*@' + hexlify(crypto_hash_sha256(src.split('@',1)[1])[:4]) 349 | for cmd in EXCEPT[dst]: 350 | if cmd(src): 351 | cmd = 0 352 | break 353 | if cmd: 354 | for cmd in BAN[dst]: 355 | if cmd(src): 356 | cmd = 0 357 | break 358 | if cmd == 0: continue 359 | cmd = re_SPLIT(buffer,3)[1].upper() 360 | src = src.replace('!*@','@',1) + '> ' 361 | if COLOUR and buffer.split('!',1)[1].split('@')[0] == 'sign': 362 | src = '\x03' + str(ord(hexlify(crypto_hash_sha256(src)[0])[:2].decode('hex'))%16) + src.replace('@','\x0f@',1) 363 | if cmd == 'TOPIC': 364 | try_write(1,'NOTICE '+dst+' :'+src+'/TOPIC\n') 365 | time.sleep(LIMIT) 366 | src = str() 367 | if action: src = '\x01ACTION ' + src 368 | msg = buffer.split(' :',1)[1] 369 | buffer = cmd + ' ' + dst + ' :' + src + msg + '\n' 370 | try_write(1,buffer) 371 | -------------------------------------------------------------------------------- /src/urccache-failover.c: -------------------------------------------------------------------------------- 1 | #define USAGE "Usage: urccache /path/to/root/\n" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | main(int argc, char **argv) 11 | { 12 | 13 | if (argc<2) 14 | { 15 | write(2,USAGE,strlen(USAGE)); 16 | exit(64); 17 | } 18 | 19 | unsigned char cache[131072*32]={0}; 20 | 21 | struct passwd *urcd = getpwnam("urcd"); 22 | 23 | if ((!urcd) 24 | || (chdir(argv[1])) 25 | || (chroot(argv[1])) 26 | || (setgroups(0,'\x00')) 27 | || (setgid(urcd->pw_gid)) 28 | || (setuid(urcd->pw_uid))) exit(64); 29 | 30 | unsigned char buffer[16+8+65536+32]; 31 | unsigned char hash[32]; 32 | int i, n, l; 33 | 34 | while (1) 35 | { 36 | 37 | readbuffer: if (read(0,buffer,2)<2) exit(1); 38 | 39 | n = 0; 40 | l = 16 + 8 + buffer[0] * 256 + buffer[1]; 41 | 42 | while (n-32;i-=32) if (!crypto_verify_32(hash,cache+i)) 52 | { 53 | if (write(1,"\1",1)<1) exit(3); 54 | goto readbuffer; 55 | } 56 | 57 | memcpy(cache,cache+32,131072*32-32); 58 | memcpy(cache+131072*32-32,hash,32); 59 | 60 | if (write(1,"\0",1)<1) exit(4); 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/urccache.c: -------------------------------------------------------------------------------- 1 | #define USAGE "Usage: urccache /path/to/root/\n" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "tai_dec.h" 15 | #include "tai_inc.h" 16 | 17 | main(int argc, char **argv) { 18 | 19 | if (argc<2) 20 | { 21 | write(2,USAGE,strlen(USAGE)); 22 | exit(64); 23 | } 24 | 25 | unsigned char cache[256][16384]={0}; 26 | unsigned char buffer[65536*2]; 27 | unsigned char salt[32]; 28 | unsigned char hash[32]; 29 | unsigned char ts[16]; 30 | unsigned char st[16]; 31 | unsigned char ret[1]; 32 | 33 | unsigned long timecached[256]; 34 | float cached[256]; 35 | int i, n, l; 36 | 37 | randombytes(salt,32); 38 | 39 | taia_now(st); 40 | taia_pack(st,st); 41 | tai_inc(st,st,"\0\0\0\0\0\0\0\x20"); 42 | 43 | bzero(cached,sizeof(cached)); 44 | for (i=0;i<256;++i) timecached[i] = time(0L); 45 | 46 | struct passwd *urcd = getpwnam("urcd"); 47 | 48 | if ((!urcd) 49 | || (chdir(argv[1])) 50 | || (chroot(argv[1])) 51 | || (setgroups(0,'\x00')) 52 | || (setgid(urcd->pw_gid)) 53 | || (setuid(urcd->pw_uid))) exit(64); 54 | 55 | while (1) { 56 | 57 | readbuffer: if (read(0,buffer,2)<2) exit(1); 58 | 59 | n = 0; 60 | l = 12 + 4 + 8 + buffer[0] * 256 + buffer[1]; 61 | 62 | while (n buffer[i]) 73 | { 74 | if (write(1,"\4",1)<1) exit(3); 75 | goto readbuffer; 76 | } 77 | } 78 | } 79 | 80 | taia_now(ts); 81 | taia_pack(ts,ts); 82 | 83 | tai_dec(ts,ts,"\0\0\0\0\0\0\0\x80"); 84 | 85 | for (i=0;i<12;++i) 86 | { 87 | if (ts[i] < buffer[i]) break; 88 | if (ts[i] > buffer[i]) 89 | { 90 | if (write(1,"\3",1)<1) exit(4); 91 | goto readbuffer; 92 | } 93 | } 94 | 95 | tai_inc(ts,ts,"\0\0\0\0\0\0\x01\0"); 96 | 97 | for (i=0;i<12;++i) 98 | { 99 | if (ts[i] > buffer[i]) break; 100 | if (ts[i] < buffer[i]) 101 | { 102 | if (write(1,"\2",1)<1) exit(5); 103 | goto readbuffer; 104 | } 105 | } 106 | 107 | memcpy(buffer+l,salt,32); 108 | crypto_hash_sha256(hash,buffer,l+32); 109 | 110 | for (i=16384-32;i>-32;i-=32) if (!crypto_verify_32(hash,cache[hash[0]]+i)) 111 | { 112 | if (write(1,"\1",1)<1) exit(6); 113 | goto readbuffer; 114 | } 115 | 116 | memcpy(cache[hash[0]],cache[hash[0]]+32,16384-32); 117 | memcpy(cache[hash[0]]+16384-32,hash,32); 118 | 119 | if (write(1,"\0",1)<1) exit(7); 120 | 121 | if (cached[hash[0]] == 512.0) cached[hash[0]] = 0.0; 122 | if (time(0L) - timecached[hash[0]] >= 256) 123 | { 124 | timecached[hash[0]] = time(0L); 125 | cached[hash[0]] = 0.0; 126 | } ++cached[hash[0]]; 127 | 128 | usleep((int) (cached[hash[0]] / 512.0 * 1000000.0)); 129 | 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/urchub.c: -------------------------------------------------------------------------------- 1 | #define USAGE "Usage: urchub ./urccache /path/to/sockets/\n" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef UNIX_PATH_MAX 18 | #ifdef __NetBSD__ 19 | #define UNIX_PATH_MAX 104 20 | #else 21 | #define UNIX_PATH_MAX 108 22 | #endif 23 | #endif 24 | 25 | main(int argc, char **argv) 26 | { 27 | 28 | if (argc<3) 29 | { 30 | write(2,USAGE,strlen(USAGE)); 31 | exit(64); 32 | } 33 | 34 | int cache_pid; 35 | unsigned char ret[1]; 36 | int cachein[2], cacheout[2]; 37 | 38 | if ((pipe(cachein)<0) || (pipe(cacheout)<0)) exit(1); 39 | cache_pid = fork(); 40 | if (!cache_pid) 41 | { 42 | close(0); 43 | close(1); 44 | dup(cachein[0]); 45 | dup(cacheout[1]); 46 | close(cachein[1]); 47 | close(cacheout[0]); 48 | execvp(argv[1],argv+1); 49 | } else { 50 | if (cache_pid<0) exit(2); 51 | } close(cachein[0]); close(cacheout[1]); 52 | 53 | struct passwd *urcd = getpwnam("urcd"); 54 | 55 | if ((!urcd) 56 | || (chdir(argv[2])) 57 | || (chroot(argv[2])) 58 | || (setgroups(0,'\x00')) 59 | || (setgid(urcd->pw_gid)) 60 | || (setuid(urcd->pw_uid))) exit(64); 61 | 62 | unsigned char buffer[2+16+8+65536]; 63 | char user[] = "hub\0"; 64 | int sockfd; 65 | 66 | struct sockaddr_un sock; 67 | bzero(&sock,sizeof(sock)); 68 | sock.sun_family = AF_UNIX; 69 | 70 | void sock_close(int signum) 71 | { 72 | unlink(sock.sun_path); 73 | exit(signum); 74 | } signal(SIGINT,sock_close); 75 | signal(SIGHUP,sock_close); 76 | signal(SIGTERM,sock_close); 77 | signal(SIGCHLD,sock_close); 78 | 79 | sockfd = socket(AF_UNIX,SOCK_DGRAM,0); 80 | if (sockfd<0) exit(3); 81 | int n = 1; 82 | if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n))<0) exit(4); 83 | int userlen = strlen(user); 84 | if (userlen > UNIX_PATH_MAX) exit(5); 85 | memcpy(&sock.sun_path,user,userlen); 86 | unlink(sock.sun_path); 87 | if (bind(sockfd,(struct sockaddr *)&sock,sizeof(sock))<0) exit(6); 88 | 89 | int strlen_recvpath; 90 | struct sockaddr_un recvpath; 91 | recvpath.sun_family = AF_UNIX; 92 | socklen_t recvpath_len = sizeof(struct sockaddr_un); 93 | 94 | DIR *root; 95 | int sendpath_len; 96 | struct dirent *sendpath; 97 | struct sockaddr_un sendpaths; 98 | sendpaths.sun_family = AF_UNIX; 99 | 100 | while (1) 101 | { 102 | recvpath_len = sizeof(recvpath); // must be initialized each recvfrom call 103 | bzero(&recvpath.sun_path,UNIX_PATH_MAX); 104 | n = recvfrom(sockfd,buffer,65536,0,(struct sockaddr *)&recvpath,&recvpath_len); 105 | if (!n) continue; 106 | if (n<0) sock_close(7); 107 | if (n!=2+16+8+buffer[0]*256+buffer[1]) continue; 108 | if (write(cachein[1],buffer,n)<0) sock_close(8); 109 | if (read(cacheout[0],ret,1)<1) sock_close(9); 110 | if (ret[0]) continue; 111 | 112 | root = opendir("/"); 113 | if (!root) sock_close(10); 114 | strlen_recvpath = strlen(recvpath.sun_path); 115 | while ((sendpath = readdir(root))) 116 | { 117 | if (sendpath->d_name[0] == '.') continue; 118 | sendpath_len = strlen(sendpath->d_name); 119 | if (sendpath_len > UNIX_PATH_MAX) continue; 120 | if ((sendpath_len == userlen) && (!memcmp(sendpath->d_name,user,userlen))) continue; 121 | if ((sendpath_len == strlen_recvpath) && (!memcmp(sendpath->d_name,recvpath.sun_path,strlen_recvpath))) continue; 122 | bzero(sendpaths.sun_path,UNIX_PATH_MAX); 123 | memcpy(&sendpaths.sun_path,sendpath->d_name,sendpath_len); 124 | sendto(sockfd,buffer,n,MSG_DONTWAIT,(struct sockaddr *)&sendpaths,sizeof(sendpaths)); 125 | } closedir(root); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/urchubstream.c: -------------------------------------------------------------------------------- 1 | #define USAGE "Usage: urchubstream /path/to/sockets/\n" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifndef UNIX_PATH_MAX 15 | #ifdef __NetBSD__ 16 | #define UNIX_PATH_MAX 104 17 | #else 18 | #define UNIX_PATH_MAX 108 19 | #endif 20 | #endif 21 | 22 | int itoa(char *s, int n, int slen) 23 | { 24 | if (snprintf(s,slen,"%d",n)<0) return -1; 25 | return 0; 26 | } 27 | 28 | main(int argc, char **argv) 29 | { 30 | 31 | if (argc<2) 32 | { 33 | write(2,USAGE,strlen(USAGE)); 34 | exit(64); 35 | } 36 | 37 | int devurandomfd = open("/dev/urandom",O_RDONLY); 38 | if (devurandomfd<0) exit(255); 39 | unsigned char byte[1]; 40 | 41 | int i, n, l; 42 | unsigned char buffer[2+16+8+1024] = {0}; 43 | int rd = 0, wr = 1, sd = -1; 44 | if (getenv("TCPCLIENT")){ rd = 6; wr = 7; } 45 | 46 | float LIMIT; 47 | n = open("env/LIMIT",0); 48 | if (n>0) 49 | { 50 | if (read(n,buffer,1024)>0) LIMIT = atof(buffer); 51 | else LIMIT = 1.0; 52 | } else LIMIT = 1.0; 53 | close(n); 54 | 55 | char user[UNIX_PATH_MAX] = {0}; 56 | if (itoa(user,getpid(),UNIX_PATH_MAX)<0) exit(1); 57 | 58 | struct passwd *urcd = getpwnam("urcd"); 59 | 60 | if ((!urcd) 61 | || (chdir(argv[1])) 62 | || (chroot(argv[1])) 63 | || (setgroups(0,'\x00')) 64 | || (setgid(urcd->pw_gid)) 65 | || (setuid(urcd->pw_uid))) exit(64); 66 | 67 | struct sockaddr_un sock; 68 | bzero(&sock,sizeof(sock)); 69 | sock.sun_family = AF_UNIX; 70 | 71 | void sock_close(int signum) 72 | { 73 | unlink(sock.sun_path); 74 | exit(signum); 75 | } signal(SIGINT,sock_close); 76 | signal(SIGHUP,sock_close); 77 | signal(SIGTERM,sock_close); 78 | 79 | if ((sd=socket(AF_UNIX,SOCK_DGRAM,0))<0) exit(2); 80 | n = 1; 81 | if (setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n))<0) exit(3); 82 | int userlen = strlen(user); 83 | if (userlen > UNIX_PATH_MAX) exit(4); 84 | memcpy(&sock.sun_path,user,userlen); 85 | unlink(sock.sun_path); 86 | if (bind(sd,(struct sockaddr *)&sock,sizeof(sock))<0) exit(5); 87 | 88 | struct pollfd fds[2]; 89 | fds[0].fd = rd; fds[0].events = POLLIN | POLLPRI; 90 | fds[1].fd = sd; fds[1].events = POLLIN; 91 | 92 | struct sockaddr_un hub; 93 | bzero(&hub,sizeof(hub)); 94 | hub.sun_family = AF_UNIX; 95 | memcpy(&hub.sun_path,"hub\0",4); 96 | 97 | while (1) { 98 | 99 | poll(fds,2,-1); 100 | 101 | if (fds[0].revents) 102 | { 103 | if (read(rd,buffer,2)<2) sock_close(7); 104 | n = 2; 105 | l = 2+16+8+buffer[0]*256+buffer[1]; 106 | if (l>2+16+8+1024) sock_close(8); 107 | 108 | while (n 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifndef UNIX_PATH_MAX 16 | #ifdef __NetBSD__ 17 | #define UNIX_PATH_MAX 104 18 | #else 19 | #define UNIX_PATH_MAX 108 20 | #endif 21 | #endif 22 | 23 | main(int argc, char **argv) 24 | { 25 | 26 | if (argc<2) 27 | { 28 | write(2,USAGE,strlen(USAGE)); 29 | exit(64); 30 | } 31 | 32 | char buffer[1024] = {0}; 33 | 34 | int n; 35 | float LIMIT; 36 | n = open("env/LIMIT",0); 37 | if (n>0) 38 | { 39 | if (read(n,buffer,1024)>0) LIMIT = atof(buffer); 40 | else LIMIT = 1.0; 41 | } else LIMIT = 1.0; 42 | close(n); 43 | 44 | struct passwd *urcd = getpwnam("urcd"); 45 | 46 | if ((!urcd) 47 | || (chdir(argv[1])) 48 | || (chroot(argv[1])) 49 | || (setgroups(0,'\x00')) 50 | || (setgid(urcd->pw_gid)) 51 | || (setuid(urcd->pw_uid))) exit(64); 52 | 53 | int sockfd; 54 | struct sockaddr_un sock; 55 | bzero(&sock,sizeof(sock)); 56 | sock.sun_family = AF_UNIX; 57 | 58 | if ((sockfd=socket(AF_UNIX,SOCK_DGRAM,0))<0) exit(1); 59 | n = 1; 60 | if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n))<0) exit(2); 61 | if (fcntl(sockfd,F_SETFL,O_NONBLOCK)<0) exit(3); 62 | 63 | struct pollfd fds[1]; 64 | fds[0].fd = 0; 65 | fds[0].events = POLLIN | POLLPRI; 66 | 67 | DIR *root; 68 | int pathlen; 69 | struct dirent *path; 70 | struct sockaddr_un paths; 71 | paths.sun_family = AF_UNIX; 72 | 73 | while (1) 74 | { 75 | 76 | poll(fds,1,-1); 77 | 78 | usleep((int)(LIMIT*1000000)); 79 | 80 | for (n=0;n<1024;++n) 81 | { 82 | if (read(0,buffer+n,1)<1) exit(4); 83 | if (buffer[n] == '\n') break; 84 | } if (buffer[n] != '\n') continue; 85 | ++n; 86 | 87 | root = opendir("/"); 88 | if (!root) exit(5); 89 | 90 | while ((path = readdir(root))) 91 | { 92 | if (path->d_name[0] == '.') continue; 93 | pathlen = strlen(path->d_name); 94 | if (pathlen > UNIX_PATH_MAX) continue; 95 | bzero(paths.sun_path,UNIX_PATH_MAX); 96 | memcpy(&paths.sun_path,path->d_name,pathlen); 97 | sendto(sockfd,buffer,n,0,(struct sockaddr *)&paths,sizeof(paths)); 98 | } closedir(root); 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/urcrecv.pyx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import time 4 | import pwd 5 | import sys 6 | import os 7 | 8 | LIMIT = float(open('env/LIMIT','rb').read().split('\n')[0]) if os.path.exists('env/LIMIT') else 1 9 | 10 | uid, gid = pwd.getpwnam('urcd')[2:4] 11 | os.chdir(sys.argv[1]) 12 | os.chroot(os.getcwd()) 13 | os.setgid(gid) 14 | os.setuid(uid) 15 | root = os.getcwd() 16 | del uid, gid 17 | 18 | sock=socket.socket(1,2) 19 | sock.setblocking(0) 20 | 21 | while 1: 22 | 23 | buffer = str() 24 | 25 | while 1: 26 | byte = os.read(0,1) 27 | if not byte: sys.exit(0) 28 | elif byte == '\n': 29 | buffer+=byte 30 | break 31 | elif len(buffer)<1024: buffer+=byte 32 | 33 | time.sleep(LIMIT) 34 | 35 | for path in os.listdir(root): 36 | try: sock.sendto(buffer,path) 37 | except: pass 38 | -------------------------------------------------------------------------------- /src/urcsend.c: -------------------------------------------------------------------------------- 1 | #define USAGE "Usage: urcsend /path/to/sockets/\n" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifndef UNIX_PATH_MAX 16 | #ifdef __NetBSD__ 17 | #define UNIX_PATH_MAX 104 18 | #else 19 | #define UNIX_PATH_MAX 108 20 | #endif 21 | #endif 22 | 23 | int itoa(char *s, int n, int slen) 24 | { 25 | if (snprintf(s,slen,"%d",n)<0) return -1; 26 | return 0; 27 | } 28 | 29 | main(int argc, char **argv) 30 | { 31 | 32 | if (argc<2) 33 | { 34 | write(2,USAGE,strlen(USAGE)); 35 | exit(64); 36 | } 37 | 38 | char buffer[1024] = {0}; 39 | char user[UNIX_PATH_MAX] = {0}; 40 | if (itoa(user,getpid(),UNIX_PATH_MAX)<0) exit(1); 41 | 42 | struct passwd *urcd = getpwnam("urcd"); 43 | 44 | if ((!urcd) 45 | || (chdir(argv[1])) 46 | || (chroot(argv[1])) 47 | || (setgroups(0,'\x00')) 48 | || (setgid(urcd->pw_gid)) 49 | || (setuid(urcd->pw_uid))) exit(64); 50 | 51 | int sockfd; 52 | struct sockaddr_un sock; 53 | bzero(&sock,sizeof(sock)); 54 | sock.sun_family = AF_UNIX; 55 | 56 | void sock_close(int signum) 57 | { 58 | unlink(sock.sun_path); 59 | exit(signum); 60 | } signal(SIGINT,sock_close); 61 | signal(SIGHUP,sock_close); 62 | signal(SIGTERM,sock_close); 63 | 64 | if ((sockfd=socket(AF_UNIX,SOCK_DGRAM,0))<0) exit(2); 65 | int n = 1; 66 | if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n))<0) exit(3); 67 | n = strlen(user); 68 | if (n > UNIX_PATH_MAX) exit(4); 69 | memcpy(&sock.sun_path,user,n); 70 | unlink(sock.sun_path); 71 | if (bind(sockfd,(struct sockaddr *)&sock,sizeof(sock))<0) exit(5); 72 | 73 | struct sockaddr_un path; 74 | path.sun_family = AF_UNIX; 75 | socklen_t path_len = sizeof(struct sockaddr_un); 76 | 77 | while (1) 78 | { 79 | bzero(path.sun_path,UNIX_PATH_MAX); 80 | n = recvfrom(sockfd,buffer,1024,0,(struct sockaddr *)&path,&path_len); 81 | if (!n) continue; 82 | if (n<0) sock_close(6); 83 | if (!path_len) continue; 84 | if (buffer[n-1] != '\n') continue; 85 | if (write(7,buffer,n)<0) sock_close(7); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/urcsend.pyx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import signal 4 | import pwd 5 | import sys 6 | import os 7 | 8 | fd = int(os.getenv('CURVECPCLIENT',7)) 9 | 10 | def sock_close(sn,sf): 11 | try: os.remove(str(os.getpid())) 12 | except: pass 13 | if sn: sys.exit(0) 14 | 15 | signal.signal(1 ,sock_close) 16 | signal.signal(2 ,sock_close) 17 | signal.signal(15,sock_close) 18 | 19 | uid, gid = pwd.getpwnam('urcd')[2:4] 20 | os.chdir(sys.argv[1]) 21 | os.chroot(os.getcwd()) 22 | os.setgid(gid) 23 | os.setuid(uid) 24 | root = os.getcwd() 25 | del uid, gid 26 | 27 | sock=socket.socket(1,2) 28 | sock_close(0,0) 29 | sock.bind(str(os.getpid())) 30 | 31 | while 1: 32 | 33 | buffer, path = sock.recvfrom(1024) 34 | if not path or buffer[len(buffer)-1:] != '\n': continue 35 | 36 | try: 37 | if not os.write(fd,buffer): sock_close(15,0) 38 | except: sock_close(15,0) 39 | -------------------------------------------------------------------------------- /src/urcstream.c: -------------------------------------------------------------------------------- 1 | #define USAGE "Usage: urcstream /path/to/sockets/\n" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifndef UNIX_PATH_MAX 16 | #ifdef __NetBSD__ 17 | #define UNIX_PATH_MAX 104 18 | #else 19 | #define UNIX_PATH_MAX 108 20 | #endif 21 | #endif 22 | 23 | int itoa(char *s, int n, int slen) 24 | { 25 | if (snprintf(s,slen,"%d",n)<0) return -1; 26 | return 0; 27 | } 28 | 29 | main(int argc, char **argv) 30 | { 31 | 32 | if (argc<2) 33 | { 34 | write(2,USAGE,strlen(USAGE)); 35 | exit(64); 36 | } 37 | 38 | int rd = 0, wr = 1; 39 | if (getenv("TCPCLIENT")){ rd = 6; wr = 7; } 40 | 41 | char buffer[1024] = {0}; 42 | char user[UNIX_PATH_MAX] = {0}; 43 | if (itoa(user,getpid(),UNIX_PATH_MAX)<0) exit(1); 44 | 45 | int n; 46 | float LIMIT; 47 | n = open("env/LIMIT",0); 48 | if (n>0) 49 | { 50 | if (read(n,buffer,1024)>0) LIMIT = atof(buffer); 51 | else LIMIT = 1.0; 52 | } else LIMIT = 1.0; 53 | close(n); 54 | 55 | struct passwd *urcd = getpwnam("urcd"); 56 | 57 | if ((!urcd) 58 | || (chdir(argv[1])) 59 | || (chroot(argv[1])) 60 | || (setgroups(0,'\x00')) 61 | || (setgid(urcd->pw_gid)) 62 | || (setuid(urcd->pw_uid))) exit(64); 63 | 64 | int sockfd; 65 | struct sockaddr_un sock; 66 | bzero(&sock,sizeof(sock)); 67 | sock.sun_family = AF_UNIX; 68 | 69 | void sock_close(int signum) 70 | { 71 | unlink(sock.sun_path); 72 | exit(signum); 73 | } signal(SIGINT,sock_close); 74 | signal(SIGHUP,sock_close); 75 | signal(SIGTERM,sock_close); 76 | 77 | if ((sockfd=socket(AF_UNIX,SOCK_DGRAM,0))<0) exit(2); 78 | n = 1; 79 | if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n))<0) exit(3); 80 | int userlen = strlen(user); 81 | if (userlen > UNIX_PATH_MAX) exit(4); 82 | memcpy(&sock.sun_path,user,userlen); 83 | unlink(sock.sun_path); 84 | if (bind(sockfd,(struct sockaddr *)&sock,sizeof(sock))<0) exit(5); 85 | 86 | struct pollfd fds[2]; 87 | fds[0].fd = rd; fds[0].events = POLLIN | POLLPRI; 88 | fds[1].fd = sockfd; fds[1].events = POLLIN; 89 | 90 | DIR *root; 91 | int pathlen; 92 | struct dirent *path; 93 | struct sockaddr_un paths; 94 | paths.sun_family = AF_UNIX; 95 | 96 | while (1) { 97 | 98 | poll(fds,2,-1); 99 | 100 | if (fds[0].revents) { 101 | 102 | usleep((int)(LIMIT*1000000)); 103 | 104 | for (n=0;n<1024;++n) 105 | { 106 | if (read(rd,buffer+n,1)<1) sock_close(6); 107 | if (buffer[n] == '\n') break; 108 | } if (buffer[n] != '\n') goto urcwrite; 109 | ++n; 110 | 111 | root = opendir("/"); 112 | if (!root) sock_close(7); 113 | while ((path = readdir(root))) 114 | { 115 | if (path->d_name[0] == '.') continue; 116 | pathlen = strlen(path->d_name); 117 | if (pathlen > UNIX_PATH_MAX) continue; 118 | if ((pathlen == userlen) && (!memcmp(path->d_name,user,userlen))) continue; 119 | bzero(paths.sun_path,UNIX_PATH_MAX); 120 | memcpy(&paths.sun_path,path->d_name,pathlen); 121 | sendto(sockfd,buffer,n,MSG_DONTWAIT,(struct sockaddr *)&paths,sizeof(paths)); 122 | } closedir(root); 123 | } 124 | 125 | urcwrite: while (poll(fds+1,1,0)) 126 | { 127 | n = read(sockfd,buffer,1024); 128 | if (!n) continue; 129 | if (n<0) sock_close(8); 130 | if (buffer[n-1] != '\n') continue; 131 | if (write(wr,buffer,n)<0) sock_close(9); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/urcstream.pyx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import socket 3 | import select 4 | import signal 5 | import time 6 | import pwd 7 | import sys 8 | import os 9 | 10 | user = str(os.getpid()) 11 | LIMIT = float(open('env/LIMIT','rb').read().split('\n')[0]) if os.path.exists('env/LIMIT') else 1 12 | 13 | wr = 1 14 | if int(os.getenv('TCPCLIENT',0)): 15 | wr += 6 16 | rd = wr - 1 17 | 18 | def sock_close(sn,sf): 19 | try: 20 | os.remove(str(os.getpid())) 21 | except: 22 | pass 23 | if sn: 24 | sys.exit(0) 25 | 26 | signal.signal(1 ,sock_close) 27 | signal.signal(2 ,sock_close) 28 | signal.signal(15,sock_close) 29 | 30 | uid, gid = pwd.getpwnam('urcd')[2:4] 31 | os.chdir(sys.argv[1]) 32 | os.chroot(os.getcwd()) 33 | os.setgid(gid) 34 | os.setuid(uid) 35 | root = os.getcwd() 36 | del uid, gid 37 | 38 | sock=socket.socket(1,2) 39 | sock_close(0,0) 40 | sock.bind(str(os.getpid())) 41 | sock.setblocking(0) 42 | sd=sock.fileno() 43 | 44 | client_POLLIN=select.poll() 45 | client_POLLIN.register(rd,3) 46 | 47 | server_POLLIN=select.poll() 48 | server_POLLIN.register(sd,3) 49 | 50 | now = time.time() 51 | def limit(): 52 | if ((time.time() - now) > LIMIT): 53 | global now 54 | now = time.time() 55 | return 0 56 | return 1 57 | 58 | def client_poll(): 59 | return len( client_POLLIN.poll(256- 60 | (256*len( server_POLLIN.poll(0))) 61 | )) 62 | 63 | def server_poll(): 64 | return len( server_POLLIN.poll(256- 65 | (256*len( client_POLLIN.poll(0))) 66 | )) 67 | 68 | while 1: 69 | if (client_poll() and limit()): 70 | 71 | buffer = str() 72 | 73 | while 1: 74 | byte = os.read(rd,1) 75 | if not byte: sock_close(15,0) 76 | elif byte == '\n': 77 | buffer+=byte 78 | break 79 | elif len(buffer)<1024: buffer+=byte 80 | 81 | for path in os.listdir(root): 82 | try: 83 | if path != user: 84 | sock.sendto(buffer,path) 85 | except: 86 | pass 87 | 88 | while server_poll(): 89 | buffer = os.read(sd,1024) 90 | if buffer[len(buffer)-1:] != '\n': continue 91 | try: 92 | if not os.write(wr,buffer): 93 | sock_close(15,0) 94 | except: 95 | sock_close(15,0) 96 | -------------------------------------------------------------------------------- /src/urcstream2hub.c: -------------------------------------------------------------------------------- 1 | #define USAGE "Usage: urcstream2hub /path/to/hub/sockets/ ./urcstream /path/to/sockets/\n" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #ifndef UNIX_PATH_MAX 17 | #ifdef __NetBSD__ 18 | #define UNIX_PATH_MAX 104 19 | #else 20 | #define UNIX_PATH_MAX 108 21 | #endif 22 | #endif 23 | 24 | int itoa(char *s, int n, int slen) 25 | { 26 | if (snprintf(s,slen,"%d",n)<0) return -1; 27 | return 0; 28 | } 29 | 30 | main(int argc, char **argv) 31 | { 32 | 33 | if (argc<4) 34 | { 35 | write(2,USAGE,strlen(USAGE)); 36 | exit(64); 37 | } 38 | 39 | int urcstream_pid; 40 | int urcstreamin[2], urcstreamout[2]; 41 | 42 | if ((pipe(urcstreamin)<0) || (pipe(urcstreamout)<0)) exit(1); 43 | urcstream_pid = fork(); 44 | if (!urcstream_pid) 45 | { 46 | close(0); 47 | close(1); 48 | dup(urcstreamin[0]); 49 | dup(urcstreamout[1]); 50 | close(urcstreamin[1]); 51 | close(urcstreamout[0]); 52 | execvp(argv[2],argv+2); 53 | } else { 54 | if (urcstream_pid<0) exit(2); 55 | } close(urcstreamin[0]); close(urcstreamout[1]); 56 | 57 | int devurandom = open("/dev/urandom",O_RDONLY); 58 | if (devurandom<0) exit(3); 59 | 60 | if (chdir(argv[1])) exit(64); 61 | struct passwd *urcd = getpwnam("urcd"); 62 | if ((!urcd) || ((chroot(argv[1])) || (setgroups(0,'\x00')) || (setgid(urcd->pw_gid)) || (setuid(urcd->pw_uid)))) exit(64); 63 | 64 | char user[UNIX_PATH_MAX] = {0}; 65 | if (itoa(user,getpid(),UNIX_PATH_MAX)<0) exit(4); 66 | 67 | int sockfd; 68 | struct sockaddr_un sock; 69 | bzero(&sock,sizeof(sock)); 70 | sock.sun_family = AF_UNIX; 71 | 72 | void sock_close(int signum) 73 | { 74 | unlink(sock.sun_path); 75 | exit(signum); 76 | } signal(SIGINT,sock_close); signal(SIGHUP,sock_close); signal(SIGTERM,sock_close); signal(SIGCHLD,sock_close); 77 | 78 | sockfd = socket(AF_UNIX,SOCK_DGRAM,0); 79 | if (sockfd<0) exit(5); 80 | int n = 1; 81 | if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n))<0) exit(6); 82 | int userlen = strlen(user); 83 | if (userlen > UNIX_PATH_MAX) exit(7); 84 | memcpy(&sock.sun_path,user,userlen+1); 85 | unlink(sock.sun_path); 86 | if (bind(sockfd,(struct sockaddr *)&sock,sizeof(sock.sun_family)+userlen)<0) exit(8); 87 | 88 | struct pollfd fds[2]; 89 | fds[0].fd = urcstreamout[0]; fds[0].events = POLLIN | POLLPRI; 90 | fds[1].fd = sockfd; fds[1].events = POLLIN; 91 | 92 | struct sockaddr_un hub; 93 | bzero(&hub,sizeof(hub)); 94 | hub.sun_family = AF_UNIX; 95 | memcpy(&hub.sun_path,"hub\0",4); 96 | 97 | unsigned char buffer[2+16+8+1024] = {0}; 98 | 99 | while (1) { 100 | 101 | poll(fds,2,-1); 102 | 103 | if (fds[0].revents) 104 | { 105 | for (n=0;n<1024;++n) 106 | { 107 | if (read(urcstreamout[0],buffer+2+16+8+n,1)<1) sock_close(9); 108 | if (buffer[2+16+8+n] == '\n') break; 109 | } if (buffer[2+16+8+n] != '\n') goto urcwrite; 110 | ++n; 111 | buffer[0] = n / 256; 112 | buffer[1] = n % 256; 113 | taia_now(buffer+2); 114 | taia_pack(buffer+2,buffer+2); 115 | if (read(devurandom,buffer+2+16,8)<8) sock_close(10); 116 | if (sendto(sockfd,buffer,2+16+8+n,MSG_DONTWAIT,(struct sockaddr *)&hub,sizeof(hub))<0) usleep(250000); 117 | } 118 | 119 | urcwrite: while (poll(fds+1,1,0)) 120 | { 121 | n = read(sockfd,buffer,2+16+8+1024); 122 | if (!n) continue; 123 | if (n<0) sock_close(11); 124 | if (buffer[n-1] != '\n') continue; 125 | if (n!=2+16+8+buffer[0]*256+buffer[1]) continue; 126 | if (write(urcstreamin[1],buffer+2+16+8,-2-16-8+n)<0) sock_close(12); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /stdin.cryptoserv: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | mkdir -p cryptoservroot/ 4 | mkdir -p cryptoservroot/urcsigndb/ 5 | mkdir -p cryptoservroot/urccryptoboxdir/ 6 | mkdir -p cryptoservroot/urccryptoboxpfs/ 7 | 8 | test -e cryptoservroot/.git/ || ( 9 | cd cryptoservroot/ 10 | git init 11 | ) 12 | 13 | echo "`pwd`"/cryptoservroot/urcsigndb > env/URCSIGNDB 14 | echo "`pwd`"/cryptoservroot/urccryptoboxdir > env/URCCRYPTOBOXDIR 15 | echo "`pwd`"/cryptoservroot/urccryptoboxpfs > env/URCCRYPTOBOXPFS 16 | 17 | chown urcd cryptoservroot/* 18 | 19 | # expiry cleanup (hackaround) 20 | for i in `ls cryptoservroot/urccryptoboxpfs/`; do 21 | # test -e cryptoservroot/urcsigndb/$i || rm -rf cryptoservroot/urccryptoboxpfs/$i 22 | test -e cryptoservroot/urccryptoboxdir/$i || rm -rf cryptoservroot/urccryptoboxpfs/$i 23 | done 24 | 25 | exec ./cryptoserv "`cat env/path`" "`pwd`"/cryptoservroot/ 26 | --------------------------------------------------------------------------------