diff options
author | EUcancER <root@euer.krebsco.de> | 2011-09-15 02:02:34 +0200 |
---|---|---|
committer | EUcancER <root@euer.krebsco.de> | 2011-09-15 02:02:34 +0200 |
commit | 095b22ab0c4b8ca7c6f33af2d1f75d3d82055455 (patch) | |
tree | a34afa0947b668fce2dc2b39fa1cfeac03386659 | |
parent | 88517b3edfc7b633d210422afb8579e5d0d3d1e0 (diff) | |
parent | 90be8b346c43da2b36c0b4872fcf1190cfaeaa85 (diff) |
Merge branch 'master' of github.com:krebscode/painload
-rw-r--r-- | .gitignore | 4 | ||||
-rwxr-xr-x | Reaktor/IRC/asybot.py | 197 | ||||
-rwxr-xr-x | Reaktor/IRC/bot.py | 34 | ||||
-rwxr-xr-x | Reaktor/IRC/bot2.py | 130 | ||||
-rw-r--r-- | Reaktor/IRC/content | 1 | ||||
-rwxr-xr-x | Reaktor/IRC/index | 4 | ||||
-rwxr-xr-x | Reaktor/IRC/install | 28 | ||||
-rw-r--r-- | Reaktor/README.md | 23 | ||||
-rwxr-xr-x | Reaktor/commands/reload | 2 | ||||
-rwxr-xr-x | Reaktor/index | 7 | ||||
-rwxr-xr-x | Reaktor/install | 6 | ||||
-rw-r--r-- | cholerab/reaktor/priviliged_functions | 24 | ||||
-rw-r--r-- | hyper/README.md | 15 | ||||
-rw-r--r-- | hyper/process/Makefile | 19 | ||||
-rw-r--r-- | hyper/process/main.go | 77 | ||||
-rw-r--r-- | hyper/process/src/hyper/process/Makefile | 11 | ||||
-rw-r--r-- | hyper/process/src/hyper/process/process.go | 132 | ||||
-rw-r--r-- | hyper/process/test/bc.json | 11 | ||||
-rw-r--r-- | hyper/sink/index.js | 13 | ||||
-rwxr-xr-x | punani/bin/punani | 224 | ||||
-rw-r--r-- | punani/doc/releases | 38 | ||||
-rwxr-xr-x | retiolum/bin/get-tinc-dir | 9 | ||||
-rw-r--r-- | retiolum/hosts/zerg | 10 | ||||
-rwxr-xr-x | retiolum/scripts/tinc_setup/install.sh | 1 |
24 files changed, 772 insertions, 248 deletions
@@ -1,4 +1,8 @@ +# go +_go_.8 +goinstall.log + # Linux kernel module modules.order Module.symvers diff --git a/Reaktor/IRC/asybot.py b/Reaktor/IRC/asybot.py new file mode 100755 index 00000000..99cb2fe6 --- /dev/null +++ b/Reaktor/IRC/asybot.py @@ -0,0 +1,197 @@ +#! /usr/bin/env python +# +# //Reaktor/IRC/asybot.py +# + +def is_executable(x): + import os + return os.path.exists(x) and os.access(x, os.X_OK) + +from asynchat import async_chat as asychat +from asyncore import loop +from socket import AF_INET, SOCK_STREAM +from signal import SIGALRM, signal, alarm +from datetime import datetime as date, timedelta +from sys import exit +from re import split, search + +import logging,logging.handlers +log = logging.getLogger('asybot') +hdlr = logging.handlers.SysLogHandler(facility=logging.handlers.SysLogHandler.LOG_DAEMON) +formatter = logging.Formatter( '%(filename)s: %(levelname)s: %(message)s') +hdlr.setFormatter(formatter) +log.addHandler(hdlr) + +class asybot(asychat): + def __init__(self, server, port, nickname, targets, **kwargs): + asychat.__init__(self) + self.server = server + self.port = port + self.nickname = nickname + self.targets = targets + self.username = kwargs['username'] if 'username' in kwargs else nickname + self.hostname = kwargs['hostname'] if 'hostname' in kwargs else nickname + self.ircname = kwargs['ircname'] if 'ircname' in kwargs else nickname + self.realname = kwargs['realname'] if 'realname' in kwargs else nickname + self.data = '' + self.set_terminator('\r\n') + self.create_socket(AF_INET, SOCK_STREAM) + self.connect((self.server, self.port)) + + # When we don't receive data for alarm_timeout seconds then issue a + # PING every hammer_interval seconds until kill_timeout seconds have + # passed without a message. Any incoming message will reset alarm. + self.alarm_timeout = 300 + self.hammer_interval = 10 + self.kill_timeout = 360 + signal(SIGALRM, lambda signum, frame: self.alarm_handler()) + self.reset_alarm() + + + def reset_alarm(self): + self.last_activity = date.now() + alarm(self.alarm_timeout) + + def alarm_handler(self): + delta = date.now() - self.last_activity + if delta > timedelta(seconds=self.kill_timeout): + log.error('No data for %s. Giving up...' % delta) + exit(2) + else: + log.error('No data for %s. PINGing server...' % delta) + self.push('PING :%s' % self.nickname) + alarm(self.hammer_interval) + + def collect_incoming_data(self, data): + self.data += data + + def found_terminator(self): + log.debug('<< %s' % self.data) + + message = self.data + self.data = '' + + _, prefix, command, params, rest, _ = \ + split('^(?::(\S+)\s)?(\S+)((?:\s[^:]\S*)*)(?:\s:(.*))?$', message) + params = params.split(' ')[1:] + #print([prefix, command, params, rest]) + + if command == 'PING': + self.push('PONG :%s' % rest) + log.info("Replying to servers PING with PONG :%s" %rest) + + elif command == 'PRIVMSG': + self.on_privmsg(prefix, command, params, rest) + + elif command == '433': + # ERR_NICKNAMEINUSE, retry with another name + _, nickname, int, _ = split('^.*[^0-9]([0-9]+)$', self.nickname) \ + if search('[0-9]$', self.nickname) \ + else ['', self.nickname, 0, ''] + self.nickname = nickname + str(int + 1) + self.handle_connect() + + self.reset_alarm() + + def push(self, message): + log.debug('>> %s' % message) + asychat.push(self, message + self.get_terminator()) + + def handle_connect(self): + self.push('NICK %s' % self.nickname) + self.push('USER %s %s %s :%s' % + (self.username, self.hostname, self.server, self.realname)) + self.push('JOIN %s' % ','.join(self.targets)) + + def on_privmsg(self, prefix, command, params, rest): + def PRIVMSG(text): + msg = 'PRIVMSG %s :%s' % (','.join(params), text) + self.push(msg) + + def ME(text): + PRIVMSG('ACTION ' + text + '') + + _from = prefix.split('!', 1)[0] + + try: + _, _handle, _command, _argument, _ = split( + '^(\w+|\*):\s*(\w+)(?:\s+(.*))?$', rest) + except ValueError, error: + if search(self.nickname, rest): + PRIVMSG('I\'m so famous') + return # ignore + + if _handle == self.nickname or _handle == '*': + + from os.path import realpath, dirname, join + from subprocess import Popen as popen, PIPE + + Reaktor_dir = dirname(realpath(dirname(__file__))) + public_commands = join(Reaktor_dir, 'public_commands') + command = join(public_commands, _command) + + if is_executable(command): + + env = {} + if _argument != None: + env['argument'] = _argument + + try: + p = popen([command], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + except OSError, error: + ME('brain damaged') + log.error('OSError@%s: %s' % (command, error)) + return + + stdout, stderr = [ x[:len(x)-1] for x in + [ x.split('\n') for x in p.communicate()]] + code = p.returncode + pid = p.pid + + log.info('command: %s -> %s' % (command, code)) + [log.debug('%s stdout: %s' % (pid, x)) for x in stdout] + [log.debug('%s stderr: %s' % (pid, x)) for x in stderr] + + if code == 0: + [PRIVMSG(x) for x in stdout] + [PRIVMSG(x) for x in stderr] + else: + ME('mimimi') + + else: + if _handle != '*': + PRIVMSG(_from + ': you are made of stupid') + + +# retrieve the value of a [singleton] variable from a tinc.conf(5)-like file +def getconf1(x, path): + from re import findall + pattern = '(?:^|\n)\s*' + x + '\s*=\s*(.*\w)\s*(?:\n|$)' + y = findall(pattern, open(path, 'r').read()) + if len(y) < 1: + raise AttributeError("len(getconf1('%s', '%s') < 1)" % (x, path)) + if len(y) > 1: + y = ' '.join(y) + raise AttributeError("len(getconf1('%s', '%s') > 1)\n ====> %s" + % (x, path, y)) + return y[0] + +if __name__ == "__main__": + from os import environ as env + + lol = logging.DEBUG if env.get('debug',False) else logging.INFO + logging.basicConfig(level=lol) + name = getconf1('Name', '/etc/tinc/retiolum/tinc.conf') + hostname = '%s.retiolum' % name + nick = str(env.get('nick', name)) + host = str(env.get('host', 'supernode')) + port = int(env.get('port', 6667)) + target = str(env.get('target', '#retiolum')) + log.info('=> irc://%s@%s:%s/%s' % (nick, host, port, target)) + + from getpass import getuser + asybot(host, port, nick, [target], username=getuser(), + ircname='//Reaktor running at %s' % hostname, + hostname=hostname) + + loop() diff --git a/Reaktor/IRC/bot.py b/Reaktor/IRC/bot.py deleted file mode 100755 index af974f4e..00000000 --- a/Reaktor/IRC/bot.py +++ /dev/null @@ -1,34 +0,0 @@ -#! /usr/bin/env python2 - -from irclib import IRC, ServerConnectionError, is_channel -from sys import exit -from os import environ as env - -host = str(env.get('host', 'irc.freenode.org')) -port = int(env.get('port', 6667)) -nick = str(env.get('nick', 'crabspasm')) -channel = str(env.get('channel', '#tincspasm')) -print '====> irc://%s@%s:%s/%s' % (nick, host, port, channel) - -irc = IRC() -try: - client = irc.server().connect(host, port, nick) -except ServerConnectionError, error: - print error - exit - -def on_connect(connection, event): - connection.join(channel) - print 'Es passiert...' - -def on_join(connection, event): - connection.privmsg(channel, 'lol') - -def on_disconnect(connection, event): - exit - -client.add_global_handler('welcome', on_connect) -client.add_global_handler('join', on_join) -client.add_global_handler('disconnect', on_disconnect) - -irc.process_forever() diff --git a/Reaktor/IRC/bot2.py b/Reaktor/IRC/bot2.py deleted file mode 100755 index 326dd8f5..00000000 --- a/Reaktor/IRC/bot2.py +++ /dev/null @@ -1,130 +0,0 @@ -#! /usr/bin/env python -# -# //Reaktor/IRC/bot2.py -# - -from __future__ import print_function -from irclib import SimpleIRCClient, ServerConnectionError, is_channel -from sys import exit -from os import environ as env -import re - -class IRCBot(SimpleIRCClient): - def __init__(self, target): - SimpleIRCClient.__init__(self) - self.target = target - - def on_pubmsg(self, connection, event): - - def PRIVMSG(target, text): - self.connection.privmsg(target, text) - - def ME(target, text): - PRIVMSG(target, 'ACTION ' + text + '') - - def is_executable(x): - import os - return os.path.exists(x) and os.access(x, os.X_OK) - - _nickname = connection.get_nickname() - _source = event.source() - _from = _source.split('!', 1)[0] - _target = event.target() - - try: - _, _handle, _command, _argument, _ = re.split( - '^(\w+|\*):\s*(\w+)(?:\s+(.*))?$', event.arguments()[0]) - except ValueError, error: - if re.search(_nickname, event.arguments()[0]): - PRIVMSG(self.target, 'I\'m so famous') - return # ignore - - if _handle == _nickname or _handle == '*': - - from os.path import realpath, dirname, join - from subprocess import Popen as popen, PIPE - - Reaktor_dir = dirname(realpath(dirname(__file__))) - public_commands = join(Reaktor_dir, 'public_commands') - command = join(public_commands, _command) - - if is_executable(command): - - env = {} - if _argument != None: - env['argument'] = _argument - - try: - p = popen([command], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) - except OSError, error: - ME(self.target, 'is made of stupid') - print('OSError@%s: %s' % (command, error)) - return - - stdout, stderr = [ x[:len(x)-1] for x in - [ x.split('\n') for x in p.communicate()]] - code = p.returncode - pid = p.pid - - print('command: %s -> %s' % (command, code)) - [print('%s stdout: %s' % (pid, x)) for x in stdout] - [print('%s stderr: %s' % (pid, x)) for x in stderr] - - if code == 0: - [PRIVMSG(self.target, x) for x in stdout] - [PRIVMSG(_source, x) for x in stderr] - else: - ME(self.target, 'mimimi') - - else: - if _handle != '*': - PRIVMSG(self.target, _from + ': you are made of stupid') - - def on_welcome(self, connection, event): - print('I\'m welcome! :D joining to %s now...' % (self.target)) - if is_channel(self.target): - connection.join(self.target) - else: - self.connection.privmsg(self.target, 'lol') - self.connection.quit('Pong timeout: 423 seconds') - - def on_join(self, connection, event): - print('Es passiert in %s' % (self.target)) - - def on_disconnect(self, connection, event): - # TODO reconnect - exit(0) - -# retrieve the value of a [singleton] variable from a tinc.conf(5)-like file -def getconf1(x, path): - from re import findall - pattern = '(?:^|\n)\s*' + x + '\s*=\s*(.*\w)\s*(?:\n|$)' - y = findall(pattern, open(path, 'r').read()) - if len(y) < 1: - raise AttributeError("len(getconf1('%s', '%s') < 1)" % (x, path)) - if len(y) > 1: - y = ' '.join(y) - raise AttributeError("len(getconf1('%s', '%s') > 1)\n ====> %s" - % (x, path, y)) - return y[0] - -def main(): - name = getconf1('Name', '/etc/tinc/retiolum/tinc.conf') - nick = str(env.get('nick', name)) - host = str(env.get('host', 'supernode')) - port = int(env.get('port', 6667)) - target = str(env.get('target', '#retiolum')) - print('====> irc://%s@%s:%s/%s' % (nick, host, port, target)) - - client = IRCBot(target) - try: - from getpass import getuser - client.connect(host, port, nick, username=getuser(), - ircname='//Reaktor running at %s.retiolum' % (name)) - except ServerConnectionError, error: - print(error) - exit(1) - client.start() - -if __name__ == "__main__": - main() diff --git a/Reaktor/IRC/content b/Reaktor/IRC/content deleted file mode 100644 index e0292376..00000000 --- a/Reaktor/IRC/content +++ /dev/null @@ -1 +0,0 @@ -python-irclib-0.4.6/ircbot.py diff --git a/Reaktor/IRC/index b/Reaktor/IRC/index index 68b6cf33..24982c76 100755 --- a/Reaktor/IRC/index +++ b/Reaktor/IRC/index @@ -4,6 +4,4 @@ set -xeuf # cd //Reaktor cd $(dirname $(readlink -f $0))/.. -IRC/install - -exec python IRC/bot2.py "$@" +exec python IRC/asybot.py "$@" diff --git a/Reaktor/IRC/install b/Reaktor/IRC/install deleted file mode 100755 index d5f7a8c1..00000000 --- a/Reaktor/IRC/install +++ /dev/null @@ -1,28 +0,0 @@ -#! /bin/sh -set -xeuf - -# cd //Reaktor/IRC -cd $(dirname $(readlink -f $0)) - -# install irclib.py -{ - PV=0.4.6 - PN=python-irclib - P=$PN-$PV - tarball=$P.tar.gz - URL=http://downloads.sourceforge.net/$PN/$tarball - SHA1SUM=c6271e44293ed51c21af0f44ce106667d3006e6f - - file=irclib.py - - if ! echo "$SHA1SUM $file" | sha1sum -c; then - temp=`mktemp` - trap "rm -f $temp" EXIT INT - - echo $P/$file > $temp - curl -LfsS $URL | tar --strip-components=1 -zxT $temp - fi - echo "$SHA1SUM $file" | sha1sum -c -} - - diff --git a/Reaktor/README.md b/Reaktor/README.md index 05af8ef5..a581c6bd 100644 --- a/Reaktor/README.md +++ b/Reaktor/README.md @@ -2,28 +2,25 @@ ## Quickstart - ## 1. prepare Reaktor - //Reaktor/install + ## 1. create a dedicated user + useradd reaktor - ## 2. create a dedicated user - useradd Reaktor + ## 2. marry Reaktor with /sbin/init - ## 3. marry Reaktor with /sbin/init - - ## 3a. /etc/inittab-like foo - echo 10:2345:respawn:/bin/su Reaktor -c /krebs/Reaktor/index >>/etc/inittab - # or 10:2345:respawn:/usr/bin/sudo -u Reaktor /krebs/Reaktor/index - # if Reaktor's shell is /bin/false or similar - # [check with e.g getent passwd Reaktor] + ## 2a. /etc/inittab-like foo + echo 10:2345:respawn:/bin/su reaktor -c /krebs/Reaktor/index >>/etc/inittab + # or 10:2345:respawn:/usr/bin/sudo -u reaktor /krebs/Reaktor/index + # if reaktor's shell is /bin/false or similar + # [check with e.g getent passwd reaktor] telinit q - ## 3b. upstart-like foo + ## 2b. upstart-like foo cat > /etc/init/Reaktor.conf <<EOF description "Krebs Reaktor" author "The Ministerium" stop on runlevel [016] respawn - exec /usr/bin/sudo -u Reaktor /krebs/Reaktor/index + exec /usr/bin/sudo -u reaktor /krebs/Reaktor/index EOF start Reaktor diff --git a/Reaktor/commands/reload b/Reaktor/commands/reload index 2b78b178..bfa1f041 100755 --- a/Reaktor/commands/reload +++ b/Reaktor/commands/reload @@ -1,2 +1,2 @@ #! /bin/sh -exec pkill -U Reaktor +exec pkill -U reaktor diff --git a/Reaktor/index b/Reaktor/index index ac647ca3..05827373 100755 --- a/Reaktor/index +++ b/Reaktor/index @@ -4,4 +4,11 @@ set -euf # cd //Reaktor cd $(dirname $(readlink -f $0)) +# redirect stdout [and stderr] to syslog +stdout=`mktemp -u` +mkfifo $stdout +trap "rm -vf $stdout" EXIT INT +exec 1<>$stdout 2>&1 +logger -t Reaktor -f $stdout & + exec IRC/index diff --git a/Reaktor/install b/Reaktor/install deleted file mode 100755 index 761bc437..00000000 --- a/Reaktor/install +++ /dev/null @@ -1,6 +0,0 @@ -#! /bin/sh -set -euf - -cd $(dirname $(readlink -f $0)) - -exec IRC/install diff --git a/cholerab/reaktor/priviliged_functions b/cholerab/reaktor/priviliged_functions new file mode 100644 index 00000000..a673267e --- /dev/null +++ b/cholerab/reaktor/priviliged_functions @@ -0,0 +1,24 @@ +Use Case 1: Request update on Host +================================= + +< user> bot: update +< bot> /whois user +< bot> /msg user [CHALLENGE] +< user> /msg bot [CHALLENGE-RESPONSE] +< bot> updating... +< bot> now on rev XXXXX + +Command Flow +---------------- +The bot has a locally stored list of [trusted] hosts along with their public +key, preferably from the tinc/retiolum directory. + +The bot encrypts a 1K Byte long message with the public key of the host +retrieved by the /whois command. + +This challenge is sent to the user requesting the command via private message. +The user then decrpyts the message with its own private key and sends the +decrpyted message to the bot. + +The bot then executes the requested command if the challenge is answered +correctly diff --git a/hyper/README.md b/hyper/README.md new file mode 100644 index 00000000..07fa1de5 --- /dev/null +++ b/hyper/README.md @@ -0,0 +1,15 @@ +# Overview + +## start conductor on port 8888 and sink on 1337 + + //hyper/process/main + //bin/node //hyper/sink + +## create bc process and retrieve it's process id (AKA {path}) + + url=http://localhost:8888 + curl -fvsS --data-binary @//hyper/process/test/bc.json $url/proc + +## send data for calculation + + echo 9000+2^42 | curl -fvsS --data-binary @- $url/{path} diff --git a/hyper/process/Makefile b/hyper/process/Makefile new file mode 100644 index 00000000..bbc1c2fb --- /dev/null +++ b/hyper/process/Makefile @@ -0,0 +1,19 @@ +include $(GOROOT)/src/Make.inc + +GCIMPORTS = -I pkg/$(GOOS)_$(GOARCH) +LDIMPORTS = -L pkg/$(GOOS)_$(GOARCH) + +TARG=main +GOFILES=\ + main.go\ + +include $(GOROOT)/src/Make.cmd + +export GOPATH := $(PWD) +.PHONY: prepare +prepare: + #goinstall -v github.com/garyburd/twister/server + goinstall -v gorilla.googlecode.com/hg/gorilla/mux + goinstall -v $(PWD)/src/hyper/process + +_go_.$O: prepare diff --git a/hyper/process/main.go b/hyper/process/main.go new file mode 100644 index 00000000..5420f681 --- /dev/null +++ b/hyper/process/main.go @@ -0,0 +1,77 @@ +package main + +import "json" +import "log" +import "http" +import "gorilla.googlecode.com/hg/gorilla/mux" +import "os" +import "fmt" +import "bytes" + +import "hyper/process" + +var proc = map[string] *hyper.Process{} + +// TODO Retrieve Process, Write, Kill [autokill], get exit code + +func RespondJSON(res http.ResponseWriter, v interface{}) os.Error { + content, err := json.Marshal(v) + if err == nil { + log.Printf("< %s", content) + res.Header().Set("Content-Type", "application/json; charset=\"utf-8\"") + res.WriteHeader(http.StatusOK) + res.Write(content) + } else { + log.Printf("%s while json.Marshal(%s)", err, v) + } + return err +} + +func CreateProcessHandler(res http.ResponseWriter, req *http.Request) { + if p, err := hyper.NewProcess(req); err == nil { + id := p.Id() + proc[id] = p + RespondJSON(res, &map[string]string{ + "path": fmt.Sprintf("/proc/%s", id), + }) + } else { + log.Printf("%s", err) + res.WriteHeader(http.StatusInternalServerError) + } +} + +func RetrieveProcess(res http.ResponseWriter, req *http.Request) { + if p := proc[mux.Vars(req)["id"]]; p != nil { + RespondJSON(res, p) + } else { + res.WriteHeader(http.StatusNotFound) + } +} + +func FeedProcess(res http.ResponseWriter, req *http.Request) { + if p := proc[mux.Vars(req)["id"]]; p != nil { + body := make([]byte, 4096) + if _, err := req.Body.Read(body); err == nil { + body = bytes.TrimRight(body, string([]byte{0})) + p.Write(body) + //if err := p.Write(body); err == nil { + RespondJSON(res, true) + //} + } + } else { + res.WriteHeader(http.StatusNotFound) + } +} + +func main() { + + // Gorilla + mux.HandleFunc("/proc", CreateProcessHandler).Methods("POST") + mux.HandleFunc("/proc/{id}", RetrieveProcess).Methods("GET") + mux.HandleFunc("/proc/{id}", FeedProcess).Methods("POST") + + err := http.ListenAndServe("0.0.0.0:8888", mux.DefaultRouter) + if err != nil { + log.Fatal("ListenAndServe: ", err.String()) + } +} diff --git a/hyper/process/src/hyper/process/Makefile b/hyper/process/src/hyper/process/Makefile new file mode 100644 index 00000000..7ecda716 --- /dev/null +++ b/hyper/process/src/hyper/process/Makefile @@ -0,0 +1,11 @@ +include ${GOROOT}/src/Make.inc + +TARG=hyper/process + +GOFILES=\ + process.go\ + +#DEPS=\ +# gorilla.googlecode.com/hg/gorilla/context\ + +include ${GOROOT}/src/Make.pkg diff --git a/hyper/process/src/hyper/process/process.go b/hyper/process/src/hyper/process/process.go new file mode 100644 index 00000000..18cf55fb --- /dev/null +++ b/hyper/process/src/hyper/process/process.go @@ -0,0 +1,132 @@ +package hyper + +import "fmt" +import "http" +import "bytes" +import "json" +import "os" + +type Process struct { + Path string `json:"path"` + Argv []string `json:"argv"` + Envp map[string]string `json:"envp"` + //Stdin string `json:"stdin"` + Stdout string `json:"stdout"` + Stderr string `json:"stderr"` + process *os.Process + process_stdin *os.File + process_stdout *os.File + process_stderr *os.File + id string + client http.Client +} + +func (p *Process) Id() string { + return p.id +} + +func NewProcess(req *http.Request) (*Process, os.Error) { + body := make([]byte, 4096) + _, err := req.Body.Read(body) + if err != nil { + return nil, err + } + + body = bytes.TrimRight(body, string([]byte{0})) + + var p Process + + if err := json.Unmarshal(body, &p); err != nil { + return nil, err + } + + p.id = gensym() + + if err := p.Start(); err != nil { + return nil, err + } + + return &p, nil +} + +func (hp *Process) Write(b []byte) { + n, err := hp.process_stdin.Write(b) + if err != nil { + fmt.Printf("Write: %s\n", err) + } else { + fmt.Printf("Wrote: %d bytes\n", n) + } +} + +func (hp *Process) Start() os.Error { + var name = hp.Path //os.Args[1] //"/usr/b" + var argv = hp.Argv //os.Args[1:] //[]string{ "bc" } + //var chroot = false + //var dir = "/var/empty" + var files [3][2]*os.File + var err os.Error + + for i, _ := range files { + files[i][0], files[i][1], err = os.Pipe() + if err != nil { + return err + } + } + + var env []string + for k, v := range hp.Envp { + env = append(env, fmt.Sprintf("%s=%s", k, v)) + } + + var attr = &os.ProcAttr{ + //Dir: dir, + Env: env, //os.Environ(), + Files: []*os.File{ files[0][0], files[1][1], files[2][1]}, + } + + //var foo, _ = json.Marshal(attr) + //fmt.Printf("%s\n", foo) + + hp.process, err = os.StartProcess(name, argv, attr) + if err != nil { + return err + } + + hp.process_stdin = files[0][1] + hp.process_stdout = files[1][0] + hp.process_stderr = files[2][0] + + for _, file := range attr.Files { + file.Close() + } + + go hp.reader(hp.process_stdout, hp.Stdout) + go hp.reader(hp.process_stderr, hp.Stderr) + return nil +} + +func (p *Process) reader(file *os.File, url string) { + var b []byte = make([]byte, 1024) + var err os.Error = nil + for err == nil { + var n int + n, err = file.Read(b) + fmt.Printf("data: %d, %s\n", n, b) + + res, err := p.client.Post(url, "application/octet-stream", bytes.NewBuffer(b)) + res = res + if err != nil { + fmt.Printf("EE: %s: %s\n", url, err) + } + } +} + +func gensym() string { + f, _ := os.Open("/dev/urandom") + b := make([]byte, 16) + f.Read(b) + f.Close() + uuid := fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) + return uuid +} + diff --git a/hyper/process/test/bc.json b/hyper/process/test/bc.json new file mode 100644 index 00000000..5b3b0721 --- /dev/null +++ b/hyper/process/test/bc.json @@ -0,0 +1,11 @@ +{ + "path": "/usr/bin/bc", + "argv": [ + "bc" + ], + "envp": { + "was": "geht" + }, + "stdout": "http://127.0.0.1:1337/", + "stderr": "http://127.0.0.1:1337/" +} diff --git a/hyper/sink/index.js b/hyper/sink/index.js new file mode 100644 index 00000000..b556b88d --- /dev/null +++ b/hyper/sink/index.js @@ -0,0 +1,13 @@ +require('http').createServer(function (req, res) { + + req.on('data', function (data) { + require('util').puts(data); + }); + + req.on('end', function () { + res.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': 0}); + res.end(); + }); +}).listen(1337, '127.0.0.1', function () { + console.log('Running HyperSink at http://127.0.0.1:1337/'); +}); diff --git a/punani/bin/punani b/punani/bin/punani index 7af6f0f8..d118b13c 100755 --- a/punani/bin/punani +++ b/punani/bin/punani @@ -6,33 +6,150 @@ # -E -i spec insert a package to the target filesystem # -E -r spec remove a package # - +set -euf godmode() { if test "${nosudo-false}" != true -a `id -u` != 0; then - echo "Warning: we require god mode..." >&2 + echo "!! we require god mode..." >&2 exec sudo "$0" "$@" exit 23 # go to hell fi } -if pacman --version 2>/dev/null | fgrep -q Pacman; then - system="${system+$system, }arch-like" -fi +# return the 'system' variable +# currently be: +# arch-like +# debian-like +guess_system() +{ + if [ -f "/etc/arch-release" ] ;then + system="${system+$system, }arch-like" + fi + if [ -f "/etc/lsb-release" -o -f "/etc/debian_version" ] ;then + system="${system+$system, }debian-like" + fi + +} +arch_aur_helper() +{ + # pacman is the last fallback helper + manager="yaourt clyde packer bauerbill tupac pacaur paktahn pbfetch aurget aurora cower powaur pacman" + for i in $manager;do + mgr=`which $i` + if [ "$mgr" ] ;then + echo $mgr + return 0 + fi + done + echo "!! no helper found, this should never happen(tm)." + return 1 +} +handle_system () { + case "$system" in + (*arch-like*) + # dryrun + # TODO dryrun not dry enough for aur helper + if [ "${dryrun-}" ];then + pacman () { echo "pacman $@" ; } + pkgfile () { echo "pkgfile $@"; } + yaourt () { echo "yaourt $@" ; } + fi + + # get dependencies : + # we need pkgfile + if ! [ `which pkgfile` ] ; then + pacman -S --noconfirm pkgtools + pkgfile -u + fi + punani_Scientist_update() { + pacman -Sy + pkgtool -u + } + punani_Scientist_search() { + pkgfile $1 + if [ "${hard-}" ] ; then + mgr=`arch_aur_helper` + $mgr -Ss $1 + fi + + } -case "$system" in - (*arch-like*) - punani_Engineer_insert() { - pacman -Sy "$1" - } - punani_Engineer_remove() { - pacman -Rcs "$1" - } - ;; - (*) - email='krebs@syntax-fehler.de' - irc_host='irc.freenode.org' - irc_channel='#tincspasm' - cat>&2<<EOF + punani_Engineer_insert() { + # punani under archlinux first tries to load the packages with the given file name + # it needs pkgfile for that + # + # when trying harder it tries to load the package with the given name directly via yaourt + echo "** trying to find package with given file" + if pacman -S `pkgfile $1` 2>/dev/null; then + echo "++ finished" + exit 0 + else + echo "!! nothing found in base repos" + if [ "${hard-}" ] ; then + echo "** trying harder" + echo "** trying yaourt directly with given package" + mgr=`arch_aur_helper` + if $mgr -S $1 ;then + echo "++ finished" + return 0 + else + echo "!! giving up...i am sorry" + return 1 + fi |