Commit 3c3ff9fb authored by Leo P. Singer's avatar Leo P. Singer
Browse files

Accept password interatively or from netrc, but not command line args

Reading the password from command line arguments lead to some security
breaches due to passwords hardcoded in scripts in public repositories.
The netrc file support encourages users to save their credentials (when
necessary) outside of their version-controlled scripts.
parent c0f079ff
......@@ -16,12 +16,14 @@
# You should have received a copy of the GNU General Public License
# along with lvalert. If not, see <http://www.gnu.org/licenses/>.
import netrc
import sys
import os
import time
import select
import logging
import libxml2
import getpass
from optparse import *
from M2Crypto.SSL import Context
......@@ -56,29 +58,29 @@ usage = """\
1. create a pubsub node called small_steps
%prog --username albert.einstein --password secret --create --node small_steps
%prog --username albert.einstein --create --node small_steps
2. delete a pubsub node called small_steps
%prog --username albert.einstein --password secret --delete --node small_steps
%prog --username albert.einstein --delete --node small_steps
4. subscribe to a pubsub node called lvalert_test
%prog --username albert.einstein --password secret --subscribe --node lvalert_test
%prog --username albert.einstein --subscribe --node lvalert_test
The owner (person who creates the node by default) can delete and
publish information to the node. The owner can also add other
publishers to the node using the command
%prog --username albert.einstein --password secret --add-publisher patrick.brady --node small_steps
%prog --username albert.einstein --add-publisher patrick.brady --node small_steps
Others can subscribe. To see a list of available nodes:
%prog --username albert.einstein --password secret --get-nodes
%prog --username albert.einstein --get-nodes
To see the nodes to which you are subscribed:
%prog --username albert.einstein --password secret --subscriptions
%prog --username albert.einstein --subscriptions
There are two programs called lvalert_listen and lvalert_send which
provide ways to listen for content on the node and to publish
......@@ -87,73 +89,76 @@ usage = """\
"""
#################################################################
def parse_command_line():
"""
Parser function dedicated
"""
parser = OptionParser(usage=usage)
#username and password
parser.add_option("-a","--username",action="store",type="string",\
default="", help="the username of the publisher or listener" )
parser.add_option("-b","--password",action="store",type="string",\
default="", help="the password of the publisher or listener" )
parser.add_option("-c","--server",action="store",type="string",\
default="lvalert.cgca.uwm.edu", help="the pubsub server" )
parser.add_option("-r","--resource",action="store",type="string",\
default="admin", help="resource to use in JID" )
# access information about root nodes
parser.add_option("-d","--create",action="store_true",\
default=False, help="create a new pubsub node" )
parser.add_option("-e","--delete",action="store_true",\
default=False, help="delete a new pubsub node" )
parser.add_option("-f","--subscribe",action="store_true",\
default=False, help="subscribe to a new pubsub node" )
parser.add_option("-g","--unsubscribe",action="store_true",\
default=False, help="unsubscribe from a new pubsub node" )
parser.add_option("-n","--unsubscribe-subid",action="store",type="string",\
default=None, help="subid of subscription obtained by running subscriptions" )
parser.add_option("-i","--subscriptions",action="store_true",\
default=False, help="return a list of subscriptions" )
parser.add_option("-j","--add-publisher",action="store",type="string",\
default=None, help="jabber id of person allowed to publish to node" )
parser.add_option("-m","--get-nodes",action="store_true",\
default=False, help="get the list of existing nodes" )
parser.add_option("-o","--affiliations",action="store",type="string",\
default=None, help="get the list of affiliations to a node" )
parser.add_option("-p","--delete-publisher",action="store",type="string",\
default=None, help="jid of publisher to delete from a node" )
parser.add_option("-q","--node",action="store",type="string",\
default=None, help="name of node" )
# debugging options
parser.add_option("-l","--debug",action="store_true",\
default=False, help="should print out lots of information" )
parser.add_option("-v","--verbose",action="store_true",\
default=False, help="be verbose as you process the request" )
# version
parser.add_option("-w", "--version", action="store_true",
default=False, help="display version information")
parser = OptionParser(usage=usage)
#username and password
parser.add_option("-a","--username",action="store",type="string",\
help="the username of the publisher or listener" )
parser.add_option("-c","--server",action="store",type="string",\
default="lvalert.cgca.uwm.edu", help="the pubsub server" )
parser.add_option("-r","--resource",action="store",type="string",\
default="admin", help="resource to use in JID" )
parser.add_option("--netrc", "-N",
help="Load username and password from this file",
default=os.environ.get('NETRC', '~/.netrc'))
# access information about root nodes
parser.add_option("-d","--create",action="store_true",\
default=False, help="create a new pubsub node" )
parser.add_option("-e","--delete",action="store_true",\
default=False, help="delete a new pubsub node" )
parser.add_option("-f","--subscribe",action="store_true",\
default=False, help="subscribe to a new pubsub node" )
parser.add_option("-g","--unsubscribe",action="store_true",\
default=False, help="unsubscribe from a new pubsub node" )
parser.add_option("-n","--unsubscribe-subid",action="store",type="string",\
default=None, help="subid of subscription obtained by running subscriptions" )
parser.add_option("-i","--subscriptions",action="store_true",\
default=False, help="return a list of subscriptions" )
parser.add_option("-j","--add-publisher",action="store",type="string",\
default=None, help="jabber id of person allowed to publish to node" )
parser.add_option("-m","--get-nodes",action="store_true",\
default=False, help="get the list of existing nodes" )
parser.add_option("-o","--affiliations",action="store",type="string",\
default=None, help="get the list of affiliations to a node" )
parser.add_option("-p","--delete-publisher",action="store",type="string",\
default=None, help="jid of publisher to delete from a node" )
parser.add_option("-q","--node",action="store",type="string",\
default=None, help="name of node" )
# debugging options
parser.add_option("-l","--debug",action="store_true",\
default=False, help="should print out lots of information" )
parser.add_option("-v","--verbose",action="store_true",\
default=False, help="be verbose as you process the request" )
# version
parser.add_option("-w", "--version", action="store_true",
default=False, help="display version information")
(options,args) = parser.parse_args()
# ============================================================================
# -- get command line arguments
opts, args = parser.parse_args()
if options.version:
if opts.version:
import pkg_resources
version = pkg_resources.require("ligo-lvalert")[0].version
print "LVAlert v. %s" % version
exit(0)
if not options.username:
raise ValueError, "--username must be provided"
if (opts.add_publisher or opts.create or opts.delete or opts.subscribe or opts.unsubscribe or opts.delete_publisher) and not opts.node:
parser.error("--node must be provided")
if (options.add_publisher or options.create or options.delete or options.subscribe or options.unsubscribe or options.delete_publisher) and not options.node:
raise ValueError, "--node must be provided"
return options, sys.argv[1:]
# ============================================================================
# -- get command line arguments
opts, args = parse_command_line()
try:
default_username, _, default_password = netrc.netrc(os.path.expanduser(opts.netrc)).authenticators(opts.server)
except:
default_username, default_password = None, None
myusername = opts.username or default_username
if not myusername:
parser.error('--username is required')
if myusername == default_username:
mypassword = default_password
else:
mypassword = getpass.getpass('password for ' + myusername + ': ')
class MyClient(Client):
def __init__(self, jid, password):
......@@ -251,8 +256,8 @@ else:
libxml2.debugMemory(1)
# set up the stream
myjid=JID(opts.username+"@"+opts.server+"/"+opts.resource)
s=MyClient(jid=myjid,password=opts.password)
myjid=JID(myusername+"@"+opts.server+"/"+opts.resource)
s=MyClient(jid=myjid,password=mypassword)
if opts.verbose:
print "connecting..."
......
#!/usr/bin/env python
# Copyright (C) Patrick Brady, Brian Moe, Branson Stephens (2015)
# Copyright (C) Leo Singer (2016)
#
# This file is part of lvalert
#
......@@ -16,6 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with lvalert. If not, see <http://www.gnu.org/licenses/>.
import netrc
import sys
import os
import datetime
......@@ -61,12 +63,23 @@ usage = """\
the node using lvalert_admin. Then you will receive any events that are
published to that node by doing:
%prog --username albert.einstein --password secret
%prog --username albert.einstein
If you do not provide the username, then the program will look for it in
the file ~/.netrc in your home directory. This location may be overriden
with the NETRC environment variable or the --netrc option. This file
should contain a line like the following:
machine lvalert.cgca.uwm.edu login albert.einstein password ligorocks
If a matching entry in your .netrc file is found, the program will use
that password. Otherwise, it will prompt you interactively for your
password.
When an event is published to the node, a message will be printed to
the window where the listener is running. To see the event, run
%prog --username albert.einstein --password secret --show
%prog --username albert.einstein --show
The owner (person who creates the node by default) can delete and
publish information to the node. The owner can also add other
......@@ -90,7 +103,7 @@ usage = """\
then running
lvalert_listen --username albert.einstein --password secret --config-file example.ini
lvalert_listen --username albert.einstein secret --config-file example.ini
would result in ./mycounter being executed and the output printed to
screen whenever a message was received via the lvalert_test node.
......@@ -101,52 +114,45 @@ usage = """\
"""
#################################################################
def parse_command_line():
"""
Parser function dedicated
"""
parser = OptionParser(usage=usage)
#username and password
parser.add_option("-a","--username",action="store",type="string",\
default="", help="the username of the publisher or listener" )
parser.add_option("-b","--password",action="store",type="string",\
default="", help="the password of the publisher or listener" )
parser.add_option("-s","--server",action="store",type="string",\
default="lvalert.cgca.uwm.edu", help="the pubsub server" )
parser.add_option("-r","--resource",action="store",type="string",\
default="listener", help="resource to use in JID" )
parser.add_option("-c","--config-file",action="store",type="string",\
default=None, help="config file with list of actions" )
parser.add_option("-S","--show",action="store_true",\
default=False, help="print the payload to stdout" )
parser.add_option("-n","--node",action="store",type="string",\
default=None, help="name of the node on the pubsub server" )
# debugging options
parser.add_option("-v","--verbose",action="store_true",\
default=False, help="be verbose as you process the request" )
parser.add_option("-g","--debug",action="store_true",\
default=False, help="should print out lots of information" )
# options about message handling
parser.add_option("", "--dont-wait",action="store_true",\
default=False, help="if supplied, jobs will be launched \
as soon as they arrive, rather than blocking")
# version
parser.add_option("-w", "--version", action="store_true",
default=False, help="display version information")
(options,args) = parser.parse_args()
parser = OptionParser(usage=usage)
#username and password
parser.add_option("-a","--username",action="store",type="string",\
help="the username of the publisher or listener" )
parser.add_option("-s","--server",action="store",type="string",\
default="lvalert.cgca.uwm.edu", help="the pubsub server" )
parser.add_option("-r","--resource",action="store",type="string",\
default="listener", help="resource to use in JID" )
parser.add_option("-c","--config-file",action="store",type="string",\
default=None, help="config file with list of actions" )
parser.add_option("--netrc", "-N",
help="Load username and password from this file",
default=os.environ.get('NETRC', '~/.netrc'))
parser.add_option("-S","--show",action="store_true",\
default=False, help="print the payload to stdout" )
parser.add_option("-n","--node",action="store",type="string",\
default=None, help="name of the node on the pubsub server" )
# debugging options
parser.add_option("-v","--verbose",action="store_true",\
default=False, help="be verbose as you process the request" )
parser.add_option("-g","--debug",action="store_true",\
default=False, help="should print out lots of information" )
# options about message handling
parser.add_option("", "--dont-wait",action="store_true",\
default=False, help="if supplied, jobs will be launched \
as soon as they arrive, rather than blocking")
# version
parser.add_option("-w", "--version", action="store_true",
default=False, help="display version information")
return options, sys.argv[1:]
# ============================================================================
# -- get command line arguments
opts, args = parse_command_line()
opts, args = parser.parse_args()
if opts.version:
import pkg_resources
......@@ -154,6 +160,19 @@ if opts.version:
print "LVAlert v. %s" % version
exit(0)
try:
default_username, _, default_password = netrc.netrc(os.path.expanduser(opts.netrc)).authenticators(opts.server)
except:
default_username, default_password = None, None
myusername = opts.username or default_username
if not myusername:
parser.error('--username is required')
if myusername == default_username:
mypassword = default_password
else:
mypassword = getpass.getpass('password for ' + myusername + ': ')
if opts.dont_wait: ### required packages for "dont-wait" option
import multiprocessing
import tempfile
......@@ -317,11 +336,7 @@ if opts.config_file:
actions[node] = cp.get(node,'executable')
# set up the stream
myjid=JID(opts.username+"@"+opts.server+"/"+opts.resource)
if not opts.password:
mypassword = getpass.getpass()
else:
mypassword = opts.password
myjid=JID(myusername+"@"+opts.server+"/"+opts.resource)
s=MyClient(myjid,mypassword,actions, wait=not opts.dont_wait)
if opts.verbose:
......
......@@ -16,10 +16,13 @@
# You should have received a copy of the GNU General Public License
# along with lvalert. If not, see <http://www.gnu.org/licenses/>.
import netrc
import sys
import os
import datetime
import logging
import libxml2
import getpass
from optparse import OptionParser
from M2Crypto.SSL import Context
......@@ -55,7 +58,7 @@ usage = """\
You can send information containted in the file stuff.xml by
doing:
%prog --username albert.einstein --password secret --node small_steps --file stuff.xml --max_attempts N
%prog --username albert.einstein --node small_steps --file stuff.xml --max_attempts N
When an stuff.xml is sent to a node by a publisher, it will be sent
to all subscribers who are logged in.
......@@ -77,49 +80,42 @@ usage = """\
"""
#################################################################
def parse_command_line():
"""
Parser function dedicated
"""
parser = OptionParser(usage=usage)
#username and password
parser.add_option("-a","--username",action="store",type="string",\
default="", help="the username of the publisher or listener" )
parser.add_option("-b","--password",action="store",type="string",\
default="", help="the password of the publisher or listener" )
parser.add_option("-s","--server",action="store",type="string",\
default="lvalert.cgca.uwm.edu", help="the pubsub server" )
parser.add_option("-r","--resource",action="store",type="string",\
default="sender", help="resource to use in JID" )
# access information about root nodes
parser.add_option("-n","--node",action="store",type="string",\
default=None, help="name of the node on the pubsub server" )
parser.add_option("-p","--file",action="store",type="string",\
default=None, help="name of the file with the event" )
# debugging options
parser.add_option("-v","--verbose",action="store_true",\
default=False, help="be verbose as you process the request" )
parser.add_option("-g","--debug",action="store_true",\
default=False, help="should print out lots of information" )
# timeout attempts
parser.add_option("-m","--max_attempts",action="store_true",\
default=10, help="max number of timeouts allowed" )
# version
parser.add_option("-w", "--version", action="store_true",
default=False, help="display version information")
(options,args) = parser.parse_args()
return options, sys.argv[1:]
parser = OptionParser(usage=usage)
#username and password
parser.add_option("-a","--username",action="store",type="string",\
help="the username of the publisher or listener" )
parser.add_option("-s","--server",action="store",type="string",\
default="lvalert.cgca.uwm.edu", help="the pubsub server" )
parser.add_option("-r","--resource",action="store",type="string",\
default="sender", help="resource to use in JID" )
parser.add_option("--netrc", "-N",
help="Load username and password from this file",
default=os.environ.get('NETRC', '~/.netrc'))
# access information about root nodes
parser.add_option("-n","--node",action="store",type="string",\
default=None, help="name of the node on the pubsub server" )
parser.add_option("-p","--file",action="store",type="string",\
default=None, help="name of the file with the event" )
# debugging options
parser.add_option("-v","--verbose",action="store_true",\
default=False, help="be verbose as you process the request" )
parser.add_option("-g","--debug",action="store_true",\
default=False, help="should print out lots of information" )
# timeout attempts
parser.add_option("-m","--max_attempts",action="store_true",\
default=10, help="max number of timeouts allowed" )
# version
parser.add_option("-w", "--version", action="store_true",
default=False, help="display version information")
# ============================================================================
# -- get command line arguments
opts, args = parse_command_line()
opts, args = parser.parse_args()
if opts.version:
import pkg_resources
......@@ -127,8 +123,18 @@ if opts.version:
print "LVAlert v. %s" % version
exit(0)
if not opts.username:
raise ValueError, "--username is required"
try:
default_username, _, default_password = netrc.netrc(os.path.expanduser(opts.netrc)).authenticators(opts.server)
except:
default_username, default_password = None, None
myusername = opts.username or default_username
if not myusername:
parser.error('--username is required')
if myusername == default_username:
mypassword = default_password
else:
mypassword = getpass.getpass('password for ' + myusername + ': ')
if not opts.node:
raise ValueError, "--node is required"
......@@ -237,12 +243,12 @@ if not opts.file:
libxml2.debugMemory(1)
# Instantiate the client
jid=JID(opts.username+"@"+opts.server+"/"+opts.resource)
jid=JID(myusername+"@"+opts.server+"/"+opts.resource)
# if bare JID is provided add a resource -- it is required
if not jid.resource:
jid=JID(jid.node, jid.domain, "sender")
client = MyClient(jid,opts.password,opts.max_attempts,onStart)
client = MyClient(jid,mypassword,opts.max_attempts,onStart)
# Connect
logger.info("connecting...")
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment