diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/smb.h | 10 | ||||
-rw-r--r-- | source3/param/loadparm.c | 101 | ||||
-rw-r--r-- | source3/passdb/passdb.c | 22 | ||||
-rw-r--r-- | source3/passdb/pdb_get_set.c | 35 | ||||
-rw-r--r-- | source3/passdb/pdb_interface.c | 7 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 869 | ||||
-rw-r--r-- | source3/passdb/pdb_smbpasswd.c | 2 | ||||
-rw-r--r-- | source3/passdb/pdb_tdb.c | 10 | ||||
-rw-r--r-- | source3/passdb/secrets.c | 28 |
9 files changed, 794 insertions, 290 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 1ae250f9c6..8ec092e623 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -576,8 +576,14 @@ typedef struct { #define FLAG_SAM_GID 0x00000002 #define FLAG_SAM_SMBHOME 0x00000004 #define FLAG_SAM_PROFILE 0x00000008 -#define FLAG_SAM_LOGONSCRIPT 0x00000010 -#define FLAG_SAM_DRIVE 0x00000020 +#define FLAG_SAM_DRIVE 0x00000010 +#define FLAG_SAM_LOGONSCRIPT 0x00000020 +#define FLAG_SAM_LOGONTIME 0x00000040 +#define FLAG_SAM_LOGOFFTIME 0x00000080 +#define FLAG_SAM_KICKOFFTIME 0x00000100 +#define FLAG_SAM_CANCHANGETIME 0x00000200 +#define FLAG_SAM_MUSTCHANGETIME 0x00000400 + #define IS_SAM_UNIX_USER(x) \ ((pdb_get_init_flag(x) & FLAG_SAM_UID) \ diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 7548ff03a8..6abf967cde 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -199,6 +199,8 @@ typedef struct int oplock_break_wait_time; int winbind_cache_time; #ifdef WITH_LDAP_SAM + char *szLdapMachineSuffix; + char *szLdapUserSuffix; int ldap_port; int ldap_ssl; char *szLdapServer; @@ -533,6 +535,9 @@ static BOOL handle_winbind_gid(char *pszParmValue, char **ptr); static BOOL handle_non_unix_account_range(char *pszParmValue, char **ptr); static BOOL handle_wins_server_list(char *pszParmValue, char **ptr); static BOOL handle_debug_list( char *pszParmValue, char **ptr ); +static BOOL handle_ldap_machine_suffix ( char *pszParmValue, char **ptr ); +static BOOL handle_ldap_user_suffix ( char *pszParmValue, char **ptr ); +static BOOL handle_ldap_suffix ( char *pszParmValue, char **ptr ); static void set_server_role(void); static void set_default_server_announce_type(void); @@ -970,9 +975,9 @@ static struct parm_struct parm_table[] = { #ifdef WITH_LDAP_SAM {"Ldap Options", P_SEP, P_SEPARATOR}, - {"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, 0}, - {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, 0}, - {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, 0}, + {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, handle_ldap_suffix, NULL, 0}, + {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, handle_ldap_machine_suffix, NULL, 0}, + {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_user_suffix, NULL, 0}, {"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}, @@ -1315,16 +1320,16 @@ static void init_globals(void) Globals.bUseMmap = True; #endif + string_set(&Globals.szLdapMachineSuffix, ""); + string_set(&Globals.szLdapUserSuffix, ""); /* hostname lookups can be very expensive and are broken on a large number of sites (tridge) */ Globals.bHostnameLookups = False; #ifdef WITH_LDAP_SAM - string_set(&Globals.szLdapServer, "localhost"); string_set(&Globals.szLdapSuffix, ""); string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))"); string_set(&Globals.szLdapAdminDn, ""); - Globals.ldap_port = 636; Globals.ldap_ssl = LDAP_SSL_ON; #endif /* WITH_LDAP_SAM */ @@ -1541,11 +1546,11 @@ FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers) FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups) FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain) #ifdef WITH_LDAP_SAM -FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer) FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix) +FN_GLOBAL_STRING(lp_ldap_machine_suffix, &Globals.szLdapMachineSuffix) +FN_GLOBAL_STRING(lp_ldap_user_suffix, &Globals.szLdapUserSuffix) FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter) FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn) -FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port) FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl) #endif /* WITH_LDAP_SAM */ FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand) @@ -2611,6 +2616,88 @@ static BOOL handle_debug_list( char *pszParmValueIn, char **ptr ) return debug_parse_levels( pszParmValue ); } +/*************************************************************************** + Handle the ldap machine suffix option +***************************************************************************/ +static BOOL handle_ldap_machine_suffix( char *pszParmValue, char **ptr) +{ + pstring suffix; + + pstrcpy(suffix, pszParmValue); + + if (! *Globals.szLdapSuffix ) { + string_set( ptr, suffix ); + return True; + } + + if (! strstr(suffix, Globals.szLdapSuffix) ) { + if ( *pszParmValue ) + pstrcat(suffix, ","); + pstrcat(suffix, Globals.szLdapSuffix); + } + string_set( ptr, suffix ); + return True; +} + +/*************************************************************************** + Handle the ldap user suffix option +***************************************************************************/ +static BOOL handle_ldap_user_suffix( char *pszParmValue, char **ptr) +{ + pstring suffix; + + pstrcpy(suffix, pszParmValue); + + if (! *Globals.szLdapSuffix ) { + string_set( ptr, suffix ); + return True; + } + + if (! strstr(suffix, Globals.szLdapSuffix) ) { + if ( *pszParmValue ) + pstrcat(suffix, ","); + pstrcat(suffix, Globals.szLdapSuffix); + } + string_set( ptr, suffix ); + return True; +} + +/*************************************************************************** + Handle setting ldap suffix and determines whether ldap machine suffix needs + to be set as well +***************************************************************************/ +static BOOL handle_ldap_suffix( char *pszParmValue, char **ptr) +{ + pstring suffix; + pstring user_suffix; + pstring machine_suffix; + + pstrcpy(suffix, pszParmValue); + + if (! *Globals.szLdapMachineSuffix ) + string_set(&Globals.szLdapMachineSuffix, suffix); + if (! *Globals.szLdapUserSuffix ) + string_set(&Globals.szLdapUserSuffix, suffix); + + if (! strstr(Globals.szLdapMachineSuffix, suffix)) { + pstrcpy(machine_suffix, Globals.szLdapMachineSuffix); + if ( *Globals.szLdapMachineSuffix ) + pstrcat(machine_suffix, ","); + pstrcat(machine_suffix, suffix); + string_set(&Globals.szLdapMachineSuffix, machine_suffix); + } + + if (! strstr(Globals.szLdapUserSuffix, suffix)) { + pstrcpy(user_suffix, Globals.szLdapUserSuffix); + if ( *Globals.szLdapUserSuffix ) + pstrcat(user_suffix, ","); + pstrcat(user_suffix, suffix); + string_set(&Globals.szLdapUserSuffix, user_suffix); + } + + string_set(ptr, suffix); + return True; +} /*************************************************************************** initialise a copymap diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 5ae1b710f5..191844a454 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -904,12 +904,13 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) if (from == NULL || to == NULL) return; - pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time)); - pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time)); - pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time)); + pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time), True); + pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time), True); + pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time), True); + pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time), True); + pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time), True); + pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time)); - pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time)); - pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time)); if (from->uni_user_name.buffer) pdb_set_username(to , pdb_convert(&from->uni_user_name )); @@ -958,12 +959,13 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) if (from == NULL || to == NULL) return; - pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time)); - pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time)); - pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time)); + pdb_set_logon_time(to,nt_time_to_unix(&from->logon_time), True); + pdb_set_logoff_time(to,nt_time_to_unix(&from->logoff_time), True); + pdb_set_kickoff_time(to, nt_time_to_unix(&from->kickoff_time), True); + pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time), True); + pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time), True); + pdb_set_pass_last_set_time(to, nt_time_to_unix(&from->pass_last_set_time)); - pdb_set_pass_can_change_time(to, nt_time_to_unix(&from->pass_can_change_time)); - pdb_set_pass_must_change_time(to, nt_time_to_unix(&from->pass_must_change_time)); if (from->uni_user_name.buffer) pdb_set_username(to , pdb_convert(&from->uni_user_name )); diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 5886d29c67..181364ab6b 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -321,48 +321,68 @@ BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 flags) return False; } -BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime) +BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime, BOOL store) { if (!sampass) return False; sampass->private.logon_time = mytime; + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_LOGONTIME); + return True; } -BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime) +BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime, BOOL store) { if (!sampass) return False; sampass->private.logoff_time = mytime; + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_LOGOFFTIME); + return True; } -BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime) +BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime, BOOL store) { if (!sampass) return False; sampass->private.kickoff_time = mytime; + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_KICKOFFTIME); + return True; } -BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime) +BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime, BOOL store) { if (!sampass) return False; sampass->private.pass_can_change_time = mytime; + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_CANCHANGETIME); + return True; } -BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime) +BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime, BOOL store) { if (!sampass) return False; sampass->private.pass_must_change_time = mytime; + + if (store) + pdb_set_init_flag(sampass, FLAG_SAM_MUSTCHANGETIME); + return True; } @@ -372,6 +392,7 @@ BOOL pdb_set_pass_last_set_time (SAM_ACCOUNT *sampass, time_t mytime) return False; sampass->private.pass_last_set_time = mytime; + return True; } @@ -876,12 +897,12 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass) account_policy_get(AP_MAX_PASSWORD_AGE, &expire); if (expire==(uint32)-1) { - if (!pdb_set_pass_must_change_time (sampass, 0)) + if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), False)) return False; } else { if (!pdb_set_pass_must_change_time (sampass, pdb_get_pass_last_set_time(sampass) - + expire)) + + expire, True)) return False; } diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 73532984b6..953b5c4d2f 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -27,8 +27,9 @@ const struct pdb_init_function_entry builtin_pdb_init_functions[] = { { "smbpasswd_nua", pdb_init_smbpasswd_nua }, { "tdbsam", pdb_init_tdbsam }, { "tdbsam_nua", pdb_init_tdbsam_nua }, + { "ldapsam", pdb_init_ldapsam }, + { "ldapsam_nua", pdb_init_ldapsam_nua }, #if 0 - { "ldap", pdb_init_ldap }, { "nisplus", pdb_init_nisplus }, { "unix", pdb_init_unix }, #endif @@ -252,7 +253,7 @@ static struct pdb_context *pdb_get_static_context(BOOL reload) return pdb_context; } -#if !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM) +#if !defined(WITH_NISPLUS_SAM) /****************************************************************** Backward compatability functions for the original passdb interface @@ -346,7 +347,7 @@ BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) return pdb_context->pdb_delete_sam_account(pdb_context, sam_acct); } -#endif /* !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM) */ +#endif /* !defined(WITH_NISPLUS_SAM) */ /*************************************************************** Initialize the static context (at smbd startup etc). diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 1e67d86091..7dae485394 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -4,6 +4,7 @@ Copyright (C) Gerald Carter 2001 Copyright (C) Shahms King 2001 Copyright (C) Jean François Micouleau 1998 + Copyright (C) Andrew Bartlett 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 @@ -51,87 +52,156 @@ #define SAM_ACCOUNT struct sam_passwd #endif -struct ldap_enum_info { +struct ldapsam_privates { + + /* Former statics */ LDAP *ldap_struct; LDAPMessage *result; LDAPMessage *entry; int index; + + /* retrive-once info */ + const char *uri; + + BOOL permit_non_unix_accounts; + + uint32 low_nua_rid; + uint32 high_nua_rid; }; -static struct ldap_enum_info global_ldap_ent; +static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state); +/******************************************************************* + find the ldap password +******************************************************************/ +static BOOL fetch_ldapsam_pw(char *dn, char* pw, int len) +{ + fstring key; + char *p; + void *data = NULL; + size_t size; + + pstrcpy(key, dn); + for (p=key; *p; p++) + if (*p == ',') *p = '/'; + + data=secrets_fetch(key, &size); + if (!size) { + DEBUG(0,("fetch_ldap_pw: no ldap secret retrieved!\n")); + return False; + } + + if (size > len-1) + { + DEBUG(0,("fetch_ldap_pw: ldap secret is too long (%d > %d)!\n", size, len-1)); + return False; + } + + memcpy(pw, data, size); + pw[size] = '\0'; + + return True; +} /******************************************************************* open a connection to the ldap server. ******************************************************************/ -static BOOL ldap_open_connection (LDAP ** ldap_struct) +static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct) { - int port; - int version, rc; - int tls = LDAP_OPT_X_TLS_HARD; - /* there should be an lp_ldap_ssl_port(), what happen if for some - reason we need to bind an SSLed LDAP on port 389 ?? ---simo */ - if (lp_ldap_ssl() == LDAP_SSL_ON && lp_ldap_port() == 389) { - port = 636; + if (geteuid() != 0) { + DEBUG(0, ("ldap_open_connection: cannot access LDAP when not root..\n")); + return False; } - else { - port = lp_ldap_port(); + +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) + DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri)); + + if (ldap_initialize(ldap_struct, ldap_state->uri) != LDAP_SUCCESS) { + DEBUG(0, ("ldap_initialize: %s\n", strerror(errno))); + return (False); } +#else - if ((*ldap_struct = ldap_init(lp_ldap_server(), port)) == NULL) { - DEBUG(0, ("The LDAP server is not responding !\n")); - return False; - } + /* Parse the string manually */ - /* Connect to older servers using SSL and V2 rather than Start TLS */ - if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { - if (version != LDAP_VERSION2) - { - version = LDAP_VERSION2; - ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version); + int rc; + int tls = LDAP_OPT_X_TLS_HARD; + int port = 0; + int version; + fstring protocol; + fstring host; + const char *p = ldap_state->uri; + SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); + + /* skip leading "URL:" (if any) */ + if ( strncasecmp( p, "URL:", 4 ) == 0 ) { + p += 4; } - } - switch (lp_ldap_ssl()) - { - case LDAP_SSL_START_TLS: - 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); - } + sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); + + if (port == 0) { + if (strequal(protocol, "ldap")) { + port = LDAP_PORT; + } else if (strequal(protocol, "ldaps")) { + port = LDAPS_PORT; + } else { + DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); } - if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) + } + + if ((*ldap_struct = ldap_init(host, port)) == NULL) { + DEBUG(0, ("ldap_init failed !\n")); + return False; + } + + /* Connect to older servers using SSL and V2 rather than Start TLS */ + if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) + { + if (version != LDAP_VERSION2) { - DEBUG(0,("Failed to issue the StartTLS instruction: %s\n", - ldap_err2string(rc))); - return False; + version = LDAP_VERSION2; + ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version); } - DEBUG (2, ("StartTLS issued: using a TLS connection\n")); - break; - - case LDAP_SSL_ON: - if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) - { - DEBUG(0, ("Failed to setup a TLS session\n")); + } + + if (strequal(protocol, "ldaps")) { + if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { + 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 ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) + { + DEBUG(0,("Failed to issue the StartTLS instruction: %s\n", + ldap_err2string(rc))); + return False; + } + DEBUG (2, ("StartTLS issued: using a TLS connection\n")); + } else { + + if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) + { + DEBUG(0, ("Failed to setup a TLS session\n")); + } } - break; - - case LDAP_SSL_OFF: - default: + } else { /* * No special needs to setup options prior to the LDAP * bind (which should be called next via ldap_connect_system() */ - break; + } } +#endif DEBUG(2, ("ldap_open_connection: connection opened\n")); return True; @@ -140,14 +210,14 @@ static BOOL ldap_open_connection (LDAP ** ldap_struct) /******************************************************************* connect to the ldap server under system privilege. ******************************************************************/ -static BOOL ldap_connect_system(LDAP * ldap_struct) +static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct) { int rc; static BOOL got_pw = False; static pstring ldap_secret; /* get the password if we don't have it already */ - if (!got_pw && !(got_pw=fetch_ldap_pw(lp_ldap_admin_dn(), ldap_secret, sizeof(pstring)))) + if (!got_pw && !(got_pw=fetch_ldapsam_pw(lp_ldap_admin_dn(), ldap_secret, sizeof(pstring)))) { DEBUG(0, ("ldap_connect_system: Failed to retrieve password for %s from secrets.tdb\n", lp_ldap_admin_dn())); @@ -174,19 +244,19 @@ static BOOL ldap_connect_system(LDAP * ldap_struct) /******************************************************************* run the search by name. ******************************************************************/ -static int ldap_search_one_user (LDAP * ldap_struct, const char *filter, LDAPMessage ** result) +static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *filter, LDAPMessage ** result) { int scope = LDAP_SCOPE_SUBTREE; int rc; - DEBUG(2, ("ldap_search_one_user: searching for:[%s]\n", filter)); + DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter)); rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, NULL, 0, result); if (rc != LDAP_SUCCESS) { - DEBUG(0,("ldap_search_one_user: Problem during the LDAP search: %s\n", + DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n", ldap_err2string (rc))); - DEBUG(3,("ldap_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(), + DEBUG(3,("ldapsam_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(), filter)); } @@ -196,7 +266,7 @@ static int ldap_search_one_user (LDAP * ldap_struct, const char *filter, LDAPMes /******************************************************************* run the search by name. ******************************************************************/ -static int ldap_search_one_user_by_name (LDAP * ldap_struct, const char *user, +static int ldapsam_search_one_user_by_name (struct ldapsam_privates *ldap_state, LDAP * ldap_struct, const char *user, LDAPMessage ** result) { pstring filter; @@ -213,22 +283,23 @@ static int ldap_search_one_user_by_name (LDAP * ldap_struct, const char *user, */ all_string_sub(filter, "%u", user, sizeof(pstring)); - return ldap_search_one_user(ldap_struct, filter, result); + return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result); } /******************************************************************* run the search by uid. ******************************************************************/ -static int ldap_search_one_user_by_uid(LDAP * ldap_struct, int uid, - LDAPMessage ** result) +static int ldapsam_search_one_user_by_uid(struct ldapsam_privates *ldap_state, + LDAP * ldap_struct, int uid, + LDAPMessage ** result) { struct passwd *user; pstring filter; /* Get the username from the system and look that up in the LDAP */ - if ((user = sys_getpwuid(uid)) == NULL) { - DEBUG(3,("ldap_search_one_user_by_uid: Failed to locate uid [%d]\n", uid)); + if ((user = getpwuid_alloc(uid)) == NULL) { + DEBUG(3,("ldapsam_search_one_user_by_uid: Failed to locate uid [%d]\n", uid)); return LDAP_NO_SUCH_OBJECT; } @@ -236,14 +307,17 @@ static int ldap_search_one_user_by_uid(LDAP * ldap_struct, int uid, all_string_sub(filter, "%u", user->pw_name, sizeof(pstring)); - return ldap_search_one_user(ldap_struct, filter, result); + passwd_free(&user); + + return ldapsam_search_one_user(ldap_state, ldap_struct, filter, result); } /******************************************************************* run the search by rid. ******************************************************************/ -static int ldap_search_one_user_by_rid (LDAP * ldap_struct, uint32 rid, - LDAPMessage ** result) +static int ldapsam_search_one_user_by_rid (struct ldapsam_privates *ldap_state, + LDAP * ldap_struct, uint32 rid, + LDAPMessage ** result) { pstring filter; int rc; @@ -251,11 +325,12 @@ static int ldap_search_one_user_by_rid (LDAP * ldap_struct, uint32 rid, /* check if the user rid exsists, if not, try searching on the uid */ snprintf(filter, sizeof(filter) - 1, "rid=%i", rid); - rc = ldap_search_one_user(ldap_struct, filter, result); + rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, result); if (rc != LDAP_SUCCESS) - rc = ldap_search_one_user_by_uid(ldap_struct, - pdb_user_rid_to_uid(rid), result); + rc = ldapsam_search_one_user_by_uid(ldap_state, ldap_struct, + pdb_user_rid_to_uid(rid), + result); return rc; } @@ -264,21 +339,22 @@ static int ldap_search_one_user_by_rid (LDAP * ldap_struct, uint32 rid, search an attribute and return the first value found. ******************************************************************/ static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, - char *attribute, char *value) + char *attribute, char *value) { char **values; if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { value = NULL; - DEBUG (2, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute)); + DEBUG (10, ("get_single_attribute: [%s] = [<does not exist>]\n", attribute)); return False; } - + pstrcpy(value, values[0]); ldap_value_free(values); - DEBUG (2, ("get_single_attribute: [%s] = [%s]\n", attribute, value)); - +#ifdef DEBUG_PASSWORDS + DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value)); +#endif return True; } @@ -362,8 +438,9 @@ static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, c Initialize SAM_ACCOUNT from an LDAP query (Based on init_sam_from_buffer in pdb_tdb.c) *********************************************************************/ -static BOOL init_sam_from_ldap (SAM_ACCOUNT * sampass, - LDAP * ldap_struct, LDAPMessage * entry) +static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, + SAM_ACCOUNT * sampass, + LDAP * ldap_struct, LDAPMessage * entry) { time_t logon_time, logoff_time, @@ -424,27 +501,80 @@ static BOOL init_sam_from_ldap (SAM_ACCOUNT * sampass, pstrcpy(domain, lp_workgroup()); + get_single_attribute(ldap_struct, entry, "rid", temp); + user_rid = (uint32)atol(temp); + if (!get_single_attribute(ldap_struct, entry, "primaryGroupID", temp)) { + group_rid = 0; + } else { + group_rid = (uint32)atol(temp); + } + + if ((ldap_state->permit_non_unix_accounts) + && (user_rid >= ldap_state->low_nua_rid) + && (user_rid <= ldap_state->high_nua_rid)) { + + } else { + + /* These values MAY be in LDAP, but they can also be retrieved through + * sys_getpw*() which is how we're doing it + */ + + pw = getpwnam_alloc(username); + if (pw == NULL) { + DEBUG (2,("init_sam_from_ldap: User [%s] does not ave a uid!\n", username)); + return False; + } + uid = pw->pw_uid; + gid = pw->pw_gid; + + passwd_free(&pw); + + pdb_set_uid(sampass, uid); + pdb_set_gid(sampass, gid); + + if (group_rid == 0) { + GROUP_MAP map; + /* call the mapping code here */ + if(get_group_map_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) { + sid_peek_rid(&map.sid, &group_rid); + } + else { + group_rid=pdb_gid_to_group_rid(gid); + } + } + } + get_single_attribute(ldap_struct, entry, "pwdLastSet", temp); - pass_last_set_time = (time_t) strtol(temp, NULL, 16); + pass_last_set_time = (time_t) atol(temp); - get_single_attribute(ldap_struct, entry, "logonTime", temp); - logon_time = (time_t) strtol(temp, NULL, 16); + if (!get_single_attribute(ldap_struct, entry, "logonTime", temp)) { + logon_time = (time_t) atol(temp); + pdb_set_logon_time(sampass, logon_time, True); + } - get_single_attribute(ldap_struct, entry, "logoffTime", temp); - logoff_time = (time_t) strtol(temp, NULL, 16); + if (!get_single_attribute(ldap_struct, entry, "logoffTime", temp)) { + logoff_time = (time_t) atol(temp); + pdb_set_logoff_time(sampass, logoff_time, True); + } - get_single_attribute(ldap_struct, entry, "kickoffTime", temp); - kickoff_time = (time_t) strtol(temp, NULL, 16); + if (!get_single_attribute(ldap_struct, entry, "kickoffTime", temp)) { + kickoff_time = (time_t) atol(temp); + pdb_set_kickoff_time(sampass, kickoff_time, True); + } - get_single_attribute(ldap_struct, entry, "pwdCanChange", temp); - pass_can_change_time = (time_t) strtol(temp, NULL, 16); + if (!get_single_attribute(ldap_struct, entry, "pwdCanChange", temp)) { + pass_can_change_time = (time_t) atol(temp); + pdb_set_pass_can_change_time(sampass, pass_can_change_time, True); + } - get_single_attribute(ldap_struct, entry, "pwdMustChange", temp); - pass_must_change_time = (time_t) strtol(temp, NULL, 16); + if (!get_single_attribute(ldap_struct, entry, "pwdMustChange", temp)) { + pass_must_change_time = (time_t) atol(temp); + pdb_set_pass_must_change_time(sampass, pass_must_change_time, True); + } /* recommend that 'gecos' and 'displayName' should refer to the same - * attribute OID. userFullName depreciated, only used by Samba - * primary rules of LDAP: don't make a new attribute when one is already defined + * attribute OID. userFullName depreciated, only used by Samba + * primary rules of LDAP: don't make a new attribute when one is already defined * that fits your needs; using cn then displayName rather than 'userFullName' */ @@ -491,25 +621,6 @@ static BOOL init_sam_from_ldap (SAM_ACCOUNT * sampass, get_single_attribute(ldap_struct, entry, "description", acct_desc); get_single_attribute(ldap_struct, entry, "userWorkstations", workstations); - get_single_attribute(ldap_struct, entry, "rid", temp); - user_rid = (uint32)strtol(temp, NULL, 10); - get_single_attribute(ldap_struct, entry, "primaryGroupID", temp); - group_rid = (uint32)strtol(temp, NULL, 10); - - - /* These values MAY be in LDAP, but they can also be retrieved through - * sys_getpw*() which is how we're doing it - */ - pw = getpwnam_alloc(username); - if (pw == NULL) { - DEBUG (2,("init_sam_from_ldap: User [%s] does not ave a uid!\n", username)); - return False; - } - uid = pw->pw_uid; - gid = pw->pw_gid; - - passwd_free(&pw); - /* FIXME: hours stuff should be cleaner */ logon_divs = 168; @@ -527,16 +638,8 @@ static BOOL init_sam_from_ldap (SAM_ACCOUNT * sampass, if (acct_ctrl == 0) acct_ctrl |= ACB_NORMAL; - - pdb_set_uid(sampass, uid); - pdb_set_gid(sampass, gid); pdb_set_acct_ctrl(sampass, acct_ctrl); - pdb_set_logon_time(sampass, logon_time); - pdb_set_logoff_time(sampass, logoff_time); - pdb_set_kickoff_time(sampass, kickoff_time); - pdb_set_pass_can_change_time(sampass, pass_can_change_time); - pdb_set_pass_must_change_time(sampass, pass_must_change_time); pdb_set_pass_last_set_time(sampass, pass_last_set_time); pdb_set_hours_len(sampass, hours_len); @@ -574,9 +677,12 @@ static BOOL init_sam_from_ldap (SAM_ACCOUNT * sampass, Initialize SAM_ACCOUNT from an LDAP query (Based on init_buffer_from_sam in pdb_tdb.c) *********************************************************************/ -static BOOL init_ldap_from_sam (LDAPMod *** mods, int ldap_state, const SAM_ACCOUNT * sampass) +static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, + LDAPMod *** mods, int ldap_op, + const SAM_ACCOUNT * sampass) { pstring temp; + uint32 rid; if (mods == NULL || sampass == NULL) { DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n")); @@ -590,27 +696,43 @@ static BOOL init_ldap_from_sam (LDAPMod *** mods, int ldap_state, const SAM_ACCO * do this on a per-mod basis */ - - make_a_mod(mods, ldap_state, "uid", pdb_get_username(sampass)); + make_a_mod(mods, ldap_op, "uid", pdb_get_username(sampass)); DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass))); - slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass)); - make_a_mod(mods, ldap_state, "pwdLastSet", temp); - - slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass)); - make_a_mod(mods, ldap_state, "logonTime", temp); - - slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass)); - make_a_mod(mods, ldap_state, "logoffTime", temp); + if ( pdb_get_user_rid(sampass) ) { + rid = pdb_get_user_rid(sampass); + } else if (IS_SAM_SET(sampass, FLAG_SAM_UID)) { + rid = pdb_uid_to_user_rid(pdb_get_uid(sampass)); + } else if (ldap_state->permit_non_unix_accounts) { + rid = ldapsam_get_next_available_nua_rid(ldap_state); + if (rid == 0) { + DEBUG(0, ("NO user RID specified on account %s, and findining next available NUA RID failed, cannot store!\n", pdb_get_username(sampass))); + return False; + } + } else { + DEBUG(0, ("NO user RID specified on account %s, cannot store!\n", pdb_get_username(sampass))); + return False; + } - slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass)); - make_a_mod(mods, ldap_state, "kickoffTime", temp); + slprintf(temp, sizeof(temp) - 1, "%i", rid); + make_a_mod(mods, ldap_op, "rid", temp); + + if ( pdb_get_group_rid(sampass) ) { + rid = pdb_get_group_rid(sampass); + } else if (IS_SAM_SET(sampass, FLAG_SAM_GID)) { + rid = pdb_gid_to_group_rid(pdb_get_gid(sampass)); + } else if (ldap_state->permit_non_unix_accounts) { + rid = DOMAIN_GROUP_RID_USERS; + } else { + DEBUG(0, ("NO group RID specified on account %s, cannot store!\n", pdb_get_username(sampass))); + return False; + } - slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass)); - make_a_mod(mods, ldap_state, "pwdCanChange", temp); + slprintf(temp, sizeof(temp) - 1, "%i", rid); + make_a_mod(mods, ldap_op, "primaryGroupID", temp); - slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass)); - make_a_mod(mods, ldap_state, "pwdMustChange", 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 @@ -618,96 +740,261 @@ static BOOL init_ldap_from_sam (LDAPMod *** mods, int ldap_state, const SAM_ACCO * add-user script */ - make_a_mod(mods, ldap_state, "displayName", pdb_get_fullname(sampass)); - make_a_mod(mods, ldap_state, "cn", pdb_get_fullname(sampass)); - make_a_mod(mods, ldap_state, "description", pdb_get_acct_desc(sampass)); - make_a_mod(mods, ldap_state, "userWorkstations", pdb_get_workstations(sampass)); + make_a_mod(mods, ldap_op, "displayName", pdb_get_fullname(sampass)); + make_a_mod(mods, ldap_op, "cn", pdb_get_fullname(sampass)); + make_a_mod(mods, ldap_op, "description", pdb_get_acct_desc(sampass)); + make_a_mod(mods, ldap_op, "userWorkstations", pdb_get_workstations(sampass)); /* * Only updates fields which have been set (not defaults from smb.conf) */ if (IS_SAM_SET(sampass, FLAG_SAM_SMBHOME)) - make_a_mod(mods, ldap_state, "smbHome", pdb_get_homedir(sampass)); + make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass)); if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE)) - make_a_mod(mods, ldap_state, "homeDrive", pdb_get_dirdrive(sampass)); - + make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dirdrive(sampass)); + if (IS_SAM_SET(sampass, FLAG_SAM_LOGONSCRIPT)) - make_a_mod(mods, ldap_state, "scriptPath", pdb_get_logon_script(sampass)); + make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass)); if (IS_SAM_SET(sampass, FLAG_SAM_PROFILE)) - make_a_mod(mods, ldap_state, "profilePath", pdb_get_profile_path(sampass)); + make_a_mod(mods, ldap_op, "profilePath", pdb_get_profile_path(sampass)); + if (IS_SAM_SET(sampass, FLAG_SAM_LOGONTIME)) { + slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass)); + make_a_mod(mods, ldap_op, "logonTime", temp); + } - if ( !pdb_get_user_rid(sampass)) - slprintf(temp, sizeof(temp) - 1, "%i", pdb_uid_to_user_rid(pdb_get_uid(sampass))); - else - slprintf(temp, sizeof(temp) - 1, "%i", pdb_get_user_rid(sampass)); - make_a_mod(mods, ldap_state, "rid", temp); + if (IS_SAM_SET(sampass, FLAG_SAM_LOGOFFTIME)) { + slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass)); + make_a_mod(mods, ldap_op, "logoffTime", temp); + } - if ( !pdb_get_group_rid(sampass)) - slprintf(temp, sizeof(temp) - 1, "%i", pdb_gid_to_group_rid(pdb_get_gid(sampass))); - else - slprintf(temp, sizeof(temp) - 1, "%i", pdb_get_group_rid(sampass)); - make_a_mod(mods, ldap_state, "primaryGroupID", temp); + if (IS_SAM_SET(sampass, FLAG_SAM_KICKOFFTIME)) { + slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass)); + 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); + } + + if (IS_SAM_SET(sampass, FLAG_SAM_MUSTCHANGETIME)) { + slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass)); + 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_state, "lmPassword", temp); + 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_state, "ntPassword", temp); + make_a_mod (mods, ldap_op, "ntPassword", temp); - make_a_mod (mods, ldap_state, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), + make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN)); return True; } + +/********************************************************************** +Connect to LDAP server and find the next available RID. +*********************************************************************/ +static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32 top_rid, LDAP *ldap_struct) +{ + LDAPMessage *result; + uint32 final_rid = (top_rid & (~USER_RID_TYPE)) + RID_MULTIPLIER; + if (top_rid == 0) { + return 0; + } + + if (final_rid < ldap_state->low_nua_rid || final_rid > ldap_state->high_nua_rid) { + return 0; + } + + if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, final_rid, &result) != LDAP_SUCCESS) { + DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid)); + final_rid = 0; + ldap_msgfree(result); + } + + if (ldap_count_entries(ldap_struct, result) != 0) + { + DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid)); + final_rid = 0; + ldap_msgfree(result); + } + + DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid)); + return final_rid; +} + +/********************************************************************** +Extract the RID from an LDAP entry +*********************************************************************/ +static uint32 entry_to_user_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, LDAP *ldap_struct) { + uint32 rid; + SAM_ACCOUNT *user = NULL; + if (!NT_STATUS_IS_OK(pdb_init_sam(&user))) { + return 0; + } + + if (init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) { + rid = pdb_get_user_rid(user); + } else { + rid =0; + } + pdb_free_sam(&user); + if (rid >= ldap_state->low_nua_rid && rid <= ldap_state->high_nua_rid) { + return rid; + } + return 0; +} + + +/********************************************************************** +Connect to LDAP server and find the next available RID. +*********************************************************************/ +static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state, LDAP *ldap_struct) +{ + int rc; + pstring filter; + LDAPMessage *result; + LDAPMessage *entry; + char *final_filter = NULL; + uint32 top_rid = 0; + uint32 count; + uint32 rid; + + pstrcpy(filter, lp_ldap_filter()); + all_string_sub(filter, "%u", "*", sizeof(pstring)); + +#if 0 + asprintf(&final_filter, "(&(%s)(&(rid>=%d)(rid<=%d)))", filter, ldap_state->low_nua_rid, ldap_state->high_nua_rid); +#else + final_filter = strdup(filter); +#endif + 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, NULL, 0, + &result); + + if (rc != LDAP_SUCCESS) + { + + DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc))); + DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter)); + + free(final_filter); + ldap_msgfree(result); + result = NULL; + return 0; + } + + count = ldap_count_entries(ldap_struct, result); + DEBUG(2, ("search_top_nua_rid: %d entries in the base!\n", count)); + + if (count == 0) { + DEBUG(3, ("LDAP search returned no records, assuming no non-unix-accounts present!: %s\n", ldap_err2string(rc))); + DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter)); + free(final_filter); + ldap_msgfree(result); + result = NULL; + return ldap_state->low_nua_rid; + } + + free(final_filter); + entry = ldap_first_entry(ldap_struct,result); + + top_rid = entry_to_user_rid(ldap_state, entry, ldap_struct); + + while ((entry = ldap_next_entry(ldap_struct, entry))) { + + rid = entry_to_user_rid(ldap_state, entry, ldap_struct); + if (rid > top_rid) { + top_rid = rid; + } + } + + ldap_msgfree(result); + return top_rid; +} + +/********************************************************************** +Connect to LDAP server and find the next available RID. +*********************************************************************/ +static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state) { + LDAP *ldap_struct; + uint32 next_nua_rid; + uint32 top_nua_rid; + + if (!ldapsam_open_connection(ldap_state, &ldap_struct)) + { + return 0; + } + if (!ldapsam_connect_system(ldap_state, ldap_struct)) + { + ldap_unbind(ldap_struct); + return 0; + } + + top_nua_rid = search_top_nua_rid(ldap_state, ldap_struct); + + next_nua_rid = check_nua_rid_is_avail(ldap_state, + top_nua_rid, ldap_struct); + + ldap_unbind(ldap_struct); + return next_nua_rid; +} + /********************************************************************** Connect to LDAP server for password enumeration *********************************************************************/ -BOOL pdb_setsampwent(BOOL update) +static BOOL ldapsam_setsampwent(struct pdb_context *context, BOOL update) { + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; int rc; pstring filter; - if (!ldap_open_connection(&global_ldap_ent.ldap_struct)) + if (!ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct)) { return False; } - if (!ldap_connect_system(global_ldap_ent.ldap_struct)) + if (!ldapsam_connect_system(ldap_state, ldap_state->ldap_struct)) { - ldap_unbind(global_ldap_ent.ldap_struct); + ldap_unbind(ldap_state->ldap_struct); return False; } pstrcpy(filter, lp_ldap_filter()); all_string_sub(filter, "%u", "*", sizeof(pstring)); - rc = ldap_search_s(global_ldap_ent.ldap_struct, lp_ldap_suffix(), + rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE, filter, NULL, 0, - &global_ldap_ent.result); + &ldap_state->result); if (rc != LDAP_SUCCESS) { DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc))); DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - ldap_msgfree(global_ldap_ent.result); - ldap_unbind(global_ldap_ent.ldap_struct); - global_ldap_ent.ldap_struct = NULL; - global_ldap_ent.result = NULL; + ldap_msgfree(ldap_state->result); + ldap_unbind(ldap_state->ldap_struct); + ldap_state->ldap_struct = NULL; + ldap_state->result = NULL; return False; } - DEBUG(2, ("pdb_setsampwent: %d entries in the base!\n", - ldap_count_entries(global_ldap_ent.ldap_struct, - global_ldap_ent.result))); + DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n", + ldap_count_entries(ldap_state->ldap_struct, + ldap_state->result))); - global_ldap_ent.entry = ldap_first_entry(global_ldap_ent.ldap_struct, - global_ldap_ent.result); - global_ldap_ent.index = -1; + ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct, + ldap_state->result); + ldap_state->index = 0; return True; } @@ -715,63 +1002,67 @@ BOOL pdb_setsampwent(BOOL update) /********************************************************************** End enumeration of the LDAP password list *********************************************************************/ -void pdb_endsampwent(void) +static void ldapsam_endsampwent(struct pdb_context *context) { - if (global_ldap_ent.ldap_struct && global_ldap_ent.result) + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + if (ldap_state->ldap_struct && ldap_state->result) { - ldap_msgfree(global_ldap_ent.result); - ldap_unbind(global_ldap_ent.ldap_struct); - global_ldap_ent.ldap_struct = NULL; - global_ldap_ent.result = NULL; + ldap_msgfree(ldap_state->result); + ldap_unbind(ldap_state->ldap_struct); + ldap_state->ldap_struct = NULL; + ldap_state->result = NULL; } } /********************************************************************** Get the next entry in the LDAP password database *********************************************************************/ -BOOL pdb_getsampwent(SAM_ACCOUNT * user) +static BOOL ldapsam_getsampwent(struct pdb_context *context, SAM_ACCOUNT * user) { - if (!global_ldap_ent.entry) - return False; + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; + BOOL ret = False; - global_ldap_ent.index++; - if (global_ldap_ent.index > 0) - { - global_ldap_ent.entry = ldap_next_entry(global_ldap_ent.ldap_struct, global_ldap_ent.entry); + while (!ret) { + if (!ldap_state->entry) + return False; + + ldap_state->index++; + ret = init_sam_from_ldap(ldap_state, user, ldap_state->ldap_struct, + ldap_state->entry); + + ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct, + ldap_state->entry); + } - if (global_ldap_ent.entry != NULL) - { - return init_sam_from_ldap(user, global_ldap_ent.ldap_struct, - global_ldap_ent.entry); - } - return False; + return True; } /********************************************************************** Get SAM_ACCOUNT entry from LDAP by username *********************************************************************/ -BOOL pdb_getsampwnam(SAM_ACCOUNT * user, const char *sname) +static BOOL ldapsam_getsampwnam(struct pdb_context *context, SAM_ACCOUNT * user, const char *sname) { + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; LDAP *ldap_struct; LDAPMessage *result; LDAPMessage *entry; - if (!ldap_open_connection(&ldap_struct)) + if (!ldapsam_open_connection(ldap_state, &ldap_struct)) return False; - if (!ldap_connect_system(ldap_struct)) + if (!ldapsam_connect_system(ldap_state, ldap_struct)) { ldap_unbind(ldap_struct); return False; } - if (ldap_search_one_user_by_name(ldap_struct, sname, &result) != LDAP_SUCCESS) + if (ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result) != LDAP_SUCCESS) { ldap_unbind(ldap_struct); return False; } if (ldap_count_entries(ldap_struct, result) < 1) { - DEBUG(0, + DEBUG(4, ("We don't find this user [%s] count=%d\n", sname, ldap_count_entries(ldap_struct, result))); ldap_unbind(ldap_struct); @@ -780,7 +1071,12 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT * user, const char *sname) entry = ldap_first_entry(ldap_struct, result); if (entry) { - init_sam_from_ldap(user, ldap_struct, entry); + if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) { + DEBUG(0,("ldapsam_getsampwnam: init_sam_from_ldap failed!\n")); + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return False; + } ldap_msgfree(result); ldap_unbind(ldap_struct); return True; @@ -796,21 +1092,22 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT * user, const char *sname) /********************************************************************** Get SAM_ACCOUNT entry from LDAP by rid *********************************************************************/ -BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) +static BOOL ldapsam_getsampwrid(struct pdb_context *context, SAM_ACCOUNT * user, uint32 rid) { + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; LDAP *ldap_struct; LDAPMessage *result; LDAPMessage *entry; - if (!ldap_open_connection(&ldap_struct)) + if (!ldapsam_open_connection(ldap_state, &ldap_struct)) return False; - if (!ldap_connect_system(ldap_struct)) + if (!ldapsam_connect_system(ldap_state, ldap_struct)) { ldap_unbind(ldap_struct); return False; } - if (ldap_search_one_user_by_rid(ldap_struct, rid, &result) != + if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, rid, &result) != LDAP_SUCCESS) { ldap_unbind(ldap_struct); @@ -829,7 +1126,12 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) entry = ldap_first_entry(ldap_struct, result); if (entry) { - init_sam_from_ldap(user, ldap_struct, entry); + if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) { + DEBUG(0,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n")); + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return False; + } ldap_msgfree(result); ldap_unbind(ldap_struct); return True; @@ -845,8 +1147,9 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) /********************************************************************** Delete entry from LDAP for username *********************************************************************/ -BOOL pdb_delete_sam_account(SAM_ACCOUNT * sam_acct) +static BOOL ldapsam_delete_sam_account(struct pdb_context *context, const SAM_ACCOUNT * sam_acct) { + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; const char *sname; int rc; char *dn; @@ -861,18 +1164,18 @@ BOOL pdb_delete_sam_account(SAM_ACCOUNT * sam_acct) sname = pdb_get_username(sam_acct); - if (!ldap_open_connection (&ldap_struct)) + if (!ldapsam_open_connection(ldap_state, &ldap_struct)) return False; DEBUG (3, ("Deleting user %s from LDAP.\n", sname)); - if (!ldap_connect_system (ldap_struct)) { + if (!ldapsam_connect_system(ldap_state, ldap_struct)) { ldap_unbind (ldap_struct); DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname)); return False; } - rc = ldap_search_one_user_by_name (ldap_struct, sname, &result); + rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result); if (ldap_count_entries (ldap_struct, result) == 0) { DEBUG (0, ("User doesn't exit!\n")); ldap_msgfree (result); @@ -904,8 +1207,9 @@ BOOL pdb_delete_sam_account(SAM_ACCOUNT * sam_acct) /********************************************************************** Update SAM_ACCOUNT *********************************************************************/ -BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd) +static BOOL ldapsam_update_sam_account(struct pdb_context *context, const SAM_ACCOUNT * newpwd) { + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; int rc; char *dn; LDAP *ldap_struct; @@ -913,17 +1217,17 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd) LDAPMessage *entry; LDAPMod **mods; - if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */ return False; - if (!ldap_connect_system(ldap_struct)) /* connect as system account */ + if (!ldapsam_connect_system(ldap_state, ldap_struct)) /* connect as system account */ { ldap_unbind(ldap_struct); return False; } - rc = ldap_search_one_user_by_name(ldap_struct, - pdb_get_username(newpwd), &result); + rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct, + pdb_get_username(newpwd), &result); if (ldap_count_entries(ldap_struct, result) == 0) { @@ -933,7 +1237,12 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd) return False; } - init_ldap_from_sam(&mods, LDAP_MOD_REPLACE, newpwd); + if (!init_ldap_from_sam(ldap_state, &mods, LDAP_MOD_REPLACE, newpwd)) { + DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n")); + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return False; + } entry = ldap_first_entry(ldap_struct, result); dn = ldap_get_dn(ldap_struct, entry); @@ -965,29 +1274,30 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd) /********************************************************************** Add SAM_ACCOUNT to LDAP *********************************************************************/ -BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) +static BOOL ldapsam_add_sam_account(struct pdb_context *context, const SAM_ACCOUNT * newpwd) { + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)context->pdb_selected->private_data; int rc; pstring filter; - LDAP *ldap_struct; - LDAPMessage *result; + LDAP *ldap_struct = NULL; + LDAPMessage *result = NULL; pstring dn; - LDAPMod **mods; + LDAPMod **mods = NULL; int ldap_op; uint32 num_result; - if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */ { return False; } - if (!ldap_connect_system(ldap_struct)) /* connect as system account */ + if (!ldapsam_connect_system(ldap_state, ldap_struct)) /* connect as system account */ { ldap_unbind(ldap_struct); return False; } - rc = ldap_search_one_user_by_name (ldap_struct, pdb_get_username(newpwd), &result); + rc = ldapsam_search_one_user_by_name (ldap_state, ldap_struct, pdb_get_username(newpwd), &result); if (ldap_count_entries(ldap_struct, result) != 0) { @@ -999,7 +1309,7 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) ldap_msgfree(result); slprintf (filter, sizeof (filter) - 1, "uid=%s", pdb_get_username(newpwd)); - rc = ldap_search_one_user(ldap_struct, filter, &result); + rc = ldapsam_search_one_user(ldap_state, ldap_struct, filter, &result); num_result = ldap_count_entries(ldap_struct, result); if (num_result > 1) { @@ -1023,12 +1333,22 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) /* Check if we need to add an entry */ DEBUG(3,("Adding new user\n")); ldap_op = LDAP_MOD_ADD; - slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", pdb_get_username(newpwd), lp_ldap_suffix ()); + if ( pdb_get_acct_ctrl( newpwd ) & ACB_WSTRUST ) { + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", pdb_get_username(newpwd), lp_ldap_machine_suffix ()); + } + else { + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", pdb_get_username(newpwd), lp_ldap_user_suffix ()); + } } ldap_msgfree(result); - init_ldap_from_sam(&mods, ldap_op, newpwd); + if (!init_ldap_from_sam(ldap_state, &mods, ldap_op, newpwd)) { + DEBUG(0, ("ldapsam_add_sam_account: init_ldap_from_sam failed!\n")); + ldap_mods_free(mods, 1); + ldap_unbind(ldap_struct); + return False; + } make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount"); if (ldap_op == LDAP_MOD_REPLACE) { @@ -1043,8 +1363,8 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) char *ld_error; ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(0,("failed to modify user with uid = %s with: %s\n\t%s\n", - pdb_get_username(newpwd), ldap_err2string (rc), ld_error)); + DEBUG(0,("failed to modify/add user with uid = %s (dn = %s) with: %s\n\t%s\n", + pdb_get_username(newpwd), dn, ldap_err2string (rc), ld_error)); free(ld_error); ldap_mods_free(mods, 1); ldap_unbind(ldap_struct); @@ -1057,10 +1377,105 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) return True; } +static void free_private_data(void **vp) +{ + struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp; + + if ((*ldap_state)->ldap_struct) { + ldap_unbind((*ldap_state)->ldap_struct); + } + + *ldap_state = NULL; + + /* No need to free any further, as it is talloc()ed */ +} + +NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + struct ldapsam_privates *ldap_state; + + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { + return nt_status; + } + + (*pdb_method)->name = "ldapsam"; + + (*pdb_method)->setsampwent = ldapsam_setsampwent; + (*pdb_method)->endsampwent = ldapsam_endsampwent; + (*pdb_method)->getsampwent = ldapsam_getsampwent; + (*pdb_method)->getsampwnam = ldapsam_getsampwnam; + (*pdb_method)->getsampwrid = ldapsam_getsampwrid; + (*pdb_method)->add_sam_account = ldapsam_add_sam_account; + (*pdb_method)->update_sam_account = ldapsam_update_sam_account; + (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account; + + /* TODO: Setup private data and free */ + + ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates)); + + if (!ldap_state) { + DEBUG(0, ("talloc() failed for ldapsam private_data!\n")); + return NT_STATUS_NO_MEMORY; + } + + if (location) { + ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location); + } else { + ldap_state->uri = "ldap://localhost"; + return NT_STATUS_INVALID_PARAMETER; + } + + (*pdb_method)->private_data = ldap_state; + + (*pdb_method)->free_private_data = free_private_data; + + return NT_STATUS_OK; +} + +NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + struct ldapsam_privates *ldap_state; + uint32 low_nua_uid, high_nua_uid; + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam(pdb_context, pdb_method, location))) { + return nt_status; + } + + (*pdb_method)->name = "ldapsam_nua"; + + ldap_state = (*pdb_method)->private_data; + + ldap_state->permit_non_unix_accounts = True; + + if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) { + DEBUG(0, ("cannot use ldapsam_nua without 'non unix account range' in smb.conf!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + ldap_state->low_nua_rid=pdb_uid_to_user_rid(low_nua_uid); + + ldap_state->high_nua_rid=pdb_uid_to_user_rid(high_nua_uid); + + return NT_STATUS_OK; +} + + #else -void dummy_function(void); -void -dummy_function (void) + +NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { -} /* stop some compilers complaining */ + DEBUG(0, ("ldapsam not compiled in!\n")); + return NT_STATUS_UNSUCCESSFUL; +} + +NTSTATUS pdb_init_ldapsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + DEBUG(0, ("ldapsam_nua not compiled in!\n")); + return NT_STATUS_UNSUCCESSFUL; +} + + #endif + diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index d895600e8e..e32af604fd 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -1302,7 +1302,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_AC pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd); pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl); pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time); - pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time); + pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time, True); pdb_set_domain (sam_pass, lp_workgroup()); pdb_set_dir_drive (sam_pass, lp_logon_drive(), False); diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index 3c76f8336b..40ba8dd475 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -157,11 +157,11 @@ static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, pdb_set_gid(sampass, gid); } - pdb_set_logon_time(sampass, logon_time); - pdb_set_logoff_time(sampass, logoff_time); - pdb_set_kickoff_time(sampass, kickoff_time); - pdb_set_pass_can_change_time(sampass, pass_can_change_time); - pdb_set_pass_must_change_time(sampass, pass_must_change_time); + pdb_set_logon_time(sampass, logon_time, True); + pdb_set_logoff_time(sampass, logoff_time, True); + pdb_set_kickoff_time(sampass, kickoff_time, True); + pdb_set_pass_can_change_time(sampass, pass_can_change_time, True); + pdb_set_pass_must_change_time(sampass, pass_must_change_time, True); pdb_set_pass_last_set_time(sampass, pass_last_set_time); pdb_set_username (sampass, username); diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index dbcd3e5579..5be6bee00e 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -353,31 +353,3 @@ BOOL secrets_store_ldap_pw(char* dn, char* pw) return secrets_store(key, pw, strlen(pw)); } -BOOL fetch_ldap_pw(char *dn, char* pw, int len) -{ - fstring key; - char *p; - void *data = NULL; - size_t size; - - pstrcpy(key, dn); - for (p=key; *p; p++) - if (*p == ',') *p = '/'; - - data=secrets_fetch(key, &size); - if (!size) { - DEBUG(0,("fetch_ldap_pw: no ldap secret retrieved!\n")); - return False; - } - - if (size > len-1) - { - DEBUG(0,("fetch_ldap_pw: ldap secret is too long (%d > %d)!\n", size, len-1)); - return False; - } - - memcpy(pw, data, size); - pw[size] = '\0'; - - return True; -} |