Author: Vince Brimhall Subject: Samba passdb backend for Novell eDirectory --- source/include/includes.h +++ source/include/includes.h 2005-03-01 11:57:15.027549922 -0700 @@ -923,6 +923,29 @@ #include "smbldap.h" +/* struct used by both pdb_ldap.c and pdb_nds.c */ + +struct ldapsam_privates { + struct smbldap_state *smbldap_state; + + /* Former statics */ + LDAPMessage *result; + LDAPMessage *entry; + int index; + + const char *domain_name; + DOM_SID domain_sid; + + /* configuration items */ + int schema_ver; + + /* Is this NDS ldap? */ + int is_nds_ldap; + + /* ldap server location parameter */ + char *location; +}; + /***** automatically generated prototypes *****/ #ifndef NO_PROTO_H #include "proto.h" --- source/passdb/pdb_ldap.c +++ source/passdb/pdb_ldap.c 2005-03-01 11:57:14.507612665 -0700 @@ -83,26 +83,11 @@ #include "smbldap.h" -struct ldapsam_privates { - struct smbldap_state *smbldap_state; - - /* Former statics */ - LDAPMessage *result; - LDAPMessage *entry; - int index; - - const char *domain_name; - DOM_SID domain_sid; - - /* configuration items */ - int schema_ver; -}; - /********************************************************************** Free a LDAPMessage (one is stored on the SAM_ACCOUNT). **********************************************************************/ -static void private_data_free_fn(void **result) +void private_data_free_fn(void **result) { ldap_msgfree(*result); *result = NULL; @@ -132,7 +117,7 @@ Return the list of attribute names given a user schema version. **********************************************************************/ -static char** get_userattr_list( int schema_ver ) +char** get_userattr_list( int schema_ver ) { switch ( schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: @@ -197,7 +182,7 @@ Run the search by name. ******************************************************************/ -static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, +int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user, LDAPMessage ** result, char **attr) { @@ -467,6 +452,7 @@ uint32 user_rid; uint8 smblmpwd[LM_HASH_LEN], smbntpwd[NT_HASH_LEN]; + BOOL use_samba_attrs = True; uint16 acct_ctrl = 0, logon_divs; uint16 bad_password_count = 0, @@ -705,26 +691,55 @@ hours_len = 21; memset(hours, 0xff, hours_len); - if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) { - /* leave as default */ - } else { - pdb_gethexpwd(temp, smblmpwd); - memset((char *)temp, '\0', strlen(temp)+1); - if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) - return False; - ZERO_STRUCT(smblmpwd); + if (ldap_state->is_nds_ldap) { + char *user_dn; + size_t pwd_len; + uchar clear_text_pw[512]; + + /* Make call to Novell eDirectory ldap extension to get clear text password. + NOTE: This will only work if we have an SSL connection to eDirectory. */ + user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + if (user_dn != NULL) { + DEBUG(3, ("init_sam_from_ldap: smbldap_get_dn(%s) returned '%s'\n", username, user_dn)); + + pwd_len = sizeof(clear_text_pw); + if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) { + nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd); + if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) + return False; + ZERO_STRUCT(smblmpwd); + if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) + return False; + ZERO_STRUCT(smbntpwd); + use_samba_attrs = False; + } + } else { + DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username)); + } } - if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) { - /* leave as default */ - } else { - pdb_gethexpwd(temp, smbntpwd); - memset((char *)temp, '\0', strlen(temp)+1); - if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) - return False; - ZERO_STRUCT(smbntpwd); + if (use_samba_attrs) { + if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) { + /* leave as default */ + } else { + pdb_gethexpwd(temp, smblmpwd); + memset((char *)temp, '\0', strlen(temp)+1); + if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) + return False; + ZERO_STRUCT(smblmpwd); + } + + if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) { + /* leave as default */ + } else { + pdb_gethexpwd(temp, smbntpwd); + memset((char *)temp, '\0', strlen(temp)+1); + if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) + return False; + ZERO_STRUCT(smbntpwd); + } } account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); @@ -1488,15 +1503,17 @@ (pdb_get_plaintext_passwd(newpwd)!=NULL)) { BerElement *ber; struct berval *bv; - char *retoid; - struct berval *retdata; + char *retoid = NULL; + struct berval *retdata = NULL; char *utf8_password; char *utf8_dn; - if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) { - DEBUG(2, ("ldap password change requested, but LDAP " - "server does not support it -- ignoring\n")); - return NT_STATUS_OK; + if (!ldap_state->is_nds_ldap) { + if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) { + DEBUG(2, ("ldap password change requested, but LDAP " + "server does not support it -- ignoring\n")); + return NT_STATUS_OK; + } } if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) { @@ -1530,10 +1547,16 @@ SAFE_FREE(utf8_password); ber_free(ber, 1); - if ((rc = smbldap_extended_operation(ldap_state->smbldap_state, + if (!ldap_state->is_nds_ldap) { + rc = smbldap_extended_operation(ldap_state->smbldap_state, LDAP_EXOP_MODIFY_PASSWD, bv, NULL, NULL, &retoid, - &retdata)) != LDAP_SUCCESS) { + &retdata); + } else { + rc = pdb_nds_set_password(ldap_state->smbldap_state, dn, + pdb_get_plaintext_passwd(newpwd)); + } + if (rc != LDAP_SUCCESS) { char *ld_error = NULL; if (rc == LDAP_OBJECT_CLASS_VIOLATION) { @@ -1556,8 +1579,10 @@ #ifdef DEBUG_PASSWORD DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd))); #endif - ber_bvfree(retdata); - ber_memfree(retoid); + if (retdata != NULL) + ber_bvfree(retdata); + if (retoid != NULL) + ber_memfree(retoid); } ber_bvfree(bv); } @@ -2960,7 +2985,7 @@ Initialise the 'compat' mode for pdb_ldap *********************************************************************/ -static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; struct ldapsam_privates *ldap_state; @@ -2999,7 +3024,7 @@ Initialise the normal mode for pdb_ldap *********************************************************************/ -static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; struct ldapsam_privates *ldap_state; @@ -3095,5 +3120,8 @@ if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat))) return nt_status; + /* Let pdb_nds register backends */ + pdb_nds_init(); + return NT_STATUS_OK; } --- source/Makefile.in +++ source/Makefile.in 2005-03-01 11:57:14.184651637 -0700 @@ -312,7 +312,7 @@ passdb/util_sam_sid.o passdb/pdb_compat.o \ passdb/lookup_sid.o \ passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \ - lib/system_smbd.o + lib/system_smbd.o passdb/pdb_nds.o XML_OBJ = passdb/pdb_xml.o MYSQL_OBJ = passdb/pdb_mysql.o