@@ -0,0 +1,7 @@
# Change to "yes" to run the service.
RUN_DAEMON="no"

# Uncomment this to log potentially sensitive information from your users.
# This may be useful for debugging or diagnosing functional problems, but
# should be avoided in a high-risk environment.
#UNSAFE_LOGGING="yes"
@@ -0,0 +1,11 @@
# Change to "yes" to run the service.
RUN_DAEMON="no"

# Uncomment this to log potentially sensitive information from your users.
# This may be useful for debugging or diagnosing functional problems, but
# should be avoided in a high-risk environment.
#UNSAFE_LOGGING="yes"

# Set the port for this service to listen on.
# If not set, uses the default (9003).
#PORT=9003
@@ -1,31 +1,33 @@
These are instructions for how to set up a Google App Engine application
to run at appspot.com.
for the appspot rendezvous method (flashproxy-reg-appspot). It requires
the HTTP rendezvous to be available, so you should set that up first and
ensure it is working correctly, or find someone else's to use. If you
choose the latter, note that it is *their* reg-daemon.pub that your users
must give to flashproxy-reg-appspot.

General links:
https://developers.google.com/appengine/
https://developers.google.com/appengine/docs/whatisgoogleappengine
https://developers.google.com/appengine/docs/go/gettingstarted/

You first need to create a Google account. See gmail-howto.txt for how
You first need to create a Google account. See email-howto.txt for how
to do that.

Download the SDK:
https://developers.google.com/appengine/docs/go/gettingstarted/devenvironment

Write your program and app.yaml file:
https://developers.google.com/appengine/docs/go/gettingstarted/helloworld
Find your facilitator appengine installation, probably in reg-appspot/
in your flashproxy config dir. Edit config.go to point to the address of
the HTTP facilitator.

When you're ready to upload, log in with your Google account and follow
the directions:
https://appengine.google.com/
Follow the directions to register a new application:
https://developers.google.com/appengine/docs/go/gettingstarted/uploading

Enter an application ID and create the application.

Use the appcfg.py program to upload the program. It should look
something like this:

$ torify ./google_appengine/appcfg.py update myapp/
$ torify ./google_appengine/appcfg.py -A <YOUR_APP_ID> update reg-appspot/
07:25 PM Host: appengine.google.com
07:25 PM Application: application-id; version: 1
07:25 PM
@@ -1,6 +1,21 @@
These are instructions for setting up a Gmail account for use with the
email-based rendezvous and flashproxy-reg-email. These instructions were
current as of May 2013.
These are instructions for setting up an email account for use with the
email-based rendezvous (facilitator-email-poller / flashproxy-reg-email).

You are strongly advised to use an email account dedicated for this
purpose. If your email provider supports it, we advise you to use an
app-specific password rather than your account password.

Once you have an email address and the password for it, you should add
this information to reg-email.pass in your flashproxy config directory.
For your security, this file should be on encrypted storage.

The following section provides some instructions on how to set up a new
Google account whilst revealing as little information to Google as is
feasible.

== Creating a Google account securely

These instructions were current as of May 2013.

You may have trouble if you are using Tor to create the account, for two
reasons. The first is that exit nodes are a source of abuse and Google
@@ -57,5 +72,4 @@ https://www.google.com/accounts/SmsAuthConfig.

Still on the 2-step summary page, click "Manage application-specific
passwords". Enter "IMAP" for the name and click "Generate password".
Save the password to encrypted storage. This is the password that will
be used with the --pass option of facilitator-email-poller.
Now store this in reg-email.pass, as mentioned in the introduction.
@@ -0,0 +1,44 @@
The main facilitator program is a backend server that is essentially a
dynamic database of client addresses, as well as helper programs that
receive client registrations from the Internet over various means and
pass them to the backend. There are three supported helper rendezvous
methods: HTTP, email, and appspot.

facilitator-reg is a simple program that forwards its standard input to
a locally running facilitator-reg-daemon process. It is not used by the
other components, but is useful for debugging and test purposes.

facilitator-reg-daemon accepts connections containing encrypted client
registrations and forwards them to the facilitator. It exists as a
process of its own so that only one program requires access to the
facilitator's private key.

The HTTP rendezvous uses an HTTP server and a CGI program. The HTTP
server is responsible for speaking TLS and invoking the CGI program. The
CGI program receives client registrations and proxy requests for
clients, parses them, and forwards them to the backend. We use Apache 2
as the HTTP server. The CGI script is facilitator.cgi. Currently this
is also the only method for accepting browser proxy registrations, so
you must enable this method, otherwise your clients will not be served.

For the HTTP rendezvous, there are two formats you may use for a client
registration - plain vs. (end-to-end) encrypted. Direct registrations
(e.g. flashproxy-reg-http) can use the plain format over HTTPS, which
provides transport encryption; but if you proxy registrations through
another service (e.g. reg-appspot), you must use the end-to-end format.
On the client side, you may use flashproxy-reg-url to generate
registration URLs for the end-to-end encrypted format.

The email rendezvous uses the helper program facilitator-email-poller.
Clients use the flashproxy-reg-email program to send an encrypted
message to a Gmail address. The poller constantly checks for new
messages and forwards them to facilitator-reg.

The appspot rendezvous uses Google's appengine platform as a proxy for
the HTTP method, either yours or that of another facilitator. It takes
advantage of the fact that a censor cannot distinguish between a TLS
connection to appspot.com or google.com, since the IPs are the same,
and it is highly unlikely that anyone will try to block the latter.

fac.py is a Python module containing code common to the various
facilitator programs.

This file was deleted.

@@ -0,0 +1,49 @@
These are instructions for how to set up an Apache Web Server for
handling the HTTP client registration method (facilitator.cgi /
flashproxy-reg-http / flashproxy-reg-url), as well as for browser
proxies to poll and receive a client to serve.

Unfortunately we only had time to give commands specific to the Debian
distribution of Apache; other distributions may need to tweak some
things, e.g. a2enmod, a2ensite only exist on Debian.

== HTTP server setup

Apache is the web server that runs the CGI program.

# apt-get install apache2 libapache2-mod-evasive
# a2enmod ssl headers

Edit /etc/apache2/ports.conf and comment out the port 80 configuration.

# NameVirtualHost *:80
# Listen 80

Copy examples/fp-facilitator.conf to /etc/apache2/sites-available/ or
wherever is appropriate for your Apache2 installation, then edit it as
per the instructions given in that file itself.

Link the configured site into sites-enabled.
# a2ensite fp-facilitator

=== HTTPS setup

The HTTP server should serve only over HTTPS and not unencrypted HTTP.
You will need a certificate and private key from a certificate
authority. An article on making a certificate signing request and
getting it signed is here:
http://www.debian-administration.org/articles/284
This is the basic command to generate a CSR.
$ openssl req -new -nodes -out fp-facilitator.csr.pem
The instructions below assume you have an offline private key
in fp-facilitator.key.pem and a certificate in fp-facilitator.crt.pem.

Make a file containing both the private key and a certificate.

$ cat fp-facilitator.key.pem fp-facilitator.crt.pem > fp-facilitator.pem
$ chmod 400 fp-facilitator.pem

Copy the new fp-facilitator.pem to the facilitator server as
/etc/apache2/fp-facilitator.pem.

# /etc/init.d/apache2 restart
@@ -0,0 +1,55 @@
This document describes how to configure a server running the facilitator on
Debian 7. It is not necessary to make things work, but gives you some added
security, and is a good reference if you want to create a dedicated VM for a
facilitator from scratch.

We will use the domain name fp-facilitator.example.com.

== Basic and security setup

Install some essential packages and configure a firewall.

# cat >/etc/apt/apt.conf.d/90suggests<<EOF
APT::Install-Recommends "0";
APT::Install-Suggests "0";
EOF
# apt-get remove portmap
# apt-get update
# apt-get upgrade
# apt-get install shorewall shorewall6

Away from the facilitator, generate an SSH key for authentication:

$ ssh-keygen -f ~/.ssh/fp-facilitator
$ ssh-copy-id -i ~/.ssh/fp-facilitator.pub root@fp-facilitator.example.com

Then log in and edit /etc/ssh/sshd_config to disable password
authentication:

PasswordAuthentication no

Configure the firewall to allow only SSH and HTTPS.

# cd /etc/shorewall
# cp /usr/share/doc/shorewall/examples/Universal/{interfaces,policy,rules,zones} .
Edit /etc/shorewall/rules:
SECTION NEW
SSH(ACCEPT) net $FW
HTTPS(ACCEPT) net $FW

# cd /etc/shorewall6
# cp /usr/share/doc/shorewall6/examples/Universal/{interfaces,policy,rules,zones} .
Edit /etc/shorewall6/rules:
SECTION NEW
SSH(ACCEPT) all $FW
HTTPS(ACCEPT) all $FW

Edit /etc/default/shorewall and /etc/default/shorewall6 and set

startup=1

Restart servers.

# /etc/init.d/ssh restart
# /etc/init.d/shorewall start
# /etc/init.d/shorewall6 start
@@ -0,0 +1,28 @@
# This is an example apache2 config for serving the facilitator.
#
# For instructions on how to install it, see doc/http-howto.txt. You
# should also edit the contents according to the instructions below.
#
MaxClients 256
<VirtualHost *:443>
# Update this with your hostname!
ServerName fp-facilitator.example.com
DocumentRoot /dev/null
ScriptAliasMatch ^(.*) @cgibindir@/facilitator.cgi$1

# Non-Debian distros will need to tweak this too
CustomLog ${APACHE_LOG_DIR}/fp-access.log common
ErrorLog ${APACHE_LOG_DIR}/fp-error.log
LogLevel warn

# requires mod_ssl
SSLEngine on
# Manually install your certificate to the following location.
SSLCertificateFile /etc/apache2/fp-facilitator.pem
# If you got an intermediate certificate, uncomment the following line
# and install the certificate to that location too.
#SSLCertificateChainFile /etc/apache2/fp-intermediate.pem

# requires mod_headers
Header add Strict-Transport-Security "max-age=15768000"
</VirtualHost>
@@ -0,0 +1,10 @@
# This file should contain "[<imap_host>] <email> <password>" on a single line,
# separated by whitespace. If <imap_host> is omitted, it defaults to
# imap.(<email> domain):993.
#
# If your email provider supports it, we advise you to use an app-specific
# password rather than your account password; see email-howto.txt in this
# package's documentation for details on how to do this.
#
#imap.gmail.com:993 flashproxyreg.a@gmail.com topsecret11!one
#flashproxyreg.a@gmail.com passwords with spaces are ok too
@@ -50,7 +50,7 @@ def ret(self, *args):
raise
return ret

def parse_addr_spec(spec, defhost = None, defport = None, resolve = False):
def parse_addr_spec(spec, defhost = None, defport = None, resolve = False, nameOk = False):
"""Parse a host:port specification and return a 2-tuple ("host", port) as
understood by the Python socket functions.
>>> parse_addr_spec("192.168.0.1:9999")
@@ -71,9 +71,9 @@ def parse_addr_spec(spec, defhost = None, defport = None, resolve = False):
>>> parse_addr_spec("", defhost="192.168.0.1", defport=9999)
('192.168.0.1', 9999)
If resolve is true, then the host in the specification or the defhost may be
a domain name, which will be resolved. If resolve is false, then the host
must be a numeric IPv4 or IPv6 address.
If nameOk is true, then the host in the specification or the defhost may be
a domain name. Otherwise, it must be a numeric IPv4 or IPv6 address.
If resolve is true, this implies nameOk, and the host will be resolved.
IPv6 addresses must be enclosed in square brackets."""
host = None
@@ -111,6 +111,9 @@ def parse_addr_spec(spec, defhost = None, defport = None, resolve = False):
# done only if resolve is true; otherwise the address must be numeric.
if resolve:
flags = 0
elif nameOk:
# don't pass through the getaddrinfo numeric check, just return directly
return host, int(port)
else:
flags = socket.AI_NUMERICHOST
try:
@@ -21,9 +21,7 @@ import fac
from hashlib import sha1
from M2Crypto import SSL

DEFAULT_IMAP_HOST = "imap.gmail.com"
DEFAULT_IMAP_PORT = 993
DEFAULT_EMAIL_ADDRESS = "flashproxyreg.a@gmail.com"
DEFAULT_LOG_FILENAME = "facilitator-email-poller.log"

POLL_INTERVAL = 60
@@ -75,8 +73,6 @@ PUBKEY_SHA1 = (
LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"

class options(object):
email_addr = None
imap_addr = None
password_filename = None
log_filename = DEFAULT_LOG_FILENAME
log_file = sys.stdout
@@ -126,26 +122,25 @@ class IMAP4_SSL_REQUIRED(imaplib.IMAP4_SSL):

def usage(f = sys.stdout):
print >> f, """\
Usage: %(progname)s --pass=PASSFILE
Usage: %(progname)s --email=ADDRESS --pass=PASSFILE
Facilitator-side helper for the facilitator-reg-email rendezvous. Polls
an IMAP server for email messages with client registrations, deletes
them, and forwards the registrations to the facilitator.
-d, --debug don't daemonize, log to stdout.
--disable-pin don't check server public key against a known pin.
-e, --email=ADDRESS log in as ADDRESS (default "%(email_addr)s").
-h, --help show this help.
-i, --imap=HOST[:PORT] use the given IMAP server (default "%(imap_addr)s").
--imaplib-debug show raw IMAP messages (will include email password).
-l, --log FILENAME write log to FILENAME (default \"%(log)s\").
-p, --pass=PASSFILE use the email password contained in PASSFILE.
-p, --pass=PASSFILE use the email/password contained in PASSFILE. This file
should contain "[<imap_host>] <email> <password>" on a
single line, separated by whitespace. If <imap_host> is
omitted, it defaults to imap.(<email> domain):993.
--pidfile FILENAME write PID to FILENAME after daemonizing.
--privdrop-user USER switch UID and GID to those of USER.
--unsafe-logging don't scrub email password and IP addresses from logs.\
""" % {
"progname": sys.argv[0],
"email_addr": DEFAULT_EMAIL_ADDRESS,
"imap_addr": fac.format_addr((DEFAULT_IMAP_HOST, DEFAULT_IMAP_PORT)),
"log": DEFAULT_LOG_FILENAME,
}

@@ -160,9 +155,6 @@ def log(msg):
print >> options.log_file, (u"%s %s" % (time.strftime(LOG_DATE_FORMAT), msg)).encode("UTF-8")
options.log_file.flush()

options.email_addr = DEFAULT_EMAIL_ADDRESS
options.imap_addr = (DEFAULT_IMAP_HOST, DEFAULT_IMAP_PORT)

opts, args = getopt.gnu_getopt(sys.argv[1:], "de:hi:l:p:", [
"debug",
"disable-pin",
@@ -182,13 +174,9 @@ for o, a in opts:
options.log_filename = None
elif o == "--disable-pin":
options.use_certificate_pin = False
elif o == "-e" or o == "--email":
options.email_addr = a
elif o == "-h" or o == "--help":
usage()
sys.exit()
elif o == "-i" or o == "--imap":
options.imap_addr = fac.parse_addr_spec(a, DEFAULT_IMAP_HOST, DEFAULT_IMAP_PORT)
if o == "--imaplib-debug":
options.imaplib_debug = True
elif o == "-l" or o == "--log":
@@ -222,7 +210,26 @@ try:
print >> sys.stderr, "Refusing to run with group- or world-readable password file. Try"
print >> sys.stderr, "\tchmod 600 %s" % options.password_filename
sys.exit(1)
email_password = password_file.read().strip()
for line in password_file.readlines():
line = line.strip("\n")
if not line or line.startswith('#'): continue
# we do this stricter regex match because passwords might have spaces in
res = re.match(r"(?:(\S+)\s)?(\S+@\S+)\s(.+)", line)
if not res:
raise ValueError("could not find email or password: %s" % line)
(imap_addr_spec, email_addr, email_password) = res.groups()
default_imap_host = "imap.%s" % (email_addr.split('@', 1)[1])
imap_addr = fac.parse_addr_spec(
imap_addr_spec or "", default_imap_host, DEFAULT_IMAP_PORT, nameOk=True)
break
else:
raise ValueError("no email line found")
except Exception, e:
print >> sys.stderr, """\
Failed to parse password file "%s": %s.
Syntax is [<imap_host>] <email> <password>.
""" % (options.password_filename, str(e))
sys.exit(1)
finally:
password_file.close()

@@ -372,7 +379,7 @@ def imap_login():
try:
ca_certs_file.write(CA_CERTS)
ca_certs_file.flush()
imap = IMAP4_SSL_REQUIRED(options.imap_addr[0], options.imap_addr[1],
imap = IMAP4_SSL_REQUIRED(imap_addr[0], imap_addr[1],
None, ca_certs_file.name)
finally:
ca_certs_file.close()
@@ -390,8 +397,8 @@ def imap_login():
expected = "(" + ", ".join(x.encode("hex") for x in PUBKEY_SHA1) + ")"
raise ValueError("Public key does not match pin: got %s but expected any of %s" % (found, expected))

log(u"logging in as %s" % options.email_addr)
imap.login(options.email_addr, email_password)
log(u"logging in as %s" % email_addr)
imap.login(email_addr, email_password)

return imap

@@ -1,6 +1,7 @@
#!/usr/bin/env python

from cStringIO import StringIO
import os
import socket
import subprocess
import tempfile
@@ -217,7 +218,8 @@ def setUp(self):
self.relay_file.write("%s %s\n" % (RELAY_TP, fac.format_addr(self.IPV6_RELAY_ADDR)))
self.relay_file.flush()
self.relay_file.seek(0)
self.process = subprocess.Popen(["./facilitator", "-d", "-p", str(FACILITATOR_PORT), "-r", self.relay_file.name, "-l", "/dev/null"])
fn = os.path.join(os.path.dirname(__file__), "./facilitator")
self.process = subprocess.Popen(["python", fn, "-d", "-p", str(FACILITATOR_PORT), "-r", self.relay_file.name, "-l", "/dev/null"])
time.sleep(0.1)

def tearDown(self):
@@ -348,6 +350,11 @@ def test_noresolve(self):
"""Test that parse_addr_spec does not do DNS resolution by default."""
self.assertRaises(ValueError, fac.parse_addr_spec, "example.com")

def test_noresolve_nameok(self):
"""Test that nameok passes through a domain name without resolving it."""
self.assertEqual(fac.parse_addr_spec("example.com:8888", defhost="other.com", defport=9999, nameOk=True), ("example.com", 8888))
self.assertEqual(fac.parse_addr_spec("", defhost="other.com", defport=9999, nameOk=True), ("other.com", 9999))

class ParseTransactionTest(unittest.TestCase):
def test_empty_string(self):
self.assertRaises(ValueError, fac.parse_transaction, "")
@@ -17,20 +17,30 @@
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="Flash proxy email rendezvous poller"
NAME=facilitator-email-poller
PIDFILE=/var/run/$NAME.pid
LOGFILE=/var/log/$NAME.log
CONFDIR=/etc/flashproxy
PRIVDROP_USER=facilitator-nobody
DAEMON=/usr/local/bin/$NAME

prefix=@prefix@
exec_prefix=@exec_prefix@
PIDFILE=@localstatedir@/run/$NAME.pid
LOGFILE=@localstatedir@/log/$NAME.log
CONFDIR=@sysconfdir@/flashproxy
PRIVDROP_USER=@fpfacilitatoruser@
DAEMON=@bindir@/$NAME
DAEMON_ARGS="--pass $CONFDIR/reg-email.pass --log $LOGFILE --pidfile $PIDFILE --privdrop-user $PRIVDROP_USER"
SCRIPTNAME=/etc/init.d/$NAME
DEFAULTSFILE=@sysconfdir@/default/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r "$DEFAULTSFILE" ] && . "$DEFAULTSFILE"

. /lib/init/vars.sh
. /lib/lsb/init-functions

[ "$UNSAFE_LOGGING" = "yes" ] && DAEMON_ARGS="$DAEMON_ARGS --unsafe-logging"
[ -n "$IMAPADDR" ] && DAEMON_ARGS="$DAEMON_ARGS --imap $IMAPADDR"
DAEMON_ARGS="$DAEMON_ARGS --email $FACILITATOR_EMAIL_ADDR"

#
# Function that starts the daemon/service
#
@@ -74,6 +84,10 @@ do_stop()

case "$1" in
start)
if [ "$RUN_DAEMON" != "yes" ]; then
log_action_msg "Not starting $DESC (Disabled in $DEFAULTSFILE)."
exit 0
fi
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
@@ -111,7 +125,7 @@ case "$1" in
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
echo "Usage: $0 {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
@@ -17,17 +17,26 @@
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="Flash proxy local registration daemon"
NAME=facilitator-reg-daemon
PIDFILE=/var/run/$NAME.pid
LOGFILE=/var/log/$NAME.log
CONFDIR=/etc/flashproxy
PRIVDROP_USER=facilitator-nobody
DAEMON=/usr/local/bin/$NAME

prefix=@prefix@
exec_prefix=@exec_prefix@
PIDFILE=@localstatedir@/run/$NAME.pid
LOGFILE=@localstatedir@/log/$NAME.log
CONFDIR=@sysconfdir@/flashproxy
PRIVDROP_USER=@fpfacilitatoruser@
DAEMON=@bindir@/$NAME
DAEMON_ARGS="--key $CONFDIR/reg-daemon.key --log $LOGFILE --pidfile $PIDFILE --privdrop-user $PRIVDROP_USER"
SCRIPTNAME=/etc/init.d/$NAME
DEFAULTSFILE=@sysconfdir@/default/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r "$DEFAULTSFILE" ] && . "$DEFAULTSFILE"

[ "$UNSAFE_LOGGING" = "yes" ] && DAEMON_ARGS="$DAEMON_ARGS --unsafe-logging"
[ -n "$PORT" ] && DAEMON_ARGS="$DAEMON_ARGS --port $PORT"

. /lib/init/vars.sh
. /lib/lsb/init-functions

@@ -74,6 +83,10 @@ do_stop()

case "$1" in
start)
if [ "$RUN_DAEMON" != "yes" ]; then
log_action_msg "Not starting $DESC (Disabled in $DEFAULTSFILE)."
exit 0
fi
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
@@ -111,7 +124,7 @@ case "$1" in
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
echo "Usage: $0 {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
@@ -17,21 +17,30 @@
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="Flash proxy facilitator"
NAME=facilitator
PIDFILE=/var/run/$NAME.pid
LOGFILE=/var/log/$NAME.log
CONFDIR=/etc/flashproxy

prefix=@prefix@
exec_prefix=@exec_prefix@
PIDFILE=@localstatedir@/run/$NAME.pid
LOGFILE=@localstatedir@/log/$NAME.log
CONFDIR=@sysconfdir@/flashproxy
RELAYFILE=$CONFDIR/relays
PRIVDROP_USER=facilitator-nobody
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="--relay-file $CONFDIR/relays --log $LOGFILE --pidfile $PIDFILE --privdrop-user $PRIVDROP_USER"
SCRIPTNAME=/etc/init.d/$NAME
PRIVDROP_USER=@fpfacilitatoruser@
DAEMON=@bindir@/$NAME
DAEMON_ARGS="--relay-file $RELAYFILE --log $LOGFILE --pidfile $PIDFILE --privdrop-user $PRIVDROP_USER"
DEFAULTSFILE=@sysconfdir@/default/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r "$DEFAULTSFILE" ] && . "$DEFAULTSFILE"

. /lib/init/vars.sh
. /lib/lsb/init-functions

[ "$UNSAFE_LOGGING" = "yes" ] && DAEMON_ARGS="$DAEMON_ARGS --unsafe-logging"
[ -n "$PORT" ] && DAEMON_ARGS="$DAEMON_ARGS --port $PORT"

#
# Function that starts the daemon/service
#
@@ -75,6 +84,10 @@ do_stop()

case "$1" in
start)
if [ "$RUN_DAEMON" != "yes" ]; then
log_action_msg "Not starting $DESC (Disabled in $DEFAULTSFILE)."
exit 0
fi
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
@@ -112,7 +125,7 @@ case "$1" in
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
echo "Usage: $0 {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac