summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/Bcfg2/Client/Frame.py5
-rw-r--r--src/lib/Bcfg2/Client/Tools/Action.py7
-rw-r--r--src/lib/Bcfg2/Client/Tools/__init__.py6
-rw-r--r--src/lib/Bcfg2/Server/Admin/Init.py59
-rw-r--r--src/lib/Bcfg2/Server/Admin/Pull.py8
-rwxr-xr-xsrc/sbin/bcfg2-crypt19
6 files changed, 72 insertions, 32 deletions
diff --git a/src/lib/Bcfg2/Client/Frame.py b/src/lib/Bcfg2/Client/Frame.py
index 64460ea66..53180ab68 100644
--- a/src/lib/Bcfg2/Client/Frame.py
+++ b/src/lib/Bcfg2/Client/Frame.py
@@ -1,8 +1,10 @@
""" Frame is the Client Framework that verifies and installs entries,
and generates statistics. """
+import os
import sys
import time
+import select
import fnmatch
import logging
import Bcfg2.Client.Tools
@@ -160,6 +162,9 @@ class Frame(object):
iprompt = entry.get('qtext')
else:
iprompt = prompt % (entry.tag, entry.get('name'))
+ # flush input buffer
+ while len(select.select([sys.stdin.fileno()], [], [], 0.0)[0]) > 0:
+ os.read(sys.stdin.fileno(), 4096)
try:
ans = input(iprompt.encode(sys.stdout.encoding, 'replace'))
if ans in ['y', 'Y']:
diff --git a/src/lib/Bcfg2/Client/Tools/Action.py b/src/lib/Bcfg2/Client/Tools/Action.py
index 7726da94c..b1a897c81 100644
--- a/src/lib/Bcfg2/Client/Tools/Action.py
+++ b/src/lib/Bcfg2/Client/Tools/Action.py
@@ -1,5 +1,8 @@
"""Action driver"""
+import os
+import sys
+import select
import Bcfg2.Client.Tools
from Bcfg2.Client.Frame import matches_white_list, passes_black_list
from Bcfg2.Compat import input # pylint: disable=W0622
@@ -33,6 +36,10 @@ class Action(Bcfg2.Client.Tools.Tool):
if self.setup['interactive']:
prompt = ('Run Action %s, %s: (y/N): ' %
(entry.get('name'), entry.get('command')))
+ # flush input buffer
+ while len(select.select([sys.stdin.fileno()], [], [],
+ 0.0)[0]) > 0:
+ os.read(sys.stdin.fileno(), 4096)
ans = input(prompt)
if ans not in ['y', 'Y']:
return False
diff --git a/src/lib/Bcfg2/Client/Tools/__init__.py b/src/lib/Bcfg2/Client/Tools/__init__.py
index 4022692be..927b25ba8 100644
--- a/src/lib/Bcfg2/Client/Tools/__init__.py
+++ b/src/lib/Bcfg2/Client/Tools/__init__.py
@@ -1,7 +1,9 @@
"""This contains all Bcfg2 Tool modules"""
import os
+import sys
import stat
+import select
from subprocess import Popen, PIPE
import Bcfg2.Client.XML
from Bcfg2.Compat import input, walk_packages # pylint: disable=W0622
@@ -373,6 +375,10 @@ class SvcTool(Tool):
if self.setup['interactive']:
prompt = ('Restart service %s?: (y/N): ' %
entry.get('name'))
+ # flush input buffer
+ while len(select.select([sys.stdin.fileno()], [], [],
+ 0.0)[0]) > 0:
+ os.read(sys.stdin.fileno(), 4096)
ans = input(prompt)
if ans not in ['y', 'Y']:
continue
diff --git a/src/lib/Bcfg2/Server/Admin/Init.py b/src/lib/Bcfg2/Server/Admin/Init.py
index 869dc1aca..14065980d 100644
--- a/src/lib/Bcfg2/Server/Admin/Init.py
+++ b/src/lib/Bcfg2/Server/Admin/Init.py
@@ -1,11 +1,13 @@
""" Interactively initialize a new repository. """
-import getpass
+
import os
+import sys
+import stat
+import select
import random
import socket
-import stat
import string
-import sys
+import getpass
import subprocess
import Bcfg2.Server.Admin
@@ -85,6 +87,14 @@ OS_LIST = [('Red Hat/Fedora/RHEL/RHAS/Centos', 'redhat'),
('Arch', 'arch')]
+def safe_input(prompt):
+ """ input() that flushes the input buffer before accepting input """
+ # flush input buffer
+ while len(select.select([sys.stdin.fileno()], [], [], 0.0)[0]) > 0:
+ os.read(sys.stdin.fileno(), 4096)
+ return input(prompt)
+
+
def gen_password(length):
"""Generates a random alphanumeric password with length characters."""
chars = string.letters + string.digits
@@ -116,8 +126,8 @@ def create_conf(confpath, confdata):
""" create the config file """
# Don't overwrite existing bcfg2.conf file
if os.path.exists(confpath):
- result = input("\nWarning: %s already exists. "
- "Overwrite? [y/N]: " % confpath)
+ result = safe_input("\nWarning: %s already exists. "
+ "Overwrite? [y/N]: " % confpath)
if result not in ['Y', 'y']:
print("Leaving %s unchanged" % confpath)
return
@@ -186,8 +196,8 @@ class Init(Bcfg2.Server.Admin.Mode):
def _prompt_hostname(self):
"""Ask for the server hostname."""
- data = input("What is the server's hostname [%s]: " %
- socket.getfqdn())
+ data = safe_input("What is the server's hostname [%s]: " %
+ socket.getfqdn())
if data != '':
self.data['shostname'] = data
else:
@@ -195,21 +205,21 @@ class Init(Bcfg2.Server.Admin.Mode):
def _prompt_config(self):
"""Ask for the configuration file path."""
- newconfig = input("Store Bcfg2 configuration in [%s]: " %
- self.configfile)
+ newconfig = safe_input("Store Bcfg2 configuration in [%s]: " %
+ self.configfile)
if newconfig != '':
self.data['configfile'] = os.path.abspath(newconfig)
def _prompt_repopath(self):
"""Ask for the repository path."""
while True:
- newrepo = input("Location of Bcfg2 repository [%s]: " %
+ newrepo = safe_input("Location of Bcfg2 repository [%s]: " %
self.data['repopath'])
if newrepo != '':
self.data['repopath'] = os.path.abspath(newrepo)
if os.path.isdir(self.data['repopath']):
- response = input("Directory %s exists. Overwrite? [y/N]:" %
- self.data['repopath'])
+ response = safe_input("Directory %s exists. Overwrite? [y/N]:"
+ % self.data['repopath'])
if response.lower().strip() == 'y':
break
else:
@@ -225,8 +235,8 @@ class Init(Bcfg2.Server.Admin.Mode):
def _prompt_server(self):
"""Ask for the server name."""
- newserver = input("Input the server location [%s]: " %
- self.data['server_uri'])
+ newserver = safe_input("Input the server location [%s]: " %
+ self.data['server_uri'])
if newserver != '':
self.data['server_uri'] = newserver
@@ -238,7 +248,7 @@ class Init(Bcfg2.Server.Admin.Mode):
prompt += ': '
while True:
try:
- osidx = int(input(prompt))
+ osidx = int(safe_input(prompt))
self.data['os_sel'] = OS_LIST[osidx - 1][1]
break
except ValueError:
@@ -248,27 +258,28 @@ class Init(Bcfg2.Server.Admin.Mode):
"""Ask for the key details (country, state, and location)."""
print("The following questions affect SSL certificate generation.")
print("If no data is provided, the default values are used.")
- newcountry = input("Country name (2 letter code) for certificate: ")
+ newcountry = safe_input("Country name (2 letter code) for "
+ "certificate: ")
if newcountry != '':
if len(newcountry) == 2:
self.data['country'] = newcountry
else:
while len(newcountry) != 2:
- newcountry = input("2 letter country code (eg. US): ")
+ newcountry = safe_input("2 letter country code (eg. US): ")
if len(newcountry) == 2:
self.data['country'] = newcountry
break
else:
self.data['country'] = 'US'
- newstate = input("State or Province Name (full name) for "
- "certificate: ")
+ newstate = safe_input("State or Province Name (full name) for "
+ "certificate: ")
if newstate != '':
self.data['state'] = newstate
else:
self.data['state'] = 'Illinois'
- newlocation = input("Locality Name (eg, city) for certificate: ")
+ newlocation = safe_input("Locality Name (eg, city) for certificate: ")
if newlocation != '':
self.data['location'] = newlocation
else:
@@ -277,12 +288,12 @@ class Init(Bcfg2.Server.Admin.Mode):
def _prompt_keypath(self):
""" Ask for the key pair location. Try to use sensible
defaults depending on the OS """
- keypath = input("Path where Bcfg2 server private key will be created "
- "[%s]: " % self.data['keypath'])
+ keypath = safe_input("Path where Bcfg2 server private key will be "
+ "created [%s]: " % self.data['keypath'])
if keypath:
self.data['keypath'] = keypath
- certpath = input("Path where Bcfg2 server cert will be created"
- "[%s]: " % self.data['certpath'])
+ certpath = safe_input("Path where Bcfg2 server cert will be created"
+ "[%s]: " % self.data['certpath'])
if certpath:
self.data['certpath'] = certpath
diff --git a/src/lib/Bcfg2/Server/Admin/Pull.py b/src/lib/Bcfg2/Server/Admin/Pull.py
index e41652205..130e85b67 100644
--- a/src/lib/Bcfg2/Server/Admin/Pull.py
+++ b/src/lib/Bcfg2/Server/Admin/Pull.py
@@ -1,8 +1,10 @@
""" Retrieves entries from clients and integrates the information into
the repository """
-import getopt
+import os
import sys
+import getopt
+import select
import Bcfg2.Server.Admin
from Bcfg2.Compat import input # pylint: disable=W0622
@@ -99,6 +101,10 @@ class Pull(Bcfg2.Server.Admin.MetadataCore):
else:
print(" => host entry: %s" % (choice.hostname))
+ # flush input buffer
+ while len(select.select([sys.stdin.fileno()], [], [],
+ 0.0)[0]) > 0:
+ os.read(sys.stdin.fileno(), 4096)
ans = input("Use this entry? [yN]: ") in ['y', 'Y']
if ans:
return choice
diff --git a/src/sbin/bcfg2-crypt b/src/sbin/bcfg2-crypt
index 0693b430c..961a8dc58 100755
--- a/src/sbin/bcfg2-crypt
+++ b/src/sbin/bcfg2-crypt
@@ -4,6 +4,7 @@
import os
import sys
import copy
+import select
import logging
import lxml.etree
import Bcfg2.Logger
@@ -31,7 +32,7 @@ class Encryptor(object):
self.passphrase = None
self.pname = None
self.logger = logging.getLogger(self.__class__.__name__)
-
+
def get_encrypted_filename(self, plaintext_filename):
""" get the name of the file encrypted data should be written to """
return plaintext_filename
@@ -67,7 +68,7 @@ class Encryptor(object):
if self.setup['passphrase']:
self.pname = self.setup['passphrase']
-
+
if self.pname:
if self.setup.cfp.has_option("encryption", self.pname):
self.passphrase = self.setup.cfp.get("encryption",
@@ -182,7 +183,7 @@ class Encryptor(object):
self.logger.error("Error getting encrypted data from %s: %s" %
(fname, err))
return False
-
+
try:
return self.unchunk(plaintext, crypted)
except EncryptionChunkingError:
@@ -317,10 +318,14 @@ class PropertiesEncryptor(Encryptor):
print(lxml.etree.tostring(
elt,
xml_declaration=False).decode("UTF-8").strip())
+ # flush input buffer
+ while len(select.select([sys.stdin.fileno()], [], [],
+ 0.0)[0]) > 0:
+ os.read(sys.stdin.fileno(), 4096)
ans = input("Encrypt this element? [y/N] ")
if not ans.lower().startswith("y"):
elements.remove(element)
-
+
# this is not a good use of a generator, but we need to
# generate the full list of elements in order to ensure that
# some exist before we know what to return
@@ -386,11 +391,11 @@ def main(): # pylint: disable=R0912,R0915
elif setup['interactive']:
logger.error("Cannot decrypt interactively")
setup['interactive'] = False
-
+
if setup['cfg']:
if setup['properties']:
logger.error("You cannot specify both --cfg and --properties")
- raise SystemExit(1)
+ raise SystemExit(1)
if setup['xpath']:
logger.error("Specifying --xpath with --cfg is nonsensical, "
"ignoring --xpath")
@@ -411,7 +416,7 @@ def main(): # pylint: disable=R0912,R0915
if not os.path.exists(fname):
logger.error("%s does not exist, skipping" % fname)
continue
-
+
# figure out if we need to encrypt this as a Properties file
# or as a Cfg file
props = False