We use multiple sets of predefined passwords here for test servers - I would like to try a portable Python SSH library (like the one below - spur.py) and get it to try each one in succession - but obviously stop when it is successfully connected or if it can't - ask me for a password. I'm after some sort of recursion with the exception handling I think.
def ssh_connection(user, host):
try:
shell = spur.SshShell(
hostname=host,
port=findport(host),
username=user,
password="abc123",
private_key_file= expanduser("~") + "/.ssh/id_rsa",
missing_host_key=spur.ssh.MissingHostKey.accept
)
shell.run(["true"])
return shell
except spur.ssh.ConnectionError as error:
print error
raise
Coming from the Java world I'd check if the object is null and iterate through a list until the end and then ask for a password. I can't see how to do it in Python... Here's an example I found for the list part:
passwords = ['abc123', 'abc456', 'abc789']
for password in passwords: # Second Example
print 'trying password :', password
As Joe mentioned in the comments you can do something similar:
def ssh_connection(user, host, passwords):
err = None
for password in passwords:
try:
shell = spur.SshShell(
hostname=host,
port=findport(host),
username=user,
password=password,
private_key_file= expanduser("~") + "/.ssh/id_rsa",
missing_host_key=spur.ssh.MissingHostKey.accept
)
shell.run(["true"])
return shell
except spur.ssh.ConnectionError as error:
err = error
if err:
raise error
I would cut it in 2 different functions:
def ssh_connection(user, host, password):
"""
try to connect to user:password#host
return None if failed
"""
try:
shell = spur.SshShell(
hostname=host,
port=findport(host),
username=user,
password=password,
private_key_file=expanduser("~") + "/.ssh/id_rsa",
missing_host_key=spur.ssh.MissingHostKey.accept
)
shell.run(["true"])
return shell
except spur.ssh.ConnectionError as error:
print error
return
def try_connection(user, host, passwords):
"""
try all password in passwords to connect to host
if all failed, ask for password via stdin
"""
for password in passwords:
conn = ssh_connection(user, host, password)
if not conn is None:
break
else:
# we never hit the break: ask for passwd
password = ""
while conn is None:
print "please insert password for %s#%s (empty for exit)" % (user,host)
password = raw_input("passwd:") # todo : insert Term seq for hide passwd and then restor
if password == "":
sys.exit(1)
conn = ssh_connection(user, host, password)
return conn
My comment above got mangled, so here is #Joe Doherty suggestion used with code from Ifthikan - thanks!
def loop_ssh_connection(user, host):
shell = None
passw = ['abc123', 'abc456', 'abc789']
while shell is None:
shell = ssh_connection(user, host, passw)
result = shell.run(["ls", "-l"])
print result.output # prints ouput
def ssh_connection(user, host, passw):
err = None
for password in passw:
try:
shell = spur.SshShell(
hostname=host,
port=findport(host),
username=user,
password=password,
private_key_file= expanduser("~") + "/.ssh/id_rsa",
missing_host_key=spur.ssh.MissingHostKey.accept
)
shell.run(["true"])
return shell
except spur.ssh.ConnectionError as error:
err = error
if err:
raise error
Related
I have been trying to set an account attribute for an Active Directory user but this one attribute cannot be applied the same way as other account attributes (ACE type), im applying the other attributes but "User cannot change password" is the one attribute im unable to do with python programmatically.
This is the code im using to set the password in AD and set attributes for "Password never expires" and "Store password using reversable encyption"
My sources for the code came from here: https://blog.steamsprocket.org.uk/2011/07/04/user-cannot-change-password-using-python/
Someone else other attempt was here but i'm unable to apply it:https://web.archive.org/web/20150829114442/http://www.robertmeany.com/programming/python-and-the-active-directory-security_descriptor/
Hopefully someone may be able to assist me, thank you.
import ldap3
from ldap3 import Connection,Server,ALL,SUBTREE,MODIFY_REPLACE
zid = input("username: ")
zid = str(zid).lower()
print(f'Searching for {zid}')
server = Server('ldaps://IP_OF_MY_AD_SERVER', use_ssl=True, get_info=all)
conn = Connection(server, user='DOMAIN\\USERNAME', password='password', auto_bind=True)
conn.bind()
Path_Root = "DC=domain,DC=Wan"
Filter = f'(&(objectclass=user)(&(sAMAccountName={zid})(!(objectclass=computer))))'
conn.search(search_base = Path_Root,
search_filter = Filter,
search_scope = SUBTREE,
attributes = ["cn", "sAMAccountName", "displayName"]
)
if len(conn.entries) == 1:
USER_DN = conn.response[0].get("dn")
print(USER_DN)
try:
new_password = "A__PASSWORD22"
print(new_password)
print("New password successfully applied")
except:
print("New password could not be applied")
#setting the password:
try:
res = ldap3.extend.microsoft.modifyPassword.ad_modify_password(conn, USER_DN, new_password, old_password=None, controls=None)
res = conn.extend.microsoft.modify_password(USER_DN, new_password)
changeUACattribute = {'userAccountControl': [('MODIFY_REPLACE', 66236)]}
conn.modify(USER_DN, changes=changeUACattribute)
print(conn.result)
print(res)
if res:
print('user %s change password Success.')
print('password: %s' %new_password)
else:
print('user %s change password Failed.')
except Exception as e:
print(f'Error setting AD password: {e}')
This is the code im trying to apply the nTSecurityDescriptor:
import win32security
import win32com.client as win32
domains = ["FQDN","IP_OF_DOMAIN"]
username = "DOMAIN\\USERNAME"
print(username)
password = input("Password: ")
print ("AUTHENTICATING ACCOUNT...")
for d in domains:
try:
token = win32security.LogonUser(
username,
d,
password,
win32security.LOGON32_LOGON_NEW_CREDENTIALS,
win32security.LOGON32_PROVIDER_DEFAULT)
authenticated = True
token.Close()
break
except:
authenticated = False
if (authenticated):
print ("VALID ACCOUNT!")
else:
print ("Wrong username or password!")
authenticated = bool(token)
ChangePasswordGuid = '{ab721a53-1e2f-11d0-9819-00aa0040529b}'
ADS_ACETYPE_ACCESS_DENIED_OBJECT = 0x6
SID_SELF = "S-1-5-10"
SID_EVERYONE = "S-1-1-0"
selfAccount = win32security.LookupAccountSid(None,
win32security.GetBinarySid(SID_SELF))
everyoneAccount = win32security.LookupAccountSid(None,
win32security.GetBinarySid(SID_EVERYONE))
selfName = ("%s\\%s" % (selfAccount[1], selfAccount[0])).strip('\\')
everyoneName = ("%s\\%s" % (everyoneAccount[1], everyoneAccount[0])).strip('\\')
print(USER_DN)
location = USER_DN
user = win32.GetObject("ldap://cn=%s,%s" % (zid, location))
print(user)
sd = user.nTSecurityDescriptor
dacl = sd.DiscretionaryAcl
for ace in dacl:
if ace.ObjectType.lower() == ChangePasswordGuid.lower():
if ace.Trustee == selfName or ace.Trustee == everyoneName:
ace.AceType = ADS_ACETYPE_ACCESS_DENIED_OBJECT
sd.DiscretionaryAcl = dacl
user.Put('ntSecurityDescriptor', sd)
user.SetInfo()
The Error:
sd = USER_DN.nTSecurityDescriptor
AttributeError: 'str' object has no attribute 'nTSecurityDescriptor'
I'm trying to use the example from https://www.safaribooksonline.com/library/view/python-cookbook/0596001673/ch07s14.html to connect to a database that another account on my network has access to. The error I'm given is:
r'DSN=Test'
LookupError: unknown encoding: utf-16le
import win32security, win32con
class Impersonate:
def _ _init_ _(self, login, password):
self.domain = 'bedrock'
self.login = login
self.password = password
def logon(self):
self.handle = win32security.LogonUser(self.login, self.domain,
self.password, win32con.LOGON32_LOGON_INTERACTIVE,
win32con.LOGON32_PROVIDER_DEFAULT)
win32security.ImpersonateLoggedOnUser(self.handle)
def logoff(self):
win32security.RevertToSelf( ) # terminates impersonation
self.handle.Close( ) # guarantees cleanup
if __name__=='__main__':
a = Impersonate('barney', 'bambam')
try:
a.logon() # become the user
try:
# Do whatever you need to do, e.g.,:
print win32api.GetUserName() # show you're someone else
cnxn = pyodbc.connect(
r'DSN=Test;'
)
finally:
a.logoff() # Ensure return-to-normal no matter what
except:
print 'Exception:', sys.exc_type, sys.exc_value
Thanks to Patrick, the documentation helped, here was my solution:
cnxn = pyodbc.connect(
r'DSN=HR;',encoding = 'utf-8',autocommit = True #To set the encoding for the connection
)
cnxn.setencoding(encoding = 'utf-8') #To set the encoding for any queries
I have tried to create a user account in LDAP. Sample code to connect the LDAP
conn = ldap.initialize(bind_url) # Connect LDAP service
conn.set_option(ldap.OPT_REFERRALS, 0)
conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
conn.set_option(ldap.OPT_DEBUG_LEVEL, 255)
conn.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_DEMAND)
conn.protocol_version = ldap.VERSION3 # Default version for LDAP protocol used
conn.set_option(ldap.OPT_REFERRALS, 0)
ldap_user = "CN=%s,%s" % (bind_username, base_dn)
conn.simple_bind_s(ldap_user, bind_password) # Authentication occurs
I can able to connect to LDAP and create a user in disable mode (UserAccountControl == 514). When i tried to set password or enable account. There will be error like
"{'info': '0000001F: SvcErr: DSID-031A12D2, problem 5003 (WILL_NOT_PERFORM), data 0\n', 'desc': 'Server is unwilling to perform'}"
I am usin python-ldap library. Here is my sample code to add and enable user account
user_attrs['objectclass'] = ['top', 'person', 'organizationalPerson', 'user']
user_attrs['cn'] = username
user_attrs['givenName'] = username
user_attrs['sn'] = username
user_attrs['displayName'] = username
user_attrs['userAccountControl'] = '514'
user_attrs['mail'] = str(user["email"])
user_attrs['department'] = str(user["department"])
user_ldif = modlist.addModlist(user_attrs)
add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password])]
# 512 will set user account to enabled
mod_acct = [(ldap.MOD_REPLACE, 'userAccountControl', '512')]
# Add the new user account
try:
ldap_connection.add_s(user_dn, user_ldif)
except ldap.LDAPError, error_message:
print "Error adding new user: %s" % error_message
return False
# Add the password
try:
ldap_connection.modify_s(user_dn, add_pass)
except ldap.LDAPError, error_message:
print "Error setting password: %s" % error_message
return False
# Change the account back to enabled
try:
ldap_connection.modify_s(user_dn, mod_acct)
except ldap.LDAPError, error_message:
print "Error enabling user: %s" % error_message
return False
print "User created %s" % username
Anyone please let me know if there any solution or fix.
My ldap.conf in ubuntu:
TLS_CACERT /etc/ssl/certs/ca-certificates.crt
I found the following blog post to be very helpful in this regard.
http://marcitland.blogspot.com/2011/02/python-active-directory-linux.html
Looks like what you need is as follows:
unicode_pass = unicode('\"' + password + '\"', UNICODE_STANDARD)
password_value = unicode_pass.encode(UNICODE_ENCODING)
add_pass = [(ldap.MOD_REPLACE, 'unicodePwd', [password_value])]
when i run:
def conn_string(cmd, switch_IP, uname, pword):
try:
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(switch_IP, username=uname, password=pword, port=22)
stdin, stdout, stderr = ssh.exec_command(command=cmd, timeout=60)
output = stdout.read()
current_res = output.decode('ascii')
print(current_res)
return current_res
except paramiko.AuthenticationException:
print("\n Authentication Failed!")
exit()
except paramiko.SSHException:
print("\n Issues with SSH service!!!")
exit()
except BaseException as e:
print(str(e))
exit()
if __name__ == '__main__':
switch_IP = input("Enter switch IP address: ")
u_name = "abc"
p_word = "xyz"
res = conn_string("show configuration snapshot", switch_IP, u_name, p_word)
i get SSH exception: Channel Closed
but when i run:
conn = paramiko.SSHClient()
conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
conn.connect(switch_IPAddress, port=22, username=u_name,
password=p_word,
look_for_keys=False, allow_agent=False)
con = conn.invoke_shell()
output = con.recv(65535)
final_output = output.decode('ascii')
print(final_output)
con.send("show configuration snapshot")
time.sleep(.5)
output = con.recv(65535)
final_output = output.decode('ascii')
print(final_output)
it only shows me device info and the command without any output or errors
The cmd works fine on the switch console.
if I use the same code on a cisco switch(with diff command of course) it works perfect but fails on the alcatel switch. Please help me out.
I have the following script, how to make it work on apache (I installed python server and all required configurations), now my problem is where i add def index(): i get error of indentation :(, you have solution for this problem ? and how to change:
port = 22
user = "user"
password = "password"
host = "127.0.0.1"
To $_GET ? (http://localhost/test.py?host=127.0.0.1&port=22&user=test&password=123)
import paramiko
import sys, os
import socket
import re
# - - - - - - - - - - - - - - - - #
# SSH Checker #
# - - - - - - - - - - - - - - - - #
#def index():
def is_work_sshd(host, dPort=22):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(20)
try:
sock.connect((host, dPort))
except:
return 1
sock.close()
return 0
def check_server(host, user, password, port=22):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#proxy = paramiko.ProxyCommand("127.0.0.1:8118")
if is_work_sshd(host,port): return 2
try:
ssh.connect(host, username=user, password=password, port=port)
ssh.close()
except:
return 1
return 0
def index():
port = 22
user = "user"
password = "password"
host = "127.0.0.1"
ret = check_server(host, user, password, port)
if not ret:
return "CONNECT"
elif ret == 1:
return "FAILED"
else:
return "FAILED"
Error message:
root#www:/var/www# python t.py
File "t.py", line 49
ret = check_server(host, user, password, port)
^
You should add def index(): before the line port = 22:
return 0
def index():
return "<html><body>Hello, world.</body></html>"
port = 22
Note: In Python, indentation is part of the syntax. So make sure you indent properly and correctly. See also https://docs.python.org/2/tutorial/introduction.html#first-steps-towards-programming
make sure the code editor which you use always uses tabs or spaces for indenting and don't mix the two. Editors which show whitespace work well, editors which clean up indentation automatically for Python code are better.
EDIT Here is the correct code:
def check_server(host, user, password, port=22):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#proxy = paramiko.ProxyCommand("127.0.0.1:8118")
if is_work_sshd(host,port): return 2
try:
ssh.connect(host, username=user, password=password, port=port)
ssh.close()
except:
return 1
return 0
def index():
port = 22
user = "user"
password = "password"
host = "127.0.0.1"
ret = check_server(host, user, password, port)
if not ret:
return "CONNECT"
elif ret == 1:
return "FAILED"
else:
return "FAILED"