ginsu-0.8.0: ginsu-mdk
#!/usr/bin/env python2
import xmlrpclib, sys, getopt, os, getpass, string
defaultserver= 'https://yammer.net:1115/mdk.psp'
def usage():
print """usage:
Normal usage:
%(cmd)s [-m URI]
interactive dialog to issue and write a key
More fine-grained commands:
%(cmd)s [-m URI] ls
list available domains
%(cmd)s [-m URI] gen USER@DOM.AIN [-r PR] [-u PU] -e EM /FN
generate key
%(cmd)s [-m URI] get USER@DOM.AIN [-r PR] [-u PU]
issue a key (you must have the account password)
%(cmd)s [-m URI] regen USER@DOM.AIN [-r PR] [-u PU]
reissue a key (you must have the account password)
%(cmd)s [-m URI] revoke USER@DOM.AIN
revoke a key (you must have the account password)
%(cmd)s [-m URI] change-password USER@DOM.AIN
change the account password for a key
%(cmd)s [-m URI] reset-password USER@DOM.AIN
reset the account password for a key and email it to the key's owner
-m URI the Marmaduke server URI (default: %(defaultserver)s)
-r PR write the pRivate key to file PR instead of key directory
-u PU write the pUblic key to file PU instead of key directory
-e EM email address; passwords are sent to this address
/FN full name of user, preceded by a slash
Marmaduke command line client version 1.0pre.2161,
generated on Yammer.
""" % {'cmd': sys.argv[0], 'defaultserver': defaultserver}
def handleLs(server, args):
domains= server.listDomains()
print string.join(domains)
def handleGen(server, args):
requiredArguments('key email fullname'.split(), args)
privPath= '%(galedir)s/%(key)s.gpri' % args
if args.has_key('priv') and args['priv'] is not None:
privPath= priv
pubPath= '%(galedir)s/%(key)s.gpub' % args
if args.has_key('pub') and args['pub'] is not None:
pubPath= pub
keys= server.generateKey(args['key'], args['fullname'], args['email'])
saveKeys(keys, privPath, pubPath)
kgenMsg()
def handleGet(server, args):
requiredArguments('key'.split(), args)
privPath= '%(galedir)s/%(key)s.gpri' % args
if args.has_key('priv') and args['priv'] is not None:
privPath= priv
pubPath= '%(galedir)s/%(key)s.gpub' % args
if args.has_key('pub') and args['pub'] is not None:
pubPath= pub
passwd= getPassword()
keys= server.issue(args['key'], passwd)
saveKeys(keys, privPath, pubPath)
def handleRegen(server, args):
requiredArguments('key'.split(), args)
privPath= '%(galedir)s/%(key)s.gpri' % args
if args.has_key('priv') and args['priv'] is not None:
privPath= priv
pubPath= '%(galedir)s/%(key)s.gpub' % args
if args.has_key('pub') and args['pub'] is not None:
pubPath= pub
passwd= getPassword()
keys= server.reissue(args['key'], passwd)
saveKeys(keys, privPath, pubPath)
def handleRevoke(server, args):
requiredArguments('key'.split(), args)
privPath= '%(galedir)s/%(key)s.gpri' % args
pubPath= '%(galedir)s/%(key)s.gpub' % args
passwd= getPassword()
keys= server.revoke(args['key'], passwd)
eraseKeys(privPath, pubPath)
def handleChPwd(server, args):
requiredArguments('key'.split(), args)
repeat= 1
while repeat:
oldpasswd= getPassword('Current password: ')
newpasswd1= getPassword('New password: ')
newpasswd2= getPassword('Re-enter new password: ')
if newpasswd1 != newpasswd2:
sys.stderr.write('new passwords do not match\n')
else:
repeat= 0
server.changePassword(args['key'], oldpasswd, newpasswd1)
sys.stderr.write('password changed\n')
def handleRePwd(server, args):
requiredArguments('key'.split(), args)
repeat= 1
server.forgotPassword(args['key'])
sys.stderr.write('password reset and emailed to user\n')
def handleWizard(server, args):
domains= server.listDomains()
print 'Available domains: ' + string.join(domains)
print
repeat= 1
user, fullname, email= None, None, None
while repeat:
print '\nWhat username do you want? Include the domain (example, ' + \
'user@whatever.com).'
user= readLine()
if user.find('@') < 1:
user= user + '@' + domains[0]
print 'Adding default domain -> ' + user
args['user']= user
print '\nWhat is your full name?'
if fullname is not None:
print '[hit enter to use "%s"]' % fullname
fullname= readLine(fullname)
print '\nWhat is your email address?'
if email is not None:
print '[hit enter to use "%s"]' % email
email= readLine(email)
try:
keys= server.generateKey(user, fullname, email)
print
saveKeys(keys, '%(galedir)s/%(user)s.gpri' % args,
'%(galedir)s/%(user)s.gpub' % args)
kgenMsg()
repeat= 0
except xmlrpclib.Fault, fault:
handleFault(fault)
if fault.faultCode == 111:
print 'If you have the password for %s, enter it now.' % user
print 'Otherwise, just hit enter.'
if regenWizard(server, user, args['galedir']):
return
print
def regenWizard(server, keyid, galedir):
repeat= 1
while repeat:
password= getPassword('password for %s: ' % keyid)
if len(password) == 0:
return 0
try:
keys= server.reissue(keyid, password)
print
saveKeys(keys, '%(galedir)s/%(keyid)s.gpri' % locals(),
'%(galedir)s/%(keyid)s.gpub' % locals())
repeat= 0
return 1
except xmlrpclib.Fault, fault:
handleFault(fault)
def kgenMsg():
sys.stderr.write('\nKey generated. Watch your mailbox for an account ' + \
'password;\nthis will be needed if you want to reissue or revoke\n' + \
'your key, and can also be used to log in to the appropriate instance\n' + \
'of Yammer.\n')
def eraseKeys(privPath, pubPath):
sys.stderr.write('\n')
if os.path.exists(privPath):
sys.stderr.write('erasing private key %s\n' % privPath)
os.unlink(privPath)
if os.path.exists(pubPath):
sys.stderr.write('erasing public key %s\n' % pubPath)
os.unlink(pubPath)
def saveKeys(keys, privPath=None, pubPath=None):
sys.stderr.write('writing private key to %s\n' % privPath)
mkdirDashP(privPath)
p= open(privPath, 'w')
p.write(keys['private'].data)
p.close()
mkdirDashP(pubPath)
sys.stderr.write('writing public key to %s\n' % pubPath)
p= open(pubPath, 'w')
p.write(keys['public'].data)
p.close()
def mkdirDashP(filename):
path= os.path.dirname(filename)
if not os.path.exists(path):
os.makedirs(path)
def requiredArguments(reqs, args):
a= [x for x in reqs if x not in args or args[x] is None]
if len(a) > 0:
print 'missing argument(s): ' + string.join(a)
usage()
sys.exit(1)
def getPassword(prompt= None):
if prompt is None:
prompt= 'Password: '
return getpass.getpass(prompt)
def readLine(default= None):
a= sys.stdin.readline().strip()
if len(a) == 0 and default is not None:
return default
return a
def getGaleDir():
return os.environ['HOME'] + '/.gale/auth/private'
def getServer(mdkuri):
return xmlrpclib.ServerProxy(mdkuri)
def handleFault(fault):
sys.stderr.write('\n%s\n\n' %
(fault.faultString))
commands= {'ls': handleLs, 'gen': handleGen, 'regen': handleRegen,
'get': handleGet, 'revoke': handleRevoke,
'change-password': handleChPwd, 'reset-password': handleRePwd}
argu= sys.argv[1:]
dashes, squares= [], []
i= 0
while i < len(argu):
if argu[i].startswith('-'):
dashes.append(argu[i])
if argu[i][1] != 'h':
dashes.append(argu[i+1])
i= i + 1
i= i + 1
else:
squares.append(argu[i])
i= i + 1
opts, args= getopt.getopt(dashes + squares, 'm:r:u:e:h')
mdkserver, priv, pub, email= defaultserver, None, None, None
for opt, value in opts:
if opt == '-m':
mdkserver= value
if opt == '-r':
priv= value
if opt == '-u':
pub= value
if opt == '-e':
email= value
if opt == '-h':
usage()
sys.exit(1)
cmd= None
if len(args) > 0:
cmd= args[0]
fullname= [x[1:] for x in args if x.startswith('/')]
if len(fullname) > 0:
fullname= fullname[0]
else:
fullname= None
key= [x for x in args if not x.startswith('/') and x.find('@') > 0]
if len(key) > 0:
key= key[0]
else:
key= None
try:
server= getServer(mdkserver)
galedir= getGaleDir()
if cmd is not None and commands.has_key(cmd):
commands[cmd](server, locals())
else:
handleWizard(server, locals())
except xmlrpclib.Fault, fault:
handleFault(fault)
sys.exit(fault.faultCode)