Hi Andrew,
here's the patch...

It adds a new parameter to smb.conf 'ldap passwd sync = Yes | No | Only':

Yes -> try to update the password on the LDAP-Server via extended operations.
No -> didn't try to update the passwd
Only -> This only the Passchange via  extended operations is done.
             and lmPassword, ntPassword, pwdLastSet are not updated/added

this is only availible if the ldap libs support LDAP_EXOP_X_MODIFY_PASSWD.




metze
-----------------------------------------------------------------------------
Stefan "metze" Metzmacher <[EMAIL PROTECTED]>
diff -Npur --exclude=CVS HEAD/source/include/smb.h HEAD-pdb/source/include/smb.h
--- HEAD/source/include/smb.h   Thu Aug  1 07:25:08 2002
+++ HEAD-pdb/source/include/smb.h       Thu Aug  1 10:11:05 2002
@@ -1375,6 +1375,9 @@ enum schema_types {SCHEMA_COMPAT, SCHEMA
 /* LDAP SSL options */
 enum ldap_ssl_types {LDAP_SSL_ON, LDAP_SSL_OFF, LDAP_SSL_START_TLS};
 
+/* LDAP PASSWD SYNC methods */
+enum ldap_passwd_sync_types {LDAP_PASSWD_SYNC_ON, LDAP_PASSWD_SYNC_OFF, 
+LDAP_PASSWD_SYNC_ONLY};
+
 /* Remote architectures we know about. */
 enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_WIN2K, 
RA_SAMBA};
 
diff -Npur --exclude=CVS HEAD/source/param/loadparm.c HEAD-pdb/source/param/loadparm.c
--- HEAD/source/param/loadparm.c        Thu Aug  1 07:25:09 2002
+++ HEAD-pdb/source/param/loadparm.c    Thu Aug  1 10:57:08 2002
@@ -205,11 +205,13 @@ typedef struct
        int iLockSpinTime;
        char *szLdapMachineSuffix;
        char *szLdapUserSuffix;
-       int ldap_port;
        int ldap_ssl;
        char *szLdapSuffix;
        char *szLdapFilter;
        char *szLdapAdminDn;
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+       int ldap_passwd_sync; 
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */ 
        BOOL bMsAddPrinterWizard;
        BOOL bDNSproxy;
        BOOL bWINSsupport;
@@ -590,6 +592,20 @@ static struct enum_list enum_ldap_ssl[] 
        {-1, NULL}
 };
 
+static struct enum_list enum_ldap_passwd_sync[] = {
+       {LDAP_PASSWD_SYNC_ON, "Yes"},
+       {LDAP_PASSWD_SYNC_ON, "yes"},
+       {LDAP_PASSWD_SYNC_ON, "on"},
+       {LDAP_PASSWD_SYNC_ON, "On"},
+       {LDAP_PASSWD_SYNC_OFF, "no"},
+       {LDAP_PASSWD_SYNC_OFF, "No"},
+       {LDAP_PASSWD_SYNC_OFF, "off"},
+       {LDAP_PASSWD_SYNC_OFF, "Off"},
+       {LDAP_PASSWD_SYNC_ONLY, "Only"},
+       {LDAP_PASSWD_SYNC_ONLY, "only"},
+       {-1, NULL}
+};
+
 /* Types of machine we can announce as. */
 #define ANNOUNCE_AS_NT_SERVER 1
 #define ANNOUNCE_AS_WIN95 2
@@ -968,6 +984,9 @@ static struct parm_struct parm_table[] =
        {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, 0},
        {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, 0},
        {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, 0},
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD       
+       {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, 
+enum_ldap_passwd_sync, 0},
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
 
        {"Miscellaneous Options", P_SEP, P_SEPARATOR},
        {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, 
NULL, 0},
@@ -1334,6 +1353,9 @@ static void init_globals(void)
        string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
        string_set(&Globals.szLdapAdminDn, "");
        Globals.ldap_ssl = LDAP_SSL_ON;
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD       
+       Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */ 
 
 /* these parameters are set to defaults that are more appropriate
    for the increasing samba install base:
@@ -1543,6 +1565,9 @@ FN_GLOBAL_STRING(lp_ldap_user_suffix, &G
 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD       
+FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */ 
 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
diff -Npur --exclude=CVS HEAD/source/passdb/pdb_get_set.c 
HEAD-pdb/source/passdb/pdb_get_set.c
--- HEAD/source/passdb/pdb_get_set.c    Wed Jul 24 07:57:11 2002
+++ HEAD-pdb/source/passdb/pdb_get_set.c        Thu Aug  1 12:18:47 2002
@@ -963,7 +963,7 @@ BOOL pdb_set_plaintext_pw_only (SAM_ACCO
 
        data_blob_clear_free(&sampass->private.plaintext_pw);
        
-       sampass->private.plaintext_pw = data_blob(password, len);
+       sampass->private.plaintext_pw = data_blob(password, len+1);
 
        return True;
 }
@@ -1061,6 +1061,9 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOU
                return False;
 
        if (!pdb_set_lanman_passwd (sampass, new_lanman_p16)) 
+               return False;
+
+       if (!pdb_set_plaintext_pw_only (sampass, plaintext,strlen(plaintext))) 
                return False;
        
        if (!pdb_set_pass_changed_now (sampass))
diff -Npur --exclude=CVS HEAD/source/passdb/pdb_ldap.c 
HEAD-pdb/source/passdb/pdb_ldap.c
--- HEAD/source/passdb/pdb_ldap.c       Tue Jul 30 10:39:13 2002
+++ HEAD-pdb/source/passdb/pdb_ldap.c   Thu Aug  1 15:12:50 2002
@@ -1,11 +1,12 @@
 /* 
    Unix SMB/CIFS implementation.
    LDAP protocol helper functions for SAMBA
-   Copyright (C) Gerald Carter 2001
-   Copyright (C) Shahms King 2001
-   Copyright (C) Jean Fran�ois Micouleau 1998
-   Copyright (C) Andrew Bartlett 2002
-   
+   Copyright (C) Jean Fran�ois Micouleau       1998
+   Copyright (C) Gerald Carter                 2001
+   Copyright (C) Shahms King                   2001
+   Copyright (C) Andrew Bartlett               2002
+   Copyright (C) Stefan (metze) Metzmacher     2002
+    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
@@ -158,7 +159,8 @@ static const char *attr[] = {"uid", "pwd
 ******************************************************************/
 static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** 
ldap_struct)
 {
-
+       int version;
+       
        if (geteuid() != 0) {
                DEBUG(0, ("ldap_open_connection: cannot access LDAP when not 
root..\n"));
                return False;
@@ -171,6 +173,16 @@ static BOOL ldapsam_open_connection (str
                DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));
                return (False);
        }
+
+       if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == 
+LDAP_OPT_SUCCESS)
+       {
+               if (version != LDAP_VERSION3)
+               {
+                       version = LDAP_VERSION3;
+                       ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, 
+&version);
+               }
+       }
+
 #else 
 
        /* Parse the string manually */
@@ -179,7 +191,6 @@ static BOOL ldapsam_open_connection (str
                int rc;
                int tls = LDAP_OPT_X_TLS_HARD;
                int port = 0;
-               int version;
                fstring protocol;
                fstring host;
                const char *p = ldap_state->uri; 
@@ -409,7 +420,7 @@ static int ldapsam_search_one_user (stru
 
        DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
 
-       rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, attr, 0, 
result);
+       rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, (char 
+**)attr, 0, result);
 
        if (rc != LDAP_SUCCESS) {
                DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: 
%s\n", 
@@ -932,9 +943,6 @@ static BOOL init_ldap_from_sam (struct l
        slprintf(temp, sizeof(temp) - 1, "%i", rid);
        make_a_mod(mods, ldap_op, "primaryGroupID", temp);
 
-       slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
-       make_a_mod(mods, ldap_op, "pwdLastSet", temp);
-
        /* displayName, cn, and gecos should all be the same
           *  most easily accomplished by giving them the same OID
           *  gecos isn't set here b/c it should be handled by the 
@@ -977,6 +985,7 @@ static BOOL init_ldap_from_sam (struct l
                make_a_mod(mods, ldap_op, "kickoffTime", temp);
        }
 
+
        if (IS_SAM_SET(sampass, FLAG_SAM_CANCHANGETIME)) {
                slprintf (temp, sizeof (temp) - 1, "%li", 
pdb_get_pass_can_change_time(sampass));
                make_a_mod(mods, ldap_op, "pwdCanChange", temp);
@@ -987,13 +996,26 @@ static BOOL init_ldap_from_sam (struct l
                make_a_mod(mods, ldap_op, "pwdMustChange", temp);
        }
 
-       /* FIXME: Hours stuff goes in LDAP  */
-       pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), 
pdb_get_acct_ctrl(sampass));
-       make_a_mod (mods, ldap_op, "lmPassword", temp);
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+       if (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)
+       {
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
+
+               pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), 
+pdb_get_acct_ctrl(sampass));
+               make_a_mod (mods, ldap_op, "lmPassword", temp);
        
-       pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
-       make_a_mod (mods, ldap_op, "ntPassword", temp);
+               pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), 
+pdb_get_acct_ctrl(sampass));
+               make_a_mod (mods, ldap_op, "ntPassword", temp);
        
+               slprintf (temp, sizeof (temp) - 1, "%li", 
+pdb_get_pass_last_set_time(sampass));
+               make_a_mod(mods, ldap_op, "pwdLastSet", temp);
+
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+       }
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
+
+       /* FIXME: Hours stuff goes in LDAP  */
+
        make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl 
(pdb_get_acct_ctrl(sampass),
                NEW_PW_FORMAT_SPACE_PADDED_LEN));
 
@@ -1081,7 +1103,7 @@ static uint32 search_top_nua_rid(struct 
        DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", 
final_filter));
 
        rc = ldap_search_s(ldap_struct, lp_ldap_suffix(),
-                          LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
+                          LDAP_SCOPE_SUBTREE, final_filter, (char **)attr, 0,
                           &result);
 
        if (rc != LDAP_SUCCESS)
@@ -1179,7 +1201,7 @@ static BOOL ldapsam_setsampwent(struct p
        all_string_sub(filter, "%u", "*", sizeof(pstring));
 
        rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(),
-                          LDAP_SCOPE_SUBTREE, filter, attr, 0,
+                          LDAP_SCOPE_SUBTREE, filter, (char **)attr, 0,
                           &ldap_state->result);
 
        if (rc != LDAP_SUCCESS)
@@ -1433,6 +1455,7 @@ static BOOL ldapsam_update_sam_account(s
        LDAPMessage *result;
        LDAPMessage *entry;
        LDAPMod **mods;
+       int version;
 
        if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection 
to the server */
                return False;
@@ -1480,6 +1503,70 @@ static BOOL ldapsam_update_sam_account(s
                return False;
        }
 
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+       if (ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == 
+LDAP_OPT_SUCCESS)
+       {
+               if (version != LDAP_VERSION3)
+               {
+                       version = LDAP_VERSION3;
+                       ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, 
+&version);
+               }
+       }
+        
+       if 
+((lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&(pdb_get_plaintext_passwd(newpwd)!=NULL))
+       {
+               BerElement *ber;
+               struct berval *bv;
+               char *retoid;
+               struct berval *retdata;
+               char *new_passwd;
+
+               if ((ber = ber_alloc_t(LBER_USE_DER))==NULL)
+               {
+                       DEBUG(0,("ber_alloc_t returns NULL\n"));
+                       return False;
+               }
+
+               if ((new_passwd = (char 
+*)malloc(newpwd->private.plaintext_pw.length+1))==NULL)
+               {
+                       DEBUG(0,("malloc returns NULL\n"));
+                       return False;
+               }
+
+               
+snprintf(new_passwd,newpwd->private.plaintext_pw.length,"%s",newpwd->private.plaintext_pw.data);
+
+               ber_printf (ber, "{");
+               ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
+               ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, new_passwd);
+               ber_printf (ber, "N}");
+
+               free(new_passwd);
+                                       
+               if ((rc = ber_flatten (ber, &bv))<0)
+               {
+                       DEBUG(0,("ber_flatten returns a value <0\n"));
+                       return False;
+               }
+               
+               ber_free(ber,1);
+               
+               if ((rc = ldap_extended_operation_s(ldap_struct, 
+LDAP_EXOP_X_MODIFY_PASSWD,
+                                                   bv, NULL, NULL, &retoid, 
+&retdata))!=LDAP_SUCCESS)
+               {
+                       DEBUG(0,("LDAP Password could not be changed for user %s: 
+%s\n",
+                               pdb_get_username(newpwd),ldap_err2string(rc)));
+               } else {
+                       DEBUG(3,("LDAP Password changed for user 
+%s\n",pdb_get_username(newpwd)));
+    
+                       ber_bvfree(retdata);
+                       ber_memfree(retoid);
+               }
+               ber_bvfree(bv);
+       }
+#else
+       DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
+
        DEBUG(2,
              ("successfully modified uid = %s in the LDAP database\n",
               pdb_get_username(newpwd)));
@@ -1502,7 +1589,8 @@ static BOOL ldapsam_add_sam_account(stru
        LDAPMod **mods = NULL;
        int             ldap_op;
        uint32          num_result;
-
+       int version;
+       
        const char *username = pdb_get_username(newpwd);
        if (!username || !*username) {
                DEBUG(0, ("Cannot add user without a username!\n"));
@@ -1593,6 +1681,70 @@ static BOOL ldapsam_add_sam_account(stru
                ldap_unbind(ldap_struct);
                return False;
        }
+
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+       if (ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == 
+LDAP_OPT_SUCCESS)
+       {
+               if (version != LDAP_VERSION3)
+               {
+                       version = LDAP_VERSION3;
+                       ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, 
+&version);
+               }
+       }
+        
+       if 
+((lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&(pdb_get_plaintext_passwd(newpwd)!=NULL))
+       {
+               BerElement *ber;
+               struct berval *bv;
+               char *retoid;
+               struct berval *retdata;
+               char *new_passwd;
+
+               if ((ber = ber_alloc_t(LBER_USE_DER))==NULL)
+               {
+                       DEBUG(0,("ber_alloc_t returns NULL\n"));
+                       return False;
+               }
+
+               if ((new_passwd = (char 
+*)malloc(newpwd->private.plaintext_pw.length+1))==NULL)
+               {
+                       DEBUG(0,("malloc returns NULL\n"));
+                       return False;
+               }
+
+               
+snprintf(new_passwd,newpwd->private.plaintext_pw.length,"%s",newpwd->private.plaintext_pw.data);
+
+               ber_printf (ber, "{");
+               ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
+               ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, new_passwd);
+               ber_printf (ber, "N}");
+
+               free(new_passwd);
+                                       
+               if ((rc = ber_flatten (ber, &bv))<0)
+               {
+                       DEBUG(0,("ber_flatten returns a value <0\n"));
+                       return False;
+               }
+               
+               ber_free(ber,1);
+               
+               if ((rc = ldap_extended_operation_s(ldap_struct, 
+LDAP_EXOP_X_MODIFY_PASSWD,
+                                                   bv, NULL, NULL, &retoid, 
+&retdata))!=LDAP_SUCCESS)
+               {
+                       DEBUG(0,("LDAP Password could not be changed for user %s: 
+%s\n",
+                               pdb_get_username(newpwd),ldap_err2string(rc)));
+               } else {
+                       DEBUG(3,("LDAP Password changed for user 
+%s\n",pdb_get_username(newpwd)));
+    
+                       ber_bvfree(retdata);
+                       ber_memfree(retoid);
+               }
+               ber_bvfree(bv);
+       }
+#else
+       DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
        
        DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
        ldap_mods_free(mods, 1);

Reply via email to