#!/bin/akanga -p
#



fn debug {
	if (~ $debug yes) {
		echo $* >[1=2]
		}

	return 0
	}

#
# readresponse <expect> <exitcode>
#
fn readresponse {
	read resp data line
	debug '>>>' $resp $data $line

	if (! ~ $resp $1) {
		echo error: $resp $data $line >[1=2]
		if (! ~ $2 0)
			exit $2

		return 1
		}
	
	return 0
	}

#
# putline <line>
#
fn putline {
	if (~ $debug yes)
		echo '<<<' $* >[1=2]

	echo $*  ||  {
		echo remote side closed the connection >[1=2]
		exit 1
		}

	return 0
	}


fn sendblock {
	putline +DATA
	des -3 -ehk $key <$1 | mimencode
	echo .

	readresponse +OK 2
	return 0
	}

fn receiveblock {
	readresponse +DATA 2
	{ while (read line  &&  ! ~ $line .) {
		echo $line
		}
	  } | mimencode -u | des -3 -d -hk $key >$1
	
	putline +OK
	}



config = /usr/local/cmsg/etc/server.conf
debug = no
execpath = /usr/local/cmsg/bin


parseopt '*' c:d $*  ||  exit 1
while (~ $1 -*) {
	switch ($1) {
	case -c
		configfile = $2
		shift 2
	
	case -d
		debug = yes
		shift

	case - --
		shift
		break
	
	case *
		echo $0: unknown option: $1 >[1=2]
		exit 1
		}
	}


let 'perm = stat("-p", config)'
if (! ~ $perm 0600) {
	chmod 000 $config
	echo $0: wrong permission on configuration $config: $perm >[1=2]
	exit 1
	}

#
# Serial berechnen und ausgeben.
#
serial = `{ date +'%s' } ^ : ^ $pid
putline +OK $serial



#
# Passwort einlesen
#
read -n inp
debug '>>>' $inp
if (! ~ $inp(1) +PASSWD) {
	echo -ERR bad login
	echo missing or bad password from client: $SOCKETD_CLIENT >[1=2]
	exit 1
	}

if (~ $#inp 2)			# +PASSWD <password>
	inp = ($inp(1) $SOCKETD_CLIENT $inp(2))

if (! ~ $#inp 3) {
	echo -ERR bad login
	echo protocol violation on +PASSWD >[1=2]
	exit 1
	}


#
# Konfiguration der Gegenstelle, bzw. des Benutzers, lesen
#
initvars '' client.key client.passwd client.permit config.des
readconf client. $config $inp(2)
if (~ $(client.key) ''  ||  ~ $(client.passwd) '') {
	echo -ERR bad login
	echo $0: no client configuration: $SOCKETD_CLIENT >[1=2]
	exit 1
	}

#
# Schluessel fuer Session berechnen ...
#
key = `{ echo $serial ^ : ^ $(client.key) | md5sum | awk '{ print $1 }' }
passwd = `{ echo $(client.passwd) ^ : ^ $serial | md5sum | awk '{ print $1 }' }

#
# ... und Passwort vergleichen.
#
if (! ~ $inp(3) $passwd) {
	echo -ERR bad login
	echo $0: bad password: $SOCKETD_CLIENT/$inp(2) >[1=2]
	exit 1
	}


#
# Ok, Benutzer/Gegenstelle wurde verifiziert.
#
putline +OK



if (~ $(config.des) '')
	config.des = (des -3)




#
# Clientdaten empfangen und entschluesseln ...
#
mktemp decrypted out
if (! receiveblock $decrypted) {
	echo $0: decryption error >[1=2]
	exit 1
	}

##cat $decrypted >[1=2]


{ if (! read header message  ||  ! ~ $header message:) {
	echo $0: no messagetype: $SOCKETD_CLIENT >[1=2]
	exit 1
  } else if (! read line  ||  ! ~ $line '') {
	echo $0: header error: $SOCKETD_CLIENT >[1=2]
	exit 1
  } else {
	cmd = `{ echo $message }
	if (~ $#cmd 0  ||  ~ $cmd(1) echo) {
		read - | cat -
	} else if (~ $cmd(1) */* *.*) {
		echo -ERR not processed
		exit 1
	} else if (! ~ $(client.permit) ''  &&  ! ~ $cmd(1) `{ echo $(client.permit) } ) {
		echo -ERR not processed
		exit 1
	} else {
		let 'cmd[1] = execpath ^ "/" ^ cmd[1]'
		if (let 'test("-x", cmd[1]) == 0') {
			echo -ERR not processed
			exit 1
			}
			
		read - | $cmd
		}
  	}
  } <$decrypted >$out

sendblock $out
exit 0

