Sending and Receiving files in XMPP bot with Python - python

I'm using the following bot (based on xmppy):
import xmpp, os
user = 'uname'
password = 'pass'
server="talk.google.com"
def message_handler(connect_object, message_node):
messageFromCounterPart = message_node.getBody()
connect_object.send( xmpp.Message( message_node.getFrom() ,message_node.getBody()))
jid = xmpp.JID(user)
connection = xmpp.Client(jid.getDomain())
connection.connect(server = (server, 5223))
result = connection.auth(jid.getNode(), password, "LFY-client")
connection.RegisterHandler('message', message_handler)
connection.sendInitPresence()
while connection.Process(1):
pass
How to cause it to receive and send files? Is there special name for stanzas in this case? (like in connection.RegisterHandler('message', message_handler))
Thanks.

Related

LDAP mocking in Python (ldap3 module)

My current task is to do QA Automation on our web app, but I don't want to use real credentials for it (for which we use a LDAP server). My idea was to mock the LDAP server when the web app is in TEST_MODE, and to my luck I found out that 'ldap3' (the python module) that we use for authentication, also supports a mocking function. An example code is here:
from ldap3 import Server, Connection, ALL, ALL_ATTRIBUTES, MOCK_SYNC
REAL_SERVER = 'my_real_server'
REAL_USER = 'cn=my_real_user,ou=test,o=lab'
REAL_PASSWORD = 'my_real_password'
# Retrieve server info and schema from a real server
server = Server(REAL_SERVER, get_info=ALL)
connection = Connection(server, REAL_USER, REAL_PASSWORD, auto_bind=True)
# Store server info and schema to json files
server.info.to_file('my_real_server_info.json')
server.schema.to_file('my_real_server_schema.json')
# Read entries from a portion of the DIT from real server and store them in a json file
if connection.search('ou=test,o=lab', '(objectclass=*)', attributes=ALL_ATTRIBUTES):
connection.response_to_file('my_real_server_entries.json', raw=True)
# Close the connection to the real server
connection.unbind()
# Create a fake server from the info and schema json files
fake_server = Server.from_definition('my_fake_server', 'my_real_server_info.json', 'my_real_server_schema.json')
# Create a MockSyncStrategy connection to the fake server
fake_connection = Connection(fake_server, user='cn=my_user,ou=test,o=lab', password='my_password', client_strategy=MOCK_SYNC)
# Populate the DIT of the fake server
fake_connection.strategy.entries_from_json('my_real_server_entries.json')
# Add a fake user for Simple binding
fake_connection.strategy.add_entry('cn=my_user,ou=test,o=lab', {'userPassword': 'my_password', 'sn': 'user_sn', 'revision': 0})
# Bind to the fake server
fake_connection.bind()
I followed this example with our code, and was successful halfway through it. I extracted the real_server_entries in a json file, and now is part to do the fake connection. So to summarise everything is done until this part:
# Create a MockSyncStrategy connection to the fake server
fake_connection = Connection(fake_server, user='cn=my_user,ou=test,o=lab', password='my_password', client_strategy=MOCK_SYNC)
I am not really sure what to put in the place of user and password.
A part of my code:
_USER_SEARCH_FILTER = "(&(objectClass=user)(cn={}))"
_ALL_USERS_SEARCH_FILTER = "(&(objectCategory=person)(objectClass=user))"
_EMAIL_ATTRIBUTE = "mail"
_DISPLAY_NAME_ATTRIBUTE = "displayName"
_USERNAME_ATTRIBUTE = "cn"
_SEARCH_ATTRIBUTES = (
_EMAIL_ATTRIBUTE, _DISPLAY_NAME_ATTRIBUTE, _USERNAME_ATTRIBUTE)
_LDAP_CONNECTION_ERROR = "Connection to LDAP server %s:%s failed: %s"
_LDAP_SERVER = Server(host=LDAP.host, port=int(LDAP.port), get_info='ALL')
server = _LDAP_SERVER
_CONNECTION = Connection(
server,
LDAP.manager_dn, LDAP.manager_password,
auto_bind=True, client_strategy=RESTARTABLE
)
server.info.to_file('my_real_server_info.json')
server.schema.to_file('my_real_server_schema.json')
if _CONNECTION.search(LDAP.root_dn, _ALL_USERS_SEARCH_FILTER, attributes=_SEARCH_ATTRIBUTES):
_CONNECTION.response_to_file('my_real_server_entries.json', raw=True)
_CONNECTION.unbind()
mock_server = Server.from_definition('mock_server', 'my_real_server_info.json', 'my_real_server_schema.json')
mock_connection = Connection(mock_server, user='???', password='???', client_strategy=MOCK_SYNC)
mock_connection.strategy.entries_from_json('my_real_server_entries.json')
mock_connection.strategy.add_entry('LDAP.root_dn', { #My guess is that here I mock the attributes, but this is also the other problem I am having (check below) })
The other problem I have is that I am not even sure if I can add a fake user, because when I took a look into the real_entries.json file the password is not stored there as an attribute (not even an encrypted version of it) and the only attributes we have are:
`cn` - username
`displayName` - LASTNAME, FIRSTNAME
`mail` - example#mail.com

How to parse credential args to a function handling imaplib protocols

I have a list of emails(mine) that I want to test against a list of passwords(All valid and some none valid of course) using imaplib library. Whenever I test the program ordinarily like in the code below, it works perfectly no errors.
import sys
import imaplib
# connect to host using SSL
imap_host = 'imap.server.com'
imap_port = '993'
imap_user = 'username#email'
imap_pass = 'RightPassword'
imap = imaplib.IMAP4_SSL(imap_host, imap_port)
## login to server
try:
login = imap.login(imap_user, imap_pass)
if login:
print login
except imaplib.IMAP4.error as error:
print error
#
But whenever I run the code such as to parsing credentials through a function to handle the authentication protocols such as the following code below, I get an error saying
"LOGIN command error: BAD ['Missing \'"\'']".
I have tried all sort of things I could find using google and non seem to handle it properly.
"""
E-mail Tester
NB: This is for educational purpose only.
"""
import sys
import imaplib
EMAILS_FILE = open('email_list.txt', 'r')
PASSWORD_FILE = open('pass_list.txt', 'r')
SUCCESS_FILE = open('success.txt', 'a')
EMAILS_FILE_LIST = []
def set_check(_emails):
email = str(_emails)
PASSWORD_FILE.seek(0)
for passwords in PASSWORD_FILE:
password = str(passwords)
# connect to host using SSL
imap_host = 'imap.server.com'
imap_port = '993'
imap = imaplib.IMAP4_SSL(imap_host, imap_port)
## login to server
try:
# print "%s%s" % (email,password)
# print "I got here so far"
# sys.exit()
print "Testing <--> E-mail: %s - Password: %s" % (email, password)
login = imap.login("%s","%s" % (email, password))
if login:
print login
print "OK <---> E-mail: %s\nPassword: %s" % (email, password)
except imaplib.IMAP4.error as error:
print error
for emails in EMAILS_FILE:
EMAILS_FILE_LIST.append(emails)
for email_count in range(0, len(EMAILS_FILE_LIST)):
set_check(EMAILS_FILE_LIST[email_count])
I have tried all kind of suggestions I could find on the internet but non has worked thus far.
I expect imap.login to handle the authentication without the mysterious error output
"LOGIN command error: BAD ['Missing \'"\'']"
login = imap.login("%s","%s" % (email, password))
does not work. It throws an error in Python: TypeError: not all arguments converted during string formatting, because you're providing two strings to one %s.
Why don't you just use imap.login(email, password)? It has the same effect as what you're trying to do.
And what does your password file look like? What is it actually sending? Please provide the log line before it crashes. (anonymizing if necessary, but leaving any punctuation in for help diagnosing)
Okay, so I actually got this fixed by removing trail lines from my strings.
email = str(_emails).rstrip()
PASSWORD_FILE.seek(0)
for passwords in PASSWORD_FILE:
password = str(passwords).rstrip()
the error is caused by trail lines in the strings.

Cannot add file as inline attachment python flask using CID

I have spent hours searching for a solution to no avail. I am trying to include some images in automatically generated emails, and have come up against some problems. I Cannot include the actual url as gmail blocks the images totally, so I am trying to send as attachments and then use Cids to reference the attachments. The issue is I haven't found a way to do this. Any help would be ace.
I am running python 3.6 on with Apache2 on an Ubuntu server. I have tried encoding images in base64 but that didnt work at all. the images in the email simply didnt show up.
def createVoucher(email, expiry):
voucherId = str(uuid.uuid4())
email = email
value = 1
expiryDate = expiry
redeemed = 1
connection = mysql.get_db()
cursor = connection.cursor()
cursor.execute("INSERT INTO vouchers (VoucherID, Value, ExpiryDate, Redeemed, Email) VALUES (%s,%s,%s,%s,%s)", (voucherId, value, expiryDate, redeemed, email))
msgBody = render_template('admin/eVoucherEmail.html', voucherId=voucherId, expiry=expiry)
msg = Message('New Sunday Funday eVoucher Received', sender = MAIL_USERNAME, recipients = [email])
msg.html = msgBody
with app.open_resource("static/img/Facebook.jpg") as fp:
msg.attach("Facebook.jpg", "image/jpg", fp.read())
mail.send(msg)
connection.commit()
So the code posted works fine attaching the file, it's just assigning a content id that I can use where I am struggling.
Here's how I insert an inline jpg using flask_mail.
versions: python=3.7.6, flask=1.1.2, and flask-mail=0.9.1
The "disposition" in message.attach needs to be "inline", and the html for the img should contain "cid:my_cid" as the src.
import uuid
from flask import Flask
from flask_mail import Mail, Message
from pathlib import Path
app = Flask(__name__)
app.config.update(
MAIL_SERVER='smtp.gmail.com', MAIL_PORT=465, MAIL_USE_SSL=True,
MAIL_USERNAME="myfakeemail54858939#gmail.com", MAIL_PASSWORD="myfakepw54858939")
flask_mail = Mail(app)
def test_send_voucher():
to_addr = "myfakeemail54858939#gmail.com"
expiry = "29 February"
voucher_png_path = Path(__file__).parent / "static/Facebook.jpg"
sendVoucherEmail(app, to_addr, expiry, voucher_png_path)
def sendVoucherEmail(app: Flask, to_addr: str, expiry: str, voucher_png_path: Path):
voucher_id = str(uuid.uuid4())
html = f"""<html><head></head><body>
<p>Congratulations on your voucher!<br>Your voucher code is {voucher_id}.
The offer expires on {expiry}.<br>
<img src="cid:voucher_png" width=200>
</p></body></html>"""
with app.app_context():
mail = Mail(app)
message: Message = Message(subject="my subject", sender="myfakeemail54858939#gmail.com",
recipients=[to_addr], html=html)
with app.open_resource(voucher_png_path) as fp:
message.attach(filename="myfilename.png", content_type="image/png", data=fp.read(),
disposition="inline", headers=[['Content-ID', '<voucher_png>']])
mail.send(message)
This example successfully sent an email via gmail, with an inline image "Facebook.jpg," as in the original question.
screenshot of received email

Python FIX API - no response at Logon

I've been trying to set up a connection to the FIX API for the GDAX crpyto exchange, but I can't seem to logon properly. I'm using the code below to generate the message:
import time
import simplefix
import socket
import base64
import hmac
import hashlib
from datetime import datetime
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 4197))
API_KEY = "KEY_GOES_HERE"
PASSPHRASE = "PASSPHRASE_GOES_HERE"
API_SECRET = "SECRET_GOES_HERE"
seq_num = "1"
sendingTime = str(datetime.utcnow()).replace("-","").replace(" ", "-")[:-3]
rawSig = "\x01".join([sendingTime, "A", seq_num, API_KEY, "Coinbase", PASSPHRASE]).encode("utf-8")
hmac_key = base64.b64decode(API_SECRET)
signature = hmac.new(hmac_key, rawSig, hashlib.sha256)
sign_b64 = base64.b64encode(signature.digest()).decode()
msg = simplefix.FixMessage()
msg.append_pair(8, "FIX.4.2")
msg.append_pair(35, "A")
msg.append_pair(49, API_KEY)
msg.append_pair(52, sendingTime)
msg.append_pair(56, "Coinbase")
msg.append_pair(98, "0")
msg.append_pair(108, "30")
msg.append_pair(554, PASSPHRASE)
msg.append_pair(96, sign_b64)
msg.append_pair(8013, "Y")
print(msg.encode())
s.sendall(msg.encode("ascii"))
print(s.recv(4096))
And I'm getting 0 bytes of response from the server. As far as I can tell, the stunnel is working properly (connects and validates certificates successfully, but disconnects after sending my logon message).
Have just tried with a newly generated API key, passphrase and secret but to no avail.
For reference, I was working from the question asked here: How to send FIX logon message with Python to GDAX but I'm not allowed to comment there.
If anyone has any ideas, would be appreciated. Below is an example of the fix message generated, passwords removed in post:
8=FIX.4.2\x019=161\x0135=A\x0149=[KEY_REMOVED]\x0152=20180113-18:24:07.889\x0156=Coinbase\x0198=0\x01108=30\x01554=[PASSPHRASE_REMOVED]\x0196=jueSJHoSNQM2BOCN3KM0mgB2/9tXpICbg4amqDKc2wY=\x018013=Y\x0110=053\x01

Changing Active Directory user password in Python 3.x

I am trying to make a Python script that will open an LDAP connection to a server running AD, take a search entry (in this case a name), search for that entry and change that users password to a randomly generated password (as well as set the option to change password on logon) and then send them an automated secure email containing the new temporary password.
So far I have been able to connect to the server, and search for a single DN which returns. The temporary password is being generated, and an email is being sent (although the password is not hashed, and the email is not secure yet). However, I cannot find any information on where to go from here.
I have found Change windows user password with python however I see that this does not play well with AD, and the other LDAP in Python documentation I have been finding seems to be outdated from 2.x and no longer works. The documentation for ldap3 (https://media.readthedocs.org/pdf/ldap3/stable/ldap3.pdf) also doesnt seem to really mention anything for it, and exhaustive Googling has been fruitless. I am new to this kind of programming having only low level or academic knowledge previously, so this has been a bit frustrating but Python is my strongest language.
----------------EDITED CODE TO CURRENT STATUS-----------------------
#Takes input for name which will be used for search criterion
zid = input("ZID: ")
zid = str(zid).lower()
print(zid)
#Binds session to the server and opens a connection
try:
server = ldap3.Server('ldap://<IP_Address>', get_info=all)
conn = ldap3.Connection(server, '%s#something.com' %zid, password = "<something>", auto_bind=True)
print("Successfully bound to server.\n")
except:
print("Unsucessful initialization of <IP_Address>")
try:
server = ldap3.Server('ldap://<IP_Address>', get_info=all)
conn = ldap3.Connection(server, '%s#something.com' %zid, password = "<something>", auto_bind=True)
print("Successfully bound to server.\n")
except:
print("Unsucessful initialization of <IP_Address>")
try:
server = ldap3.Server('ldap://<IP_Address>', get_info=all)
conn = ldap3.Connection(server, '%s#something.com', password = "<something>", auto_bind=True) %zid
print("Successfully bound to server.\n")
except:
print("Unsucessful initialization of <IP_Address>")
sys.exit(0)
#Searches and prints LDAP entries
try:
base_dn = 'DC=<something>,DC=<something>,DC=<something>,DC=<something>,DC=com'
zid_filter = '(sAMAccountName=%s)' %zid
conn.search(base_dn, zid_filter, attributes=['mail'])
#i.e. "DN: CN=<First Last>,OU=<something>, DC= <something>
user_dn = str(conn.entries)
#i.e. "CN=<First Last>"
front = user_dn.find('C')
back = user_dn.find(',')
user_cn = user_dn[front:back]
#i.e. "<First Last>"
display_name = user_cn[3:]
#i.e. "first.last#<something>.com"
raw_email = str(conn.entries)
front = raw_email.find('mail: ')
back = raw_email.find('#<something>.com')
user_email = raw_email[front + 6:back] + '#<something>.com'
except:
print("Could not search entries")
#Generates random 12 digit alpha-numeric password
try:
new_password = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(12))
print(new_password)
print("New password successfully generated")
except:
print("New password could not be generated")
#Set and replace AD Password
try:
conn.extend.microsoft.modify_password(user_dn, None, new_password)
print ("Active Directory password was set successfully!")
except:
print('Error setting AD password')
sys.exit(0)
Any suggestions on how to get/set the user password and hash the password for security purposes during this whole ordeal? For the email I imagine I can force it to use HTTPS and that would be sufficient, but the connection to the server passing the new_password to I would like to secure.
ldap3 contains a specific method for changing AD password, just add the following after you generated a new password:
dn = conn.entries[0].entry_get_dn() # supposing you got back a single entry
conn.extend.microsoft.modify_password(dn, None, new_password)
This should properly encode the password and store it in AD.
This code is working with Windows 2012 R2 AD:
First, install latest ldap3:
sudo pip3 install ldap
#!/usr/bin/python3
import ldap3
SERVER='127.0.0.1'
BASEDN="DC=domain,DC=com"
USER="user_domain_login_name#domain.com"
CURREENTPWD="current_password"
NEWPWD="new_password"
SEARCHFILTER='(&(userPrincipalName='+USER+')(objectClass=person))'
USER_DN=""
USER_CN=""
ldap_server = ldap3.Server(SERVER, get_info=ldap3.ALL)
conn = ldap3.Connection(ldap_server, USER, CURREENTPWD, auto_bind=True)
conn.start_tls()
print(conn)
conn.search(search_base = BASEDN,
search_filter = SEARCHFILTER,
search_scope = ldap3.SUBTREE,
attributes = ['cn', 'givenName', 'userPrincipalName'],
paged_size = 5)
for entry in conn.response:
if entry.get("dn") and entry.get("attributes"):
if entry.get("attributes").get("userPrincipalName"):
if entry.get("attributes").get("userPrincipalName") == USER:
USER_DN=entry.get("dn")
USER_CN=entry.get("attributes").get("cn")
print("Found user:", USER_CN)
if USER_DN:
print(USER_DN)
print(ldap3.extend.microsoft.modifyPassword.ad_modify_password(conn, USER_DN, NEWPWD, CURREENTPWD, controls=None))
else:
print("User DN is missing!")

Categories

Resources