Fool + Money = Fool - Money

Powered By Php

Mysql Logo

Powered By Apache

Python NSS netgroups interface
Posted by Joel (joelh-website at planetjoel dot com) on Tuesday, 2nd of December, 2008 - 09:16:09 PM

While working on my python test-sudoers script I realised I would need to query NSS netgroups. I went looking for a python module that would do that, and I found the nis module but this wasn't really what I was after. The NIS module allows you to query NIS netgroups if you have a NIS domain set up - we have an LDAP server that serves out netgroups. This sounded like a good opportunity to attempt to write my first C python extension!

The python C extension framework is actually fantastically easy to use even for someone who is not a natural C programmer like myself. This gotcha's are around reference counters since you have to keep the garbage collector aware of what you are doing. But that is not too bad. What did throw me off was a simple valgrind run of a very simple test case produced 4KB's or so of memory leak. I spent a while trying to fiddle and fix the reference count stuff to see if I was doing something wrong and leaving something with two many references. By causing it to crash I was able to determine that yes I had the minimal number of reference counters so I had a different problem. I ran "valgrind getent netgroup LinuxAdmins" and there it was - the NSS libraries themselves were leaking memory. Interesting.

Here is my python NSS netgroups module. To compile it download and run "python setup.py build" then "python setup.py install". You should already have NSS setup to query netgroup information ("getent netgroup somegroup" should work). For further help simply run pythons help() routinue on the module.

Python NSS netgroups module v0.11

UPDATE: Fixed some INCREF bugs thanks to bioinformed

Add a comment

Comments

All comments owned by their poster.

Name: Bioinformed
Email: jacobs at bioinformed dot com
Time: 3/12/08 - 08:53:37

Your code is missing Py_INCREFs on the "return Py_True" and "return Py_False". Also, here is a simpler ctypes version that works on Linux with Python 2.5 or newer:

from ctypes import CDLL,byref,c_char_p

def getgroup(name):
'''
getgroup(netgroupName)

Retrieve a netgroup using NSS routines
Returns a list of matching (host,user,domain) tuples
'''
host,user,domain = c_char_p(None),c_char_p(None),c_char_p(None)

libc=CDLL("libc.so.6")

libc.setnetgrent(name)

try:
groups = []
while libc.getnetgrent(byref(host), byref(user), byref(domain)):
groups.append( (host.value,user.value,domain.value) )
return groups

finally:
libc.endnetgrent()

def innetgr(netgroup,host=None,user=None,domain=None):
'''
innetgr(netgroup,host=host,user=user,domain=domain) -> bool

Ask whether a host/user/domain tuple is part of a netgroup
If no host,user or domain is passed then it returns true if the netgroup exists
'''
libc=CDLL("libc.so.6")
return bool(libc.innetgr(netgroup,host,user,domain))