python ldap attribute query - python

I am trying to modify a python based-authenticator for murmur (voip software) to work with my ldap tree.
The LDAP authenticator is available at:
http://www.winex.org/linux/zealot/src/mumble-scripts/Authenticators/LDAP/LDAPauth.py
It works, but not quite with my ldap layout, so I have to modify it a bit. I know an approach that could work, but unfortunately I have no more knowledge about python than what I learned from google (I have some other programming expertise though).
My ldap layout looks like this:
charName=xxx, ou=people, dc=xxx, dc=com
Under this there are attributes stored such as userPassword and login among others.
The python script above is tailored to use a ldap bind to authenticate. In this case I would have to bind as "charName=logindatafromapp, ou=people, dc=xxx, dc=com". Unfortunately people don't log in with "charName" but with "login" which is an attribute, but isn't identical with "charName".
I do not know a way to bind to an attribute, so here is my idea:
I first bind as ldap admin and perform a search over all entries for "logindatafromapp" and match that value against "login". If a match is found I grab the matching "charName" and re-bind with that charName as originally intended.
I am currently stuck on querying the "charName" value and at assigning that value to a variable, so i could use it in a second ldap bind (google didn't really help me).
Here is my code:
ldap_conn = ldap.initialize(ldap_uri, 0)
ldap_conn.bind_s("cn=admin,dc=xxxxxxxx,dc=com","pass")
res = ldap_conn.search_s('ou=people,dc=xxxxxx,dc=com', ldap.SCOPE_ONELEVEL,'login=trony',['charName'])
print(res)
It then prints "[('charName=Trony,ou=people,dc=xxxxxxx,dc=com', {'charName': ['Trony']})]".
(the "login=trony") is a temporary filter that I would have to replace with the applogin var. My problem is now how can I assign "Trony" (in this case) to a variable? The output seems to be a special struct?

'Trony' is in
res[0][1]['charName'][0]
You take the first element of the list — it's a tuple; then the first element of the tuple; it's a dictionary; then value of the dictionary for the key 'charName'; it's a list once again; and then the first element of the list.

There are at least two alternatives:
Use the method you describe to search for the entry using the information you have, in this case the value of the login attribute as entered by the user and then using the DN that was found in a simple or SASL bind or
Use SASL with identity mapping to map the authId (the value of the login attribute) in such a way that a SASL bind will succeed where only the value of the login attribute is known
The first method requires a search and then a bind, the second might require that user entries have reversible passwords (AES is a good encryption scheme for that purpose) depending on the SASL mechanism that is chosen. Using SASL with the DIGEST-MD5 mechanism would provide a way to map identities as described (all professional-quality LDAP servers support such a mapping mechanism) and would obviate the need to send a password in the clear over a network, but has the disadvantage of not being as secure as using simple bind where the password is stored as a salted SHA-2 digest. Although DIGEST-MD5 should not be used because it requires reversible passwords and thus is not as secure as using the strong SHA-2 (with salt) it is available for applications that require it.

Related

How to protect program with unique licence key on python?

I need to set key on my program, which would be an exe file. I want to see:
User clicks on exe file then program requers key, user paste the key and key never asks again. User can't send this acivated exe to other users also other users can't use this key again.
or suggest better idea.
p. c. exe file is console app
You can for instance use the platform module to (almost) uniquely identify a machine. They key can then be the sha256 hexdigest of this identifier viewed as a string, like this:
import hashlib
import platform
# Only an example, you can add whatever you want provided by the platform module to identify the machine
identifier = platform.platform()
key = hashlib.sha256(identifier.encode()).hexdigest()
Pros:
Can't be shared
Isn't reusable
Cons:
Doesn't respect Kerchkoff's principle
Hence, it means that your system is secure as long as the user does not know how to compute the identifier by themselves.
You can ellaborate on this model, using maybe a server of your own. For instance, you can compute a key on your server using the identifier you computed and a secret string.
Pros:
You don't have to store a random key for each user, you just need to have access to its identifier
Cons:
If your identifier isn't accurate enough, two users may have the same key
To solve this problem, you can define a random string for each user that you append to their identifier, but it means that you have to store this random string for each user.
Note also that the last two solutions make use of an external server. Hence, you assume that you will be able to do network requests.

AES Key Generation from variables

I want to code a custom key generator in Python. This key will be used as an input (along with the plain text) to AES algorithm for encryption (I will probably use pycrypto or m2crypto libraries for that).
But the key generator has to be custom, as it would generate the key based on the string that would be supplied by the user.
str = date + case-id + name
where:
date = current date when a case was submitted
(we work on separate security analysis cases, submitted on our ticketing tool)
name = person handling the case
case-id = the ticket id with which it was submitted.
This same key needs to be known to the decryptor (on a different system) so that it can decrypt the data.
So the key will have to be fixed for a specific set of date name and case-id for a specific order and will only be different if any of these 3 change in value or order and should not be random every time.
I've gone through some of stackoverflow articles, where it is suggested to use
random_key = os.urandom(16)
but I don't believe this will serve my purpose.
Suggestion on some articles where to start with if I want to design a key generator from scratch, or some pointers on existing libraries will be highly appreciated.
You're looking for a Password hashing algorithm, such as Argon2 or PBKDF2. It will allow you to deterministically extend the 'password' generated from the input values into a suitable key.
However, note that your passwords may still be very weak. I suspect that there is a strong correlation between case-id and date. Names are probably only a small list of people easily found out. Also, isn't this data sent along with the encrypted data by your system? This makes using it as a password a bad idea.

Protocols list in Twisted app

I would like to know which is best way to manage the protocols active in Twisted or if there is no concrete way.
In my current app I created a dictionary where there are two fields. At one I put the remote user and the local user to another. Both fields are lists so I can add several items.
The method I'm using is the following. First I check by a try-except if the dictionary exists. If there is no dictionary, I create it.
try:
if self.factory.active_protocols:
log.msg('Active protocols dictionary already created')
except Exception as e:
log.err(e)
self.factory.active_protocols = {}
self.factory.active_protocols.setdefault('localUsr', [])
self.factory.active_protocols.setdefault('remoteUsr', [])
Then I check if the local user is in the local users list. If there is no user I adds it to the list of local users. If the list exists, it throws an error.
if sUsername in self.factory.active_protocols['localUsr']:
log.err('Client already logged in')
raise UnauthorizedLogin('Client already logged in')
else:
# Attach local user to active protocols list.
self.sUsername = sUsername
self.factory.active_protocols['localUsr'].append(self.sUsername)
If the conditions are right the remote user is also added to the list of remote users using the following code.
# If time is correct, attach remote user to active_protocols
self.factory.active_protocols['remoteUsr'].append(remoteUsr)
When I disconnect users, I delete the lists using the following code.
if self.sUsername in self.factory.active_protocols['localUsr']:
self.factory.active_protocols['localUsr'] = []
if self.remoteUsr in self.factory.active_protocols['remoteUsr']:
self.factory.active_protocols['remoteUsr'] = []
Is there a more correct way to do it? Should implement some special kind of dictionary? To Create a list? Does using a proprietary method of Twisted?
I have been looking for information about internet and I have not found anything conclusive about it.
Thank you!
No, there is no special type of list or dictionary in Twisted you can use for this.
Twisted's job is turning network events into method calls on your objects. Once you you are implementing those methods on those objects, as much as possible, you want to use regular Python data structures. There are certain things in Twisted, like Deferreds, which are data structures you can use to implement certain asynchronous data-flow patterns, but for something as simple as a basic observer pattern with multiple entities in a list, regular lists and dictionaries and such are just fine.

Auto increment property with py2neo (Neo4j)?

I'm using flask with py2neo for my Rest service , I have a user node with the label "User".
how to autoincrement id for the "User" label , in neo4j using py2neo?
You don't, and you probably shouldn't. Neo4j already provides an internal id field that is an auto-incrementing integer. It isn't a property of the node, but is accessible via the id() function, like this:
MATCH (n:Person)
RETURN id(n);
So whenever you create any node, this already happens automatically for free by neo4j, and isn't done by py2neo.
If you need a different type of identifier for your code, I'd recommend something that's plausibly globally unique, like a UUID which is very easy to do in python, rather than an auto-incrementing integer.
The trouble with auto-incrementing numbers as IDs is that since they have a pattern to them (auto-incrementing) people come to rely on the value of the identifier, or come to rely on expectations of how the ID will be assigned. This is almost always a bad idea in databases. The sole purpose of the identifier is to be unique from everything else. It doesn't mean anything, and in some cases isn't even guaranteed not to change. Avoid embedding any reliance on any particular value or assignment scheme into your code.
That's why I like UUIDs, is because their assignment scheme is essentially arbitrary, and they clearly don't mean anything -- so they don't tempt designers to do anything clever with them. :)

Exploiting hash function in python

I made a topic about the built-in python hash function: Old python hashing done left to right - why is it bad?
The previous topic was about why it was bad for encryption, because we have an application called Gruyere which is filled with security holes, and it uses the hash() to encrypt cookies.
# global cookie_secret; only use positive hash values
h_data = str(hash(cookie_secret + c_data) & 0x7FFFFFF)
c_data is a username; cookie_secret is salt (which is just '' by default)
I have implemented a more secure encryption method using md5 hashing with salt, but one excercise is to beat this old encryption and I still cannot understand how :-( I've read the string_hash code from python sourcecode but it's not documented and I can't figure it out.
EDIT: The idea is to write a program which can create a valid cookie any valid user, so I think I need to find out cookie_secret somehow
Zack described the answer already in your last question: It's easy to find a collision.
Let's say you save hash("pwd") in the database (that you actually do something different doesn't matter. Now, if you enter "pwd" in the site, you can enter. But how is this checked? Again, the hash of "pwd" is token, and compared to the value in the database. But what if there is a second string, say "hello", and hash("hello") == hash("pwd")? Then you could also use "hello" as password. So to beat the encryption, you don't need to find "pwd", you just need any string which has the same hash-value. You can just search for such a string brute-force (and I guess you can do some optimizations based on the knowledge of the source of hash)

Categories

Resources