As far as I know, MoinMoin does not have support for PAM authentication. I use MoinMoin 1.5.2 (last package for ubuntu sarge). I needed to join current authentication system and not to create a new one. So I copied MoinMoin.auth.moin_cookie method to the new file (pam_auth.py) and modified it. My version of the method is called pam_cookie.
pam_auth.py
# -*- coding: iso-8859-1 -*- """ @copyright: 2007 by Pavel Hančar <hancar@email.cz> @license: GNU GPL, see COPYING for details. """ import PAM import Cookie from MoinMoin import user class PAMInternalError(Exception): """ Internal error in PAM authentication """ def pam_cookie(request, **kw): def pam_cookie_conv(auth, query_list, userData): resp = [] for i in range(len(query_list)): query, type = query_list[i] if type == PAM.PAM_PROMPT_ECHO_ON: val = kw.get('name') resp.append((val, 0)) elif type == PAM.PAM_PROMPT_ECHO_OFF: val =kw.get('password') resp.append((val, 0)) elif type == PAM.PAM_PROMPT_ERROR_MSG or type == PAM.PAM_PROMPT_TEXT_INFO: resp.append(('', 0)) else: return None return resp # authenticate via the MOIN_ID cookie if kw.get('login'): name = kw.get('name') password = kw.get('password') auth_pam = PAM.pam() auth_pam.start('passwd') auth_pam.set_item(PAM.PAM_USER, name) auth_pam.set_item(PAM.PAM_CONV, pam_cookie_conv) try: auth_pam.authenticate() auth_pam.acct_mgmt() except PAM.error, resp: pass except: raise PAMInternalError('PAM internal error\n') else: u = user.User(request, name=name, password=password, auth_method='login_userpassword') if u.valid: request.user = u # needed by setCookie request.setCookie() return u, False return None, True if kw.get('logout'): # clear the cookie in the browser and locally. Does not # check if we have a valid user logged, just make sure we # don't have one after this call. request.deleteCookie() return None, True try: cookie = Cookie.SimpleCookie(request.saved_cookie) except Cookie.CookieError: # ignore invalid cookies, else user can't relogin cookie = None if cookie and cookie.has_key('MOIN_ID'): u = user.User(request, id=cookie['MOIN_ID'].value, auth_method='pam_cookie', auth_attribs=()) if u.valid: return u, False return None, True
Then I inserted two lines to wikiconfig.py:
from pam_auth import pam_cookie . . auth=[pam_cookie]
Now it works -- only those users, which have an account in PAM, can create their MoinMoin account and login. But this mechanism is not ideal. The creating of MoinMoin accounts is possible only by useless writing of two passwords and e-mail. Maybe I will copy and modify macro UserPreferences. It means to reimplement some method(s) in userform.
I am sorry, I didn't test it properly. The pam_auth above has a defect. There is possible to create an account, which one can not login because of PAM.
This is better:
pam_auth.py
# -*- coding: iso-8859-1 -*- """ @copyright: 2007 by Pavel Hančar <hancar@email.cz> @license: GNU GPL, see COPYING for details. """ import PAM,Cookie from MoinMoin import user,wikiutil,i18n class PAMInternalError(Exception): """ Internal error in PAM authentication """ def pam_cookie(request, **kw): def pam_cookie_conv(auth, query_list, userData): resp = [] for i in range(len(query_list)): query, type = query_list[i] if type == PAM.PAM_PROMPT_ECHO_ON: val = kw.get('name') resp.append((val, 0)) elif type == PAM.PAM_PROMPT_ECHO_OFF: val =kw.get('password') resp.append((val, 0)) elif type == PAM.PAM_PROMPT_ERROR_MSG or type == PAM.PAM_PROMPT_TEXT_INFO: resp.append(('', 0)) else: return None return resp # authenticate via the MOIN_ID cookie f=open("pamlog","w"); f.write(str(kw)+"\n") f.close # login or create account if kw.get('login') or request.form.has_key("create"): name = kw.get('name') password = kw.get('password') auth_pam = PAM.pam() auth_pam.start('passwd') auth_pam.set_item(PAM.PAM_USER, name) auth_pam.set_item(PAM.PAM_CONV, pam_cookie_conv) try: auth_pam.authenticate() auth_pam.acct_mgmt() except PAM.error, resp: request.deleteCookie() if "getText" in dir(request): _=request.getText msg=_("PAM error: invalid user name or password") page = wikiutil.getSysPage(request, 'UserPreferences') page.send_page(request, msg=msg) except: raise PAMInternalError('PAM internal error\n') else: if kw.get('login'): u = user.User(request, name=name, password=password, auth_method='login_userpassword') if u.valid: request.user = u # needed by setCookie request.setCookie() return u, False return None, True if kw.get('logout'): # clear the cookie in the browser and locally. Does not # check if we have a valid user logged, just make sure we # don't have one after this call. request.deleteCookie() return None, True try: cookie = Cookie.SimpleCookie(request.saved_cookie) except Cookie.CookieError: # ignore invalid cookies, else user can't relogin cookie = None if cookie and cookie.has_key('MOIN_ID'): u = user.User(request, id=cookie['MOIN_ID'].value, auth_method='pam_cookie', auth_attribs=()) if u.valid: return u, False return None, True
These lines are needed in wikiconfig.py
from pam_auth import pam_cookie . . auth=[pam_cookie]
and good is also
user_form_remove=["password2"] user_form_disable=["name","password"]
because it's not configurable, it's in PAM.
But if you don't want repeat password while creating account (which is useless because it's proved by PAM), you need new implementation of action userform. So put the file userform.py into directory data/plugin/action/.
userform.py
# -*- coding: iso-8859-1 -*- """ @copyright: 2007 by Pavel Hančar <hancar@email.cz> @license: GNU GPL, see COPYING for details. """ from MoinMoin import userform from MoinMoin.Page import Page def execute(pagename,request): form=request.form if form.has_key("create"): form["password2"]=form["password"] savemsg = userform.savedata(request) Page(request, pagename).send_page(request, msg=savemsg)
What about the copyright? Maybe Jürgen Hermann is more the author of this action than me, because in wikiaction.py is this:
@copyright: 2000-2004 by Jürgen Hermann <jh@web.de> @license: GNU GPL, see COPYING for details.
If you reused code from Juergen, but added own code, too, then just add yourself to the (C) line.
How about doing this for 1.6?
This means that the wiki needs to run as root which is highly insecure. Much better would be to write an auth method that uses a checkpasswd server or such. -- JohannesBerg 2008-03-18 11:54:17
We wanted PAM-based auth for our hackerspace's internal wiki so I've had another go at this. I'm attaching a patch against the 1.9 branch for a pam_login auth method. moin-1.9-pamauth.patch If accepted, I'm happy to write up a Howto on the wiki here as well.
It is correct that if you're using pam_unix with a shadow password, moin needs to run with elevated privileges. However it doesn't need to run as root, you can run as a group with read-only access to the shadow file, as documented by mod_auth_pam authors here: http://pam.sourceforge.net/mod_auth_pam/shadow.html Some distros (Debian-based, maybe others?) come preconfigured with a 'shadow' group for this purpose. As the mod_auth_pam author says, you are weakening your system security, albeit only a little.
You also don't need any elevated privileges at all if you're using PAM with a different backend (LDAP, windows, etc.)
Cheers (moinmoin is a great wiki btw, very happy to have such a quality Python-based option!) -- -- AngusGratton 2012-08-05 09:49:28