Scenario:
*) Zimbra 4.5 running on CentOS, configured with internal authentication
*) zimbra_posixaccount and zimbra_samba Admin Extensions installed
*) Samba PDC on another machine using the zimbra ldap backend for users and groups
*) No time to study and try how to extend UI using APIs, Zimlets and so on
*) Need to solve the full sso issue with zimbra and samba
Quick and dirty solution:
1) download, make and copy
mkntpwd into /opt/zimbra/bin
2) download zimbra 4.5 sources
3) read
Zimbra Development with Eclipse
4) modify LdapProvisioning.java in the com.zimbra.cs.account.ldap package writing a new setPassword(Account acct, String newPassword, boolean enforcePolicy) method and comment out the old one:
void setPassword(Account acct, String newPassword, boolean enforcePolicy) throws ServiceException {
if (enforcePolicy) {
checkPasswordStrength(newPassword, acct, null, null);
int minAge = acct.getIntAttr(Provisioning.A_zimbraPasswordMinAg e, 0);
if (minAge > 0) {
Date lastChange = acct.getGeneralizedTimeAttr(Provisioning.A_zimbraP asswordModifiedTime, null);
if (lastChange != null) {
long last = lastChange.getTime();
long curr = System.currentTimeMillis();
if ((last+(ONE_DAY_IN_MILLIS * minAge)) > curr)
throw AccountServiceException.PASSWORD_CHANGE_TOO_SOON() ;
}
}
}
Map<String, Object> attrs = new HashMap<String, Object>();
int enforceHistory = acct.getIntAttr(Provisioning.A_zimbraPasswordEnfor ceHistory, 0);
if (enforceHistory > 0) {
String[] newHistory = updateHistory(
acct.getMultiAttr(Provisioning.A_zimbraPasswordHis tory),
acct.getAttr(Provisioning.A_userPassword),
enforceHistory);
attrs.put(Provisioning.A_zimbraPasswordHistory, newHistory);
checkHistory(newPassword, newHistory);
}
String encodedPassword = LdapUtil.generateSSHA(newPassword, null);
String lmPassword = "";
try {
Process p1 = Runtime.getRuntime().exec("/opt/zimbra/bin/mkntpwd -L " + newPassword);
BufferedReader bf1=new BufferedReader(new InputStreamReader(p1.getInputStream()));
lmPassword = bf1.readLine();
} catch (IOException ioe) {
ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] {"cmd", "LdapProvisioning.SetPassword","lmPassword", ioe.getMessage()}));
}
String ntPassword = "";
try {
Process p2 = Runtime.getRuntime().exec("/opt/zimbra/bin/mkntpwd -N " + newPassword);
BufferedReader bf2=new BufferedReader(new InputStreamReader(p2.getInputStream()));
ntPassword = bf2.readLine();
} catch (IOException ioe) {
ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] {"cmd", "LdapProvisioning.SetPassword","ntPassword", ioe.getMessage()}));
}
boolean mustChange = acct.getBooleanAttr(Provisioning.A_zimbraPasswordM ustChange, false);
// unset it so it doesn't take up space...
if (mustChange)
attrs.put(Provisioning.A_zimbraPasswordMustChange, "");
attrs.put(Provisioning.A_userPassword, encodedPassword);
attrs.put(Provisioning.A_zimbraPasswordModifiedTim e, DateUtil.toGeneralizedTime(new Date()));
attrs.put("sambaLMPassword", lmPassword);
attrs.put("sambaNTPassword", ntPassword);
ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] {"cmd", "LdapProvisioning.SetPassword","lmPassword", lmPassword}));
ZimbraLog.security.info(ZimbraLog.encodeAttrs(new String[] {"cmd", "LdapProvisioning.SetPassword","ntPassword", ntPassword}));
modifyAttrs(acct, attrs);
}
5) rebuild zimbrastore.jar
6) zmcontrol stop
7) copy the new zimbrastore.jar into /opt/zimbra/lib/jars/, into /opt/zimbra/tomcat/webapps/zimbra/WEB-INF/lib/ and into /opt/zimbra/tomcat/webapps/service/WEB-INF/lib/ (
make backup copy first!)
8) zmcontrol start
9) log in as admin and change a user password (and, if you want, set also the "must change password" checkbox)
10) in /opt/zimbra/log/audit.log you should note two lines with the NT and LM password hashes
11) open a samba share with the new credentials
It works for me.
Regards,
Antonio