summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2002-08-17 17:00:51 +0000
committerJelmer Vernooij <jelmer@samba.org>2002-08-17 17:00:51 +0000
commit3928578b52cfc949be5e0ef444fce1558d75f290 (patch)
tree651ed4a38e217dfa3f3874e7db8e45e7429af1f0
parenteac75549c398f208484ae735d5a5931fed6d0e99 (diff)
downloadsamba-3928578b52cfc949be5e0ef444fce1558d75f290.tar.gz
samba-3928578b52cfc949be5e0ef444fce1558d75f290.tar.xz
samba-3928578b52cfc949be5e0ef444fce1558d75f290.zip
sync 3.0 branch with head
-rw-r--r--WHATSNEW.txt98
-rw-r--r--source/auth/auth.c14
-rw-r--r--source/auth/auth_domain.c139
-rw-r--r--source/auth/auth_sam.c19
-rw-r--r--source/auth/auth_util.c5
-rw-r--r--source/auth/auth_winbind.c70
-rw-r--r--source/client/clitar.c2
-rw-r--r--source/client/smbmount.c3
-rw-r--r--source/client/smbspool.c15
-rwxr-xr-xsource/configure90
-rw-r--r--source/configure.in31
-rw-r--r--source/include/ads.h62
-rw-r--r--source/include/config.h.in17
-rw-r--r--source/include/includes.h2
-rw-r--r--source/include/local.h14
-rw-r--r--source/include/messages.h1
-rw-r--r--source/include/nameserv.h2
-rw-r--r--source/include/nt_printing.h32
-rw-r--r--source/include/passdb.h4
-rw-r--r--source/include/rpc_lsa.h38
-rw-r--r--source/include/rpc_reg.h108
-rw-r--r--source/include/rpc_samr.h72
-rwxr-xr-xsource/include/rpc_spoolss.h14
-rw-r--r--source/include/rpc_srvsvc.h116
-rw-r--r--source/include/secrets.h4
-rw-r--r--source/include/smb.h27
-rw-r--r--source/include/version.h2
-rw-r--r--source/include/vfs.h201
-rw-r--r--source/intl/lang_tdb.c6
-rw-r--r--source/lib/account_pol.c88
-rw-r--r--source/lib/charcnv.c19
-rw-r--r--source/lib/debug.c8
-rw-r--r--source/lib/genrand.c2
-rw-r--r--source/lib/replace.c2
-rw-r--r--source/lib/smbrun.c2
-rw-r--r--source/lib/substitute.c53
-rw-r--r--source/lib/system.c10
-rw-r--r--source/lib/username.c2
-rw-r--r--source/lib/util.c38
-rw-r--r--source/lib/util_getent.c21
-rw-r--r--source/lib/util_sid.c3
-rw-r--r--source/lib/util_sock.c2
-rw-r--r--source/lib/util_str.c165
-rw-r--r--source/lib/wins_srv.c2
-rw-r--r--source/lib/xfile.c2
-rw-r--r--source/libads/ads_struct.c107
-rw-r--r--source/libads/kerberos.c12
-rw-r--r--source/libads/kerberos_verify.c2
-rw-r--r--source/libads/ldap.c389
-rw-r--r--source/libads/ldap_user.c6
-rw-r--r--source/libads/sasl.c9
-rw-r--r--source/libads/util.c2
-rw-r--r--source/libsmb/cliconnect.c47
-rw-r--r--source/libsmb/clispnego.c61
-rw-r--r--source/libsmb/namequery.c67
-rw-r--r--source/libsmb/smbencrypt.c16
-rw-r--r--source/libsmb/trust_passwd.c2
-rw-r--r--source/nmbd/asyncdns.c1
-rw-r--r--source/nmbd/nmbd.c11
-rw-r--r--source/nmbd/nmbd_become_dmb.c2
-rw-r--r--source/nmbd/nmbd_mynames.c2
-rw-r--r--source/nmbd/nmbd_nameregister.c22
-rw-r--r--source/nmbd/nmbd_packets.c25
-rw-r--r--source/nmbd/nmbd_processlogon.c113
-rw-r--r--source/nsswitch/pam_winbind.c18
-rw-r--r--source/nsswitch/wb_client.c6
-rw-r--r--source/nsswitch/wb_common.c17
-rw-r--r--source/nsswitch/wbinfo.c7
-rw-r--r--source/nsswitch/winbindd.c7
-rw-r--r--source/nsswitch/winbindd.h8
-rw-r--r--source/nsswitch/winbindd_ads.c119
-rw-r--r--source/nsswitch/winbindd_cache.c15
-rw-r--r--source/nsswitch/winbindd_cm.c196
-rw-r--r--source/nsswitch/winbindd_group.c6
-rw-r--r--source/nsswitch/winbindd_nss.h12
-rw-r--r--source/nsswitch/winbindd_pam.c139
-rw-r--r--source/nsswitch/winbindd_rpc.c15
-rw-r--r--source/nsswitch/winbindd_sid.c15
-rw-r--r--source/nsswitch/winbindd_user.c3
-rw-r--r--source/nsswitch/winbindd_util.c118
-rw-r--r--source/nsswitch/winbindd_wins.c6
-rw-r--r--source/param/loadparm.c96
-rw-r--r--source/passdb/passdb.c158
-rw-r--r--source/passdb/pdb_get_set.c11
-rw-r--r--source/passdb/pdb_interface.c6
-rw-r--r--source/passdb/pdb_ldap.c179
-rw-r--r--source/passdb/pdb_nisplus.c16
-rw-r--r--source/passdb/pdb_smbpasswd.c4
-rw-r--r--source/passdb/pdb_tdb.c7
-rw-r--r--source/passdb/pdb_unix.c29
-rw-r--r--source/passdb/secrets.c62
-rw-r--r--source/passdb/util_sam_sid.c3
-rw-r--r--source/printing/pcap.c11
-rw-r--r--source/printing/print_svid.c2
-rw-r--r--source/printing/printfsp.c6
-rw-r--r--source/printing/printing.c399
-rw-r--r--source/rpc_parse/parse_lsa.c123
-rw-r--r--source/rpc_parse/parse_net.c2
-rw-r--r--source/rpc_parse/parse_prs.c8
-rw-r--r--source/rpc_parse/parse_reg.c269
-rw-r--r--source/rpc_parse/parse_samr.c88
-rw-r--r--source/rpc_parse/parse_spoolss.c87
-rw-r--r--source/rpc_parse/parse_srv.c703
103 files changed, 4037 insertions, 1462 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index ba9956cdbbb..80383d8eeb1 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,6 +1,104 @@
WHATS NEW IN Samba 3.0 alphaX
=============================
+Changes in alpha19
+ - Heavy registry updates (jerry)
+ - Use 850 as the default DOS character set in smb.conf (tpot)
+ - printer fixes - removed encoding of queueid in job number (jra)
+ - A lot of small fixes (jra)
+ - virtual registry framework with initial printing hooks (jerry)
+ - Don't crash on setfileinfo on printer fsp(jra)
+ - fixed line buffer mode in XFILE(jra)
+ - update samba.schema from 2.2 (jerry,idra)
+ - Fix problem with oplock breaks and win2k -
+ noticed by Lev Iserovich <lev@ciprico.com> (jra)
+ - Give different error message when PDC is down -
+ thanks to Mark Kaplan from Quantum (abartlet)
+ - Add wrapper for dup2() (abartlet)
+ - Update smbgroupedit to document -d - thanks to metze (abartlet)
+ - Support weird behaviour used by win9x pass-through auth (abartlet,tpot)
+ - Support for duplicating stderr in log files (abartlet)
+ - Move startup time initialisation to server.c (abartlet)
+ - *A lot* of fixes and cleanups (abartlet)
+ - Fix up compiler warnings (abartlet)
+ - Few small fixes (tpot)
+ - Renamed new_cli_netlogon_* -> cli_netlogon_* (tpot)
+ - Fixed segfault in net time when host is unavailable (tridge)
+ - Ensure to be root when opening printer backend tdb (jra)
+ - Merges from APPLIANCE_HEAD (tpot,jerry)
+ - configure updates (tridge)
+ - particularly getgrouplist() (tridge)
+ - Make sure to be root when accessing pdb (abartlet)
+ - Better PAM error message (abartlet)
+ - Support for pdbedit to query account policy values (abartlet)
+ - Fix few typos (mimir, abartlet)
+ - Allow one to create trusting domain account using smbpasswd (mimir,abartlet)
+ - 'Net rpc trustdom list' (mimir, abartlet)
+ - Fix fallback to anonymous connection (mimir, abartlet)
+ - Add debugging info to secrets.c (mimir, abartlet)
+ - Fix for pdb_ldap and OpenLDAP 2.1
+ - Added support in swat to determine whether winbind is running (idra)
+ - Add 'hide unwritable' option (idra)
+ - Correct pickup of [homes] share after subsequent session setups (abartlet)
+ - Update rebind code in pdb_ldap (abartlet)
+ - Add some info levels to RPC srvsvc code -
+ thanks to Nigel Williams" <nigel@veritas.com> (abartlet)
+ - Small doc fixes (tridge)
+ - good security patch from Timothy.Sell@unisys.com (tridge)
+ - fix minor nits in nmbd from adtam@cup.hp.com (tridge)
+ - make sure async dns nmbd child dies (tridge)
+ - interim fix for nmbd not registering DOMAIN#1b (tridge)
+ - fix for smbtar filename matching (tridge)
+ - Better quote handling in smb.conf (abartlet)
+ - Support browsers setting multiple languages in swat (idra)
+ - Changed str_list_make to be able to use a different separator string (idra)
+ - Remove use of strtof because of portability issues (idra)
+ - Common popt definition for -d option (tpot)
+ - Samsync support to insert account info into the pdb (tpot)
+ - Don't hide unwritable dirs when 'hide unwritable' is enabled -
+ suggested by Alexander Oswald <oswald@is.haw-hamburg.de> (idra)
+ - Fix for handling sparse files in smbd (tridge)
+ - Merges from 2_2 (jerry)
+ - Add cvslog.pl file
+ - Minor printer fixes (jerry)
+ - Fix SID lookup code to never do recursive winbind (abartlet)
+ - Fix SID lookup code to never use algoritmic rid for fixed mappings (abartlet)
+ - Cascaded VFS (Alexander Bokovoy, idra)
+ - Optimisations when in ADS mode (tridge)
+ - Try netbios-less connections when in ADS mode (tridge)
+ - Minor ADS tweaks (tridge)
+ - Fix plaintext passwords with win2k (tridge)
+ - 'net ads info' reports IP of LDAP server (tridge)
+ - Add LSA RPC 0x2E, lsa_query_info2 (jmcd)
+ - Add 'smb ports = ' option (tridge)
+ - Various small fixes (tridge)
+ - Add 'disable netbios = yes/no' (tridge)
+ - Passdb security checks (abartlet)
+ - Large winbind updates (abartlet)
+ - Moved rpc client routines from libsmb to rpc_client (tpot)
+ - Few nmbd fixes (jmcd)
+ - Fix swat to handle new debug level (idra)
+ - Fix name length in namequeries (tridge)
+ - Netbios-less setup ADS fixes (tridge)
+ - Add SAMR 0x3e, which is samr_connect4 (jmcd)
+ - Add consts to passdb (abartlet)
+ - Don't client binaries depend on libs they don't use -
+ patch from Steve Langasek <vorlon@netexpress.net> (abartlet)
+ - Printing change notification (merged from HEAD_APPLIANCE) (jerry)
+ - fix delete printer driver (from HEAD_APPLIANCE) (jerry)
+ - Added pdb_xml and pdb_mysql (jelmer)
+ - Update pdb_test (jelmer)
+ - Fix security issues with %m (abartlet)
+ - Add client side support for samr connect4 (0x3e) (jmcd)
+ - Add lsa 0x2e (queryinfo2) client side (jmcd)
+ - Support for service joins from win2k AND use SPNEGO (jmcd)
+ - pdbedit -i and -e fix, add -b (idra)
+ - textdocs converted to sgml (jelmer, jerry)
+ - Merge netbios namecache code from APPLIANCE_HEAD (tpot)
+ - Fix segs in new NTLMSSP code (abartlet)
+ - Always make guest rid 501 (abartlet)
+
+
Changes in alpha18
- huge number of changes! really too many to list ... (and its 1am
here, and I'm too tired)
diff --git a/source/auth/auth.c b/source/auth/auth.c
index 4f7a5c24a00..d43afc71e14 100644
--- a/source/auth/auth.c
+++ b/source/auth/auth.c
@@ -395,33 +395,33 @@ NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context)
{
case SEC_DOMAIN:
DEBUG(5,("Making default auth method list for security=domain\n"));
- auth_method_list = str_list_make("guest sam ntdomain");
+ auth_method_list = str_list_make("guest sam winbind ntdomain", NULL);
break;
case SEC_SERVER:
DEBUG(5,("Making default auth method list for security=server\n"));
- auth_method_list = str_list_make("guest sam smbserver");
+ auth_method_list = str_list_make("guest sam smbserver", NULL);
break;
case SEC_USER:
if (lp_encrypted_passwords()) {
DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n"));
- auth_method_list = str_list_make("guest sam");
+ auth_method_list = str_list_make("guest sam", NULL);
} else {
DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n"));
- auth_method_list = str_list_make("guest unix");
+ auth_method_list = str_list_make("guest unix", NULL);
}
break;
case SEC_SHARE:
if (lp_encrypted_passwords()) {
DEBUG(5,("Making default auth method list for security=share, encrypt passwords = yes\n"));
- auth_method_list = str_list_make("guest sam");
+ auth_method_list = str_list_make("guest sam", NULL);
} else {
DEBUG(5,("Making default auth method list for security=share, encrypt passwords = no\n"));
- auth_method_list = str_list_make("guest unix");
+ auth_method_list = str_list_make("guest unix", NULL);
}
break;
case SEC_ADS:
DEBUG(5,("Making default auth method list for security=ADS\n"));
- auth_method_list = str_list_make("guest sam ads ntdomain");
+ auth_method_list = str_list_make("guest sam ads winbind ntdomain", NULL);
break;
default:
DEBUG(5,("Unknown auth method!\n"));
diff --git a/source/auth/auth_domain.c b/source/auth/auth_domain.c
index 3352c5f9c89..d48cec5b293 100644
--- a/source/auth/auth_domain.c
+++ b/source/auth/auth_domain.c
@@ -29,6 +29,88 @@ BOOL global_machine_password_needs_changing = False;
extern pstring global_myname;
extern userdom_struct current_user_info;
+
+/*
+ resolve the name of a DC in ways appropriate for an ADS domain mode
+ an ADS domain may not have Netbios enabled at all, so this is
+ quite different from the RPC case
+ Note that we ignore the 'server' parameter here. That has the effect of using
+ the 'ADS server' smb.conf parameter, which is what we really want anyway
+ */
+static NTSTATUS ads_resolve_dc(fstring remote_machine,
+ struct in_addr *dest_ip)
+{
+ ADS_STRUCT *ads;
+ ads = ads_init_simple();
+ if (!ads) {
+ return NT_STATUS_NO_LOGON_SERVERS;
+ }
+
+ DEBUG(4,("ads_resolve_dc: realm=%s\n", ads->config.realm));
+
+ ads->auth.no_bind = 1;
+
+#ifdef HAVE_ADS
+ /* a full ads_connect() is actually overkill, as we don't srictly need
+ to do the SASL auth in order to get the info we need, but libads
+ doesn't offer a better way right now */
+ ads_connect(ads);
+#endif
+
+ fstrcpy(remote_machine, ads->config.ldap_server_name);
+ strupper(remote_machine);
+ *dest_ip = ads->ldap_ip;
+ ads_destroy(&ads);
+
+ if (!*remote_machine || is_zero_ip(*dest_ip)) {
+ return NT_STATUS_NO_LOGON_SERVERS;
+ }
+
+ DEBUG(4,("ads_resolve_dc: using server='%s' IP=%s\n",
+ remote_machine, inet_ntoa(*dest_ip)));
+
+ return NT_STATUS_OK;
+}
+
+/*
+ resolve the name of a DC in ways appropriate for RPC domain mode
+ this relies on the server supporting netbios and port 137 not being
+ firewalled
+ */
+static NTSTATUS rpc_resolve_dc(const char *server,
+ fstring remote_machine,
+ struct in_addr *dest_ip)
+{
+ if (is_ipaddress(server)) {
+ struct in_addr to_ip = *interpret_addr2(server);
+
+ /* we need to know the machines netbios name - this is a lousy
+ way to find it, but until we have a RPC call that does this
+ it will have to do */
+ if (!name_status_find("*", 0x20, 0x20, to_ip, remote_machine)) {
+ DEBUG(2, ("connect_to_domain_password_server: Can't "
+ "resolve name for IP %s\n", server));
+ return NT_STATUS_NO_LOGON_SERVERS;
+ }
+
+ *dest_ip = to_ip;
+ return NT_STATUS_OK;
+ }
+
+ fstrcpy(remote_machine, server);
+ strupper(remote_machine);
+ if (!resolve_name(remote_machine, dest_ip, 0x20)) {
+ DEBUG(1,("connect_to_domain_password_server: Can't resolve address for %s\n",
+ remote_machine));
+ return NT_STATUS_NO_LOGON_SERVERS;
+ }
+
+ DEBUG(4,("rpc_resolve_dc: using server='%s' IP=%s\n",
+ remote_machine, inet_ntoa(*dest_ip)));
+
+ return NT_STATUS_OK;
+}
+
/**
* Connect to a remote server for domain security authenticaion.
*
@@ -50,37 +132,22 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
fstring remote_machine;
NTSTATUS result;
- if (is_ipaddress(server)) {
- struct in_addr to_ip;
-
- /* we shouldn't have 255.255.255.255 forthe IP address of
- a password server anyways */
- if ((to_ip.s_addr=inet_addr(server)) == 0xFFFFFFFF) {
- DEBUG (0,("connect_to_domain_password_server: inet_addr(%s) returned 0xFFFFFFFF!\n", server));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!name_status_find("*", 0x20, 0x20, to_ip, remote_machine)) {
- DEBUG(0, ("connect_to_domain_password_server: Can't "
- "resolve name for IP %s\n", server));
- return NT_STATUS_UNSUCCESSFUL;
- }
+ if (lp_security() == SEC_ADS) {
+ result = ads_resolve_dc(remote_machine, &dest_ip);
} else {
- fstrcpy(remote_machine, server);
+ result = rpc_resolve_dc(server, remote_machine, &dest_ip);
}
- standard_sub_basic(current_user_info.smb_name, remote_machine, sizeof(remote_machine));
- strupper(remote_machine);
-
- if(!resolve_name( remote_machine, &dest_ip, 0x20)) {
- DEBUG(1,("connect_to_domain_password_server: Can't resolve address for %s\n", remote_machine));
- return NT_STATUS_UNSUCCESSFUL;
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(2,("connect_to_domain_password_server: unable to resolve DC: %s\n",
+ nt_errstr(result)));
+ return result;
}
-
+
if (ismyip(dest_ip)) {
DEBUG(1,("connect_to_domain_password_server: Password server loop - not using password server %s\n",
remote_machine));
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_NO_LOGON_SERVERS;
}
/* TODO: Send a SAMLOGON request to determine whether this is a valid
@@ -98,11 +165,11 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
*/
if (!grab_server_mutex(server))
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_NO_LOGON_SERVERS;
/* Attempt connection */
- result = cli_full_connection(cli, global_myname, server,
- &dest_ip, 0, "IPC$", "IPC", "", "", "", 0);
+ result = cli_full_connection(cli, global_myname, remote_machine,
+ &dest_ip, 0, "IPC$", "IPC", "", "", "",0);
if (!NT_STATUS_IS_OK(result)) {
release_server_mutex();
@@ -129,7 +196,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli)));
cli_ulogoff(*cli);
cli_shutdown(*cli);
release_server_mutex();
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_NO_LOGON_SERVERS;
}
snprintf((*cli)->mach_acct, sizeof((*cli)->mach_acct) - 1, "%s$", setup_creds_as);
@@ -139,7 +206,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli)));
return NT_STATUS_NO_MEMORY;
}
- result = new_cli_nt_setup_creds(*cli, sec_chan, trust_passwd);
+ result = cli_nt_setup_creds(*cli, sec_chan, trust_passwd);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \
@@ -174,10 +241,10 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli,
*/
if (is_zero_ip(*ip))
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_NO_LOGON_SERVERS;
if (!lookup_dc_name(global_myname, domain, ip, dc_name))
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_NO_LOGON_SERVERS;
return connect_to_domain_password_server(cli, dc_name, setup_creds_as, sec_chan, trust_passwd);
}
@@ -196,7 +263,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
struct in_addr *ip_list = NULL;
int count = 0;
int i;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS;
time_t time_now = time(NULL);
BOOL use_pdc_only = False;
@@ -212,7 +279,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli,
use_pdc_only = True;
if (!get_dc_list(use_pdc_only, domain, &ip_list, &count))
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_NO_LOGON_SERVERS;
/*
* Firstly try and contact a PDC/BDC who has the same
@@ -288,7 +355,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
fstring remote_machine;
NET_USER_INFO_3 info3;
struct cli_state *cli = NULL;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS;
/*
* At this point, smb_apasswd points to the lanman response to
@@ -300,7 +367,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
while (!NT_STATUS_IS_OK(nt_status) &&
next_token(&server,remote_machine,LIST_SEP,sizeof(remote_machine))) {
- if(strequal(remote_machine, "*")) {
+ if(lp_security() != SEC_ADS && strequal(remote_machine, "*")) {
nt_status = find_connect_pdc(&cli, domain, setup_creds_as, sec_chan, trust_passwd, last_change_time);
} else {
nt_status = connect_to_domain_password_server(&cli, remote_machine, setup_creds_as, sec_chan, trust_passwd);
@@ -503,7 +570,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
#ifdef DEBUG_PASSWORD
DEBUG(100, ("Trust password for domain %s is %s\n", user_info->domain.str, trust_password));
#endif
- E_md4hash((uchar *)trust_password, trust_md4_password);
+ E_md4hash(trust_password, trust_md4_password);
SAFE_FREE(trust_password);
#if 0
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index 76579150ce9..155370546a5 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -107,7 +107,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response,
memcpy(client_response, ntv2_response.data, sizeof(client_response));
ntv2_owf_gen(part_passwd, user, domain, kr);
- SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, (char *)value_from_encryption);
+ SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, value_from_encryption);
if (user_sess_key != NULL)
{
SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key);
@@ -232,11 +232,26 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
{
return NT_STATUS_OK;
} else {
+ if (lp_ntlm_auth()) {
+ /* Apparently NT accepts NT responses in the LM feild
+ - I think this is related to Win9X pass-though authenticaion
+ */
+ DEBUG(4,("sam_password_ok: Checking NT MD4 password in LM feild\n"));
+ if (smb_pwd_check_ntlmv1(user_info->lm_resp,
+ nt_pw, auth_context->challenge,
+ user_sess_key))
+ {
+ return NT_STATUS_OK;
+ } else {
+ DEBUG(3,("sam_password_ok: NT MD4 password in LM feild failed for user %s\n",pdb_get_username(sampass)));
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+ }
DEBUG(4,("sam_password_ok: LM password check failed for user %s\n",pdb_get_username(sampass)));
return NT_STATUS_WRONG_PASSWORD;
}
}
-
+
/* Should not be reached, but if they send nothing... */
DEBUG(3,("sam_password_ok: NEITHER LanMan nor NT password supplied for user %s\n",pdb_get_username(sampass)));
return NT_STATUS_WRONG_PASSWORD;
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 3ade220c0f0..f914d918715 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -25,7 +25,6 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
-extern fstring remote_machine;
extern pstring global_myname;
/****************************************************************************
@@ -394,7 +393,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
ret = make_user_info_map(user_info, smb_name,
client_domain,
- remote_machine,
+ get_remote_machine_name(),
local_lm_blob,
local_nt_blob,
plaintext_password,
@@ -429,7 +428,7 @@ BOOL make_user_info_for_reply_enc(auth_usersupplied_info **user_info,
return make_user_info_map(user_info, smb_name,
client_domain,
- remote_machine,
+ get_remote_machine_name(),
lm_resp,
nt_resp,
no_plaintext_blob,
diff --git a/source/auth/auth_winbind.c b/source/auth/auth_winbind.c
index 671e198bf59..5bdccd39f3e 100644
--- a/source/auth/auth_winbind.c
+++ b/source/auth/auth_winbind.c
@@ -32,6 +32,30 @@ NSS_STATUS winbindd_request(int req_type,
struct winbindd_request *request,
struct winbindd_response *response);
+NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, NET_USER_INFO_3 *info3)
+{
+ uint8 *info3_ndr;
+ size_t len = response->length - sizeof(response);
+ prs_struct ps;
+ if (len > 0) {
+ info3_ndr = response->extra_data;
+ if (!prs_init(&ps, len, mem_ctx, UNMARSHALL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ prs_append_data(&ps, info3_ndr, len);
+ ps.data_offset = 0;
+ if (!net_io_user_info3("", info3, &ps, 1, 3)) {
+ DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ prs_mem_free(&ps);
+
+ return NT_STATUS_OK;
+ } else {
+ DEBUG(2, ("get_info3_from_ndr: No info3 struct found!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+}
/* Authenticate a user with a challenge/response */
@@ -44,11 +68,11 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
struct winbindd_request request;
struct winbindd_response response;
NSS_STATUS result;
- struct passwd *pw;
NTSTATUS nt_status;
+ NET_USER_INFO_3 info3;
if (!user_info) {
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_INVALID_PARAMETER;
}
if (!auth_context) {
@@ -62,11 +86,14 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- snprintf(request.data.auth_crap.user, sizeof(request.data.auth_crap.user),
- "%s\\%s", user_info->domain.str, user_info->smb_name.str);
+ request.data.auth_crap.flags = WINBIND_PAM_INFO3_NDR;
- fstrcpy(request.data.auth_crap.user, user_info->smb_name.str);
- fstrcpy(request.data.auth_crap.domain, user_info->domain.str);
+ push_utf8_fstring(request.data.auth_crap.user,
+ user_info->smb_name.str);
+ push_utf8_fstring(request.data.auth_crap.domain,
+ user_info->domain.str);
+ push_utf8_fstring(request.data.auth_crap.workstation,
+ user_info->wksta_name.str);
memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal));
@@ -76,27 +103,28 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
sizeof(request.data.auth_crap.nt_resp));
memcpy(request.data.auth_crap.lm_resp, user_info->lm_resp.data,
- sizeof(request.data.auth_crap.lm_resp_len));
- memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data,
request.data.auth_crap.lm_resp_len);
+ memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data,
+ request.data.auth_crap.nt_resp_len);
result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response);
- if (result == NSS_STATUS_SUCCESS) {
-
- pw = Get_Pwnam(user_info->internal_username.str);
-
- if (pw) {
- if (make_server_info_pw(server_info, pw)) {
- nt_status = NT_STATUS_OK;
- } else {
- nt_status = NT_STATUS_NO_MEMORY;
+ nt_status = NT_STATUS(response.data.auth.nt_status);
+
+ if (result == NSS_STATUS_SUCCESS && response.extra_data) {
+ if (NT_STATUS_IS_OK(nt_status)) {
+ if (NT_STATUS_IS_OK(nt_status = get_info3_from_ndr(mem_ctx, &response, &info3))) {
+ nt_status =
+ make_server_info_info3(mem_ctx,
+ user_info->internal_username.str,
+ user_info->smb_name.str,
+ user_info->domain.str,
+ server_info,
+ &info3);
}
- } else {
- nt_status = NT_STATUS_NO_SUCH_USER;
}
- } else {
- nt_status = NT_STATUS_LOGON_FAILURE;
+ } else if (NT_STATUS_IS_OK(nt_status)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
}
return nt_status;
diff --git a/source/client/clitar.c b/source/client/clitar.c
index 43b0ef44bc7..c453cfbb548 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -492,7 +492,7 @@ static int strslashcmp(char *s1, char *s2)
if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0;
/* check for s1 is an "initial" string of s2 */
- if (*s2 == '/' || *s2 == '\\') return 0;
+ if ((*s2 == '/' || *s2 == '\\') && !*s1) return 0;
return *s1-*s2;
}
diff --git a/source/client/smbmount.c b/source/client/smbmount.c
index ad050063ec4..0db990e8bd6 100644
--- a/source/client/smbmount.c
+++ b/source/client/smbmount.c
@@ -29,7 +29,6 @@
extern BOOL in_client;
extern pstring user_socket_options;
extern BOOL append_log;
-extern fstring remote_machine;
static pstring credentials;
static pstring my_netbios_name;
@@ -377,7 +376,7 @@ static void send_fs_socket(char *the_service, char *mount_point, struct cli_stat
}
/* here we are no longer interactive */
- pstrcpy(remote_machine, "smbmount"); /* sneaky ... */
+ set_remote_machine_name("smbmount"); /* sneaky ... */
setup_logging("mount.smbfs", False);
append_log = True;
reopen_logs();
diff --git a/source/client/smbspool.c b/source/client/smbspool.c
index b78d9d22a80..ecb5c311c54 100644
--- a/source/client/smbspool.c
+++ b/source/client/smbspool.c
@@ -282,20 +282,17 @@ smb_connect(char *workgroup, /* I - Workgroup */
get_myname(myname);
nt_status = cli_full_connection(&c, myname, server, NULL, 0, share, "?????",
- username, lp_workgroup(), password, 0);
+ username, workgroup, password, 0);
- if (NT_STATUS_IS_OK(nt_status)) {
- return c;
- } else {
+ if (!NT_STATUS_IS_OK(nt_status)) {
fprintf(stderr, "ERROR: Connection failed with error %s\n", nt_errstr(nt_status));
return NULL;
}
-
- /*
- * Return the new connection...
- */
-
+ /*
+ * Return the new connection...
+ */
+
return (c);
}
diff --git a/source/configure b/source/configure
index be0e78133a7..06694c8e64a 100755
--- a/source/configure
+++ b/source/configure
@@ -5932,7 +5932,7 @@ else
fi
done
-for ac_func in syslog vsyslog
+for ac_func in syslog vsyslog getgrouplist
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5939: checking for $ac_func" >&5
@@ -13763,6 +13763,10 @@ WINBIND_PAM_PROGS=""
if test x"$HAVE_WINBIND" = x"yes"; then
echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define WITH_WINBIND 1
+EOF
+
WINBIND_TARGETS="bin/wbinfo"
WINBIND_STARGETS="bin/winbindd"
@@ -13777,58 +13781,6 @@ else
fi
-# Check for FreeBSD problem with getgroups
-# It returns EGID too many times in the list of groups
-# and causes a security problem
-echo $ac_n "checking whether or not getgroups returns EGID too many times""... $ac_c" 1>&6
-echo "configure:13785: checking whether or not getgroups returns EGID too many times" >&5
-if eval "test \"`echo '$''{'samba_cv_have_getgroups_too_many_egids'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- samba_cv_have_getgroups_too_many_egids=cross
-else
- cat > conftest.$ac_ext <<EOF
-#line 13793 "configure"
-#include "confdefs.h"
-
-#include <sys/types.h>
-#include <stdio.h>
-
-int main(int argc, char *argv[])
-{
- gid_t groups[10];
- int n = 10;
-
- n = getgroups(n, &groups);
- /* Could actually pass back the number of EGIDs there ... */
- exit((n > 1 && groups[0] == getegid() && groups[1] == getegid()) ? 1 : 0);
-}
-EOF
-if { (eval echo configure:13809: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- samba_cv_have_getgroups_too_many_egids=no
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- samba_cv_have_getgroups_too_many_egids=yes
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$samba_cv_have_getgroups_too_many_egids" 1>&6
-if test x"$samba_cv_have_getgroups_too_many_egids" = x"yes"; then
- cat >> confdefs.h <<\EOF
-#define HAVE_GETGROUPS_TOO_MANY_EGIDS 1
-EOF
-
-fi
-
-
-
# Substitution time!
@@ -13848,20 +13800,20 @@ fi
# [#include <pwd.h>])
echo $ac_n "checking whether struct passwd has pw_comment""... $ac_c" 1>&6
-echo "configure:13852: checking whether struct passwd has pw_comment" >&5
+echo "configure:13804: checking whether struct passwd has pw_comment" >&5
if eval "test \"`echo '$''{'samba_cv_passwd_pw_comment'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 13858 "configure"
+#line 13810 "configure"
#include "confdefs.h"
#include <pwd.h>
int main() {
struct passwd p; p.pw_comment;
; return 0; }
EOF
-if { (eval echo configure:13865: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:13817: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
samba_cv_passwd_pw_comment=yes
else
@@ -13886,20 +13838,20 @@ fi
# [#include <pwd.h>])
echo $ac_n "checking whether struct passwd has pw_age""... $ac_c" 1>&6
-echo "configure:13890: checking whether struct passwd has pw_age" >&5
+echo "configure:13842: checking whether struct passwd has pw_age" >&5
if eval "test \"`echo '$''{'samba_cv_passwd_pw_age'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 13896 "configure"
+#line 13848 "configure"
#include "confdefs.h"
#include <pwd.h>
int main() {
struct passwd p; p.pw_age;
; return 0; }
EOF
-if { (eval echo configure:13903: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:13855: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
samba_cv_passwd_pw_age=yes
else
@@ -13938,7 +13890,7 @@ fi
if test x"$INCLUDED_POPT" != x"yes"; then
echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6
-echo "configure:13942: checking for poptGetContext in -lpopt" >&5
+echo "configure:13894: checking for poptGetContext in -lpopt" >&5
ac_lib_var=`echo popt'_'poptGetContext | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -13946,7 +13898,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lpopt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 13950 "configure"
+#line 13902 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -13957,7 +13909,7 @@ int main() {
poptGetContext()
; return 0; }
EOF
-if { (eval echo configure:13961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -13981,9 +13933,9 @@ fi
fi
echo $ac_n "checking whether to use included popt""... $ac_c" 1>&6
-echo "configure:13985: checking whether to use included popt" >&5
+echo "configure:13937: checking whether to use included popt" >&5
if test x"$INCLUDED_POPT" = x"yes"; then
- echo "$ac_t""$srcdir/popt" 1>&6
+ echo "$ac_t""yes" 1>&6
BUILD_POPT='$(POPT_OBJS)'
FLAGS1="-I$srcdir/popt"
else
@@ -14004,16 +13956,16 @@ fi
# final configure stuff
echo $ac_n "checking configure summary""... $ac_c" 1>&6
-echo "configure:14008: checking configure summary" >&5
+echo "configure:13960: checking configure summary" >&5
if test "$cross_compiling" = yes; then
echo "configure: warning: cannot run when cross-compiling" 1>&2
else
cat > conftest.$ac_ext <<EOF
-#line 14013 "configure"
+#line 13965 "configure"
#include "confdefs.h"
#include "${srcdir-.}/tests/summary.c"
EOF
-if { (eval echo configure:14017: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13969: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
echo "$ac_t""yes" 1>&6
else
@@ -14130,7 +14082,7 @@ done
ac_given_srcdir=$srcdir
ac_given_INSTALL="$INSTALL"
-trap 'rm -fr `echo "include/stamp-h Makefile script/findsmb include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+trap 'rm -fr `echo "include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/VFS/block/Makefile include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
@@ -14264,7 +14216,7 @@ EOF
cat >> $CONFIG_STATUS <<EOF
-CONFIG_FILES=\${CONFIG_FILES-"include/stamp-h Makefile script/findsmb"}
+CONFIG_FILES=\${CONFIG_FILES-"include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/VFS/block/Makefile"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
diff --git a/source/configure.in b/source/configure.in
index 915c91e5850..db34c266c58 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -746,7 +746,7 @@ AC_CHECK_FUNCS(setpriv setgidx setuidx setgroups sysconf mktime rename ftruncate
AC_CHECK_FUNCS(lstat64 fopen64 atexit grantpt dup2 lseek64 ftruncate64 readdir64)
AC_CHECK_FUNCS(fseek64 fseeko64 ftell64 ftello64 setluid getpwanam setlinebuf)
AC_CHECK_FUNCS(srandom random srand rand setenv usleep strcasecmp fcvt fcvtl symlink readlink)
-AC_CHECK_FUNCS(syslog vsyslog)
+AC_CHECK_FUNCS(syslog vsyslog getgrouplist)
# setbuffer is needed for smbtorture
AC_CHECK_FUNCS(setbuffer)
@@ -2695,6 +2695,7 @@ WINBIND_PAM_PROGS=""
if test x"$HAVE_WINBIND" = x"yes"; then
AC_MSG_RESULT(yes)
+ AC_DEFINE(WITH_WINBIND)
WINBIND_TARGETS="bin/wbinfo"
WINBIND_STARGETS="bin/winbindd"
@@ -2709,30 +2710,6 @@ else
fi
-# Check for FreeBSD problem with getgroups
-# It returns EGID too many times in the list of groups
-# and causes a security problem
-AC_CACHE_CHECK([whether or not getgroups returns EGID too many times],
- samba_cv_have_getgroups_too_many_egids,[AC_TRY_RUN([
-#include <sys/types.h>
-#include <stdio.h>
-
-int main(int argc, char *argv[])
-{
- gid_t groups[10];
- int n = 10;
-
- n = getgroups(n, &groups);
- /* Could actually pass back the number of EGIDs there ... */
- exit((n > 1 && groups[0] == getegid() && groups[1] == getegid()) ? 1 : 0);
-}],
- samba_cv_have_getgroups_too_many_egids=no,samba_cv_have_getgroups_too_many_egids=yes, samba_cv_have_getgroups_too_many_egids=cross)])
-if test x"$samba_cv_have_getgroups_too_many_egids" = x"yes"; then
- AC_DEFINE(HAVE_GETGROUPS_TOO_MANY_EGIDS)
-fi
-
-
-
# Substitution time!
AC_SUBST(WINBIND_TARGETS)
@@ -2791,7 +2768,7 @@ fi
AC_MSG_CHECKING(whether to use included popt)
if test x"$INCLUDED_POPT" = x"yes"; then
- AC_MSG_RESULT($srcdir/popt)
+ AC_MSG_RESULT(yes)
BUILD_POPT='$(POPT_OBJS)'
FLAGS1="-I$srcdir/popt"
else
@@ -2820,7 +2797,7 @@ AC_TRY_RUN([#include "${srcdir-.}/tests/summary.c"],
builddir=`pwd`
AC_SUBST(builddir)
-AC_OUTPUT(include/stamp-h Makefile script/findsmb)
+AC_OUTPUT(include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/VFS/block/Makefile)
#################################################
# Print very concise instructions on building/use
diff --git a/source/include/ads.h b/source/include/ads.h
index b3e18f18b8d..7504a369b4b 100644
--- a/source/include/ads.h
+++ b/source/include/ads.h
@@ -5,18 +5,34 @@
*/
typedef struct {
- void *ld;
- char *realm;
- char *workgroup;
- char *ldap_server;
- char *ldap_server_name;
- char *kdc_server;
+ void *ld; /* the active ldap structure */
+ struct in_addr ldap_ip; /* the ip of the active connection, if any */
+ time_t last_attempt; /* last attempt to reconnect */
int ldap_port;
- char *bind_path;
- time_t last_attempt;
- char *password;
- char *user_name;
- char *server_realm;
+
+ /* info needed to find the server */
+ struct {
+ char *realm;
+ char *workgroup;
+ char *ldap_server;
+ int foreign; /* set to 1 if connecting to a foreign realm */
+ } server;
+
+ /* info needed to authenticate */
+ struct {
+ char *realm;
+ char *password;
+ char *user_name;
+ char *kdc_server;
+ int no_bind;
+ } auth;
+
+ /* info derived from the servers config */
+ struct {
+ char *realm;
+ char *bind_path;
+ char *ldap_server_name;
+ } config;
} ADS_STRUCT;
typedef struct {
@@ -94,7 +110,7 @@ typedef void **ADS_MODLIST;
/* macros to simplify error returning */
#define ADS_ERROR(rc) ads_build_error(ADS_ERROR_LDAP, rc, 0)
-#define ADS_ERROR_SYSTEM(rc) ads_build_error(ADS_ERROR_SYSTEM, rc, 0)
+#define ADS_ERROR_SYSTEM(rc) ads_build_error(ADS_ERROR_SYSTEM, rc?rc:EINVAL, 0)
#define ADS_ERROR_KRB5(rc) ads_build_error(ADS_ERROR_KRB5, rc, 0)
#define ADS_ERROR_GSS(rc, minor) ads_build_error(ADS_ERROR_GSS, rc, minor)
@@ -129,3 +145,25 @@ typedef void **ADS_MODLIST;
/* account types */
#define ATYPE_GROUP 0x10000000
#define ATYPE_USER 0x30000000
+
+/* Mailslot or cldap getdcname response flags */
+#define ADS_PDC 0x00000001 /* DC is PDC */
+#define ADS_GC 0x00000004 /* DC is a GC of forest */
+#define ADS_LDAP 0x00000008 /* DC is an LDAP server */
+#define ADS_DS 0x00000010 /* DC supports DS */
+#define ADS_KDC 0x00000020 /* DC is running KDC */
+#define ADS_TIMESERV 0x00000040 /* DC is running time services */
+#define ADS_CLOSEST 0x00000080 /* DC is closest to client */
+#define ADS_WRITABLE 0x00000100 /* DC has writable DS */
+#define ADS_GOOD_TIMESERV 0x00000200 /* DC has hardware clock
+ (and running time) */
+#define ADS_NDNC 0x00000400 /* DomainName is non-domain NC serviced
+ by LDAP server */
+#define ADS_PINGS 0x0000FFFF /* Ping response */
+#define ADS_DNS_CONTROLLER 0x20000000 /* DomainControllerName is a DNS name*/
+#define ADS_DNS_DOMAIN 0x40000000 /* DomainName is a DNS name */
+#define ADS_DNS_FOREST 0x80000000 /* DnsForestName is a DNS name */
+
+/* DomainCntrollerAddressType */
+#define ADS_INET_ADDRESS 0x00000001
+#define ADS_NETBIOS_ADDRESS 0x00000002
diff --git a/source/include/config.h.in b/source/include/config.h.in
index ac28c0856cf..4a138b6db6a 100644
--- a/source/include/config.h.in
+++ b/source/include/config.h.in
@@ -285,6 +285,8 @@
#undef _GNU_SOURCE
#endif
+#undef LDAP_SET_REBIND_PROC_ARGS
+
/* The number of bytes in a int. */
#undef SIZEOF_INT
@@ -615,6 +617,9 @@
/* Define if you have the getgrnam function. */
#undef HAVE_GETGRNAM
+/* Define if you have the getgrouplist function. */
+#undef HAVE_GETGROUPLIST
+
/* Define if you have the getnetgrent function. */
#undef HAVE_GETNETGRENT
@@ -645,6 +650,9 @@
/* Define if you have the innetgr function. */
#undef HAVE_INNETGR
+/* Define if you have the ldap_set_rebind_proc function. */
+#undef HAVE_LDAP_SET_REBIND_PROC
+
/* Define if you have the link function. */
#undef HAVE_LINK
@@ -873,12 +881,6 @@
/* Define if you have the <ctype.h> header file. */
#undef HAVE_CTYPE_H
-/* Define if you have the <cups/cups.h> header file. */
-#undef HAVE_CUPS_CUPS_H
-
-/* Define if you have the <cups/language.h> header file. */
-#undef HAVE_CUPS_LANGUAGE_H
-
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
@@ -1125,9 +1127,6 @@
/* Define if you have the acl library (-lacl). */
#undef HAVE_LIBACL
-/* Define if you have the cups library (-lcups). */
-#undef HAVE_LIBCUPS
-
/* Define if you have the gen library (-lgen). */
#undef HAVE_LIBGEN
diff --git a/source/include/includes.h b/source/include/includes.h
index 435810a1bab..6084d583ed6 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -707,9 +707,11 @@ extern int errno;
#include "hash.h"
#include "trans2.h"
#include "nterr.h"
+#include "ntioctl.h"
#include "messages.h"
#include "charset.h"
#include "dynconfig.h"
+#include "adt_tree.h"
#include "util_getent.h"
diff --git a/source/include/local.h b/source/include/local.h
index 24f3fa77246..2538715c412 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -187,8 +187,20 @@
than 62*62 for the current code */
#define MAX_SESSION_ID 3000
+/* For the benifit of PAM and the 'session exec' scripts, we fake up a terminal
+ name. This can be in one of two forms: The first for systems not using
+ utmp (and therefore not constrained as to length or the need for a number
+ < 3000 or so) and the second for systems with this 'well behaved terminal
+ like name' constraint.
+*/
+
#ifndef SESSION_TEMPLATE
-#define SESSION_TEMPLATE "smb/%d"
+/* Paramaters are 'pid' and 'vuid' */
+#define SESSION_TEMPLATE "smb/%lu/%d"
+#endif
+
+#ifndef SESSION_UTMP_TEMPLATE
+#define SESSION_UTMP_TEMPLATE "smb/%d"
#endif
/* the maximum age in seconds of a password. Should be a lp_ parameter */
diff --git a/source/include/messages.h b/source/include/messages.h
index 79a08a75462..58e606b40fa 100644
--- a/source/include/messages.h
+++ b/source/include/messages.h
@@ -51,6 +51,7 @@
/* #define MSG_PRINTER_NOTIFY 2001*/ /* Obsolete */
#define MSG_PRINTER_DRVUPGRADE 2002
#define MSG_PRINTER_NOTIFY2 2003
+#define MSG_PRINTERDATA_INIT_RESET 2004
/* smbd messages */
#define MSG_SMB_CONF_UPDATED 3001
diff --git a/source/include/nameserv.h b/source/include/nameserv.h
index fefa243c3fd..14561cf44d1 100644
--- a/source/include/nameserv.h
+++ b/source/include/nameserv.h
@@ -557,6 +557,8 @@ struct packet_struct
#define SAMLOGON 18
#define SAMLOGON_R 19
#define SAMLOGON_UNK_R 21
+#define SAMLOGON_AD_UNK_R 23
+#define SAMLOGON_AD_R 25
/* Ids for netbios packet types. */
diff --git a/source/include/nt_printing.h b/source/include/nt_printing.h
index 57181c66591..5e2b8f7f64a 100644
--- a/source/include/nt_printing.h
+++ b/source/include/nt_printing.h
@@ -174,14 +174,27 @@ typedef struct nt_printer_driver_info_level
NT_PRINTER_DRIVER_INFO_LEVEL_6 *info_6;
} NT_PRINTER_DRIVER_INFO_LEVEL;
-typedef struct nt_printer_param
-{
- fstring value;
- uint32 type;
- uint8 *data;
- int data_len;
- struct nt_printer_param *next;
-} NT_PRINTER_PARAM;
+/* predefined registry key names for printer data */
+
+#define SPOOL_PRINTERDATA_KEY "PrinterDriverData"
+#define SPOOL_DSSPOOLER_KEY "DsSpooler"
+#define SPOOL_DSDRIVER_KEY "DsDriver"
+#define SPOOL_DSUSER_KEY "DsUser"
+#define SPOOL_PNPDATA_KEY "PnPData"
+
+/* container for a single registry key */
+
+typedef struct {
+ char *name;
+ REGVAL_CTR values;
+} NT_PRINTER_KEY;
+
+/* container for all printer data */
+
+typedef struct {
+ int num_keys;
+ NT_PRINTER_KEY *keys;
+} NT_PRINTER_DATA;
typedef struct ntdevicemode
{
@@ -246,9 +259,8 @@ typedef struct nt_printer_info_level_2
fstring printprocessor;
fstring datatype;
fstring parameters;
- NT_PRINTER_PARAM *specific;
+ NT_PRINTER_DATA data;
SEC_DESC_BUF *secdesc_buf;
- /* not used but ... and how ??? */
uint32 changeid;
uint32 c_setprinter;
uint32 setuptime;
diff --git a/source/include/passdb.h b/source/include/passdb.h
index a79c8a0289f..7a791ddac4f 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -57,7 +57,7 @@ typedef struct pdb_context
BOOL (*pdb_getsampwnam)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const char *username);
- BOOL (*pdb_getsampwsid)(struct pdb_context *, SAM_ACCOUNT *sam_acct, DOM_SID *sid);
+ BOOL (*pdb_getsampwsid)(struct pdb_context *, SAM_ACCOUNT *sam_acct, const DOM_SID *sid);
BOOL (*pdb_add_sam_account)(struct pdb_context *, SAM_ACCOUNT *sampass);
@@ -88,7 +88,7 @@ typedef struct pdb_methods
BOOL (*getsampwnam)(struct pdb_methods *, SAM_ACCOUNT *sam_acct, const char *username);
- BOOL (*getsampwsid)(struct pdb_methods *, SAM_ACCOUNT *sam_acct, DOM_SID *Sid);
+ BOOL (*getsampwsid)(struct pdb_methods *, SAM_ACCOUNT *sam_acct, const DOM_SID *Sid);
BOOL (*add_sam_account)(struct pdb_methods *, SAM_ACCOUNT *sampass);
diff --git a/source/include/rpc_lsa.h b/source/include/rpc_lsa.h
index 8e42ac7d2cb..39f3e47dc85 100644
--- a/source/include/rpc_lsa.h
+++ b/source/include/rpc_lsa.h
@@ -73,6 +73,7 @@
#define LSA_RETRPRIVDATA 0x2b
#define LSA_OPENPOLICY2 0x2c
#define LSA_UNK_GET_CONNUSER 0x2d /* LsaGetConnectedCredentials ? */
+#define LSA_QUERYINFO2 0x2e
/* XXXX these are here to get a compile! */
#define LSA_LOOKUPRIDS 0xFD
@@ -261,6 +262,43 @@ typedef struct lsa_r_query_info
} LSA_R_QUERY_INFO;
+/* LSA_DNS_DOM_INFO - DNS domain info - info class 12*/
+typedef struct lsa_dns_dom_info
+{
+ UNIHDR hdr_nb_dom_name; /* netbios domain name */
+ UNIHDR hdr_dns_dom_name;
+ UNIHDR hdr_forest_name;
+
+ GUID dom_guid; /* domain GUID */
+
+ UNISTR2 uni_nb_dom_name;
+ UNISTR2 uni_dns_dom_name;
+ UNISTR2 uni_forest_name;
+
+ uint32 ptr_dom_sid;
+ DOM_SID2 dom_sid; /* domain SID */
+} LSA_DNS_DOM_INFO;
+
+typedef union lsa_info2_union
+{
+ LSA_DNS_DOM_INFO dns_dom_info;
+} LSA_INFO2_UNION;
+
+/* LSA_Q_QUERY_INFO2 - LSA query info */
+typedef struct lsa_q_query_info2
+{
+ POLICY_HND pol; /* policy handle */
+ uint16 info_class; /* info class */
+} LSA_Q_QUERY_INFO2;
+
+typedef struct lsa_r_query_info2
+{
+ uint32 ptr; /* pointer to info struct */
+ uint16 info_class;
+ LSA_INFO2_UNION info; /* so far the only one */
+ NTSTATUS status;
+} LSA_R_QUERY_INFO2;
+
/* LSA_Q_ENUM_TRUST_DOM - LSA enumerate trusted domains */
typedef struct lsa_enum_trust_dom_info
{
diff --git a/source/include/rpc_reg.h b/source/include/rpc_reg.h
index 3f3db0f2ba0..92175cf287b 100644
--- a/source/include/rpc_reg.h
+++ b/source/include/rpc_reg.h
@@ -1,9 +1,10 @@
/*
Unix SMB/CIFS implementation.
SMB parameters and setup
- Copyright (C) Andrew Tridgell 1992-1997
- Copyright (C) Luke Kenneth Casson Leighton 1996-1997
- Copyright (C) Paul Ashton 1997
+ Copyright (C) Andrew Tridgell 1992-1997.
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
+ Copyright (C) Paul Ashton 1997.
+ Copyright (C) Gerald Carter 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
@@ -26,35 +27,35 @@
/* winreg pipe defines
NOT IMPLEMENTED !!
-#define REG_OPEN_HKCR 0x00
#define _REG_UNK_01 0x01
#define _REG_UNK_03 0x03
#define REG_CREATE_KEY 0x06
#define REG_DELETE_KEY 0x07
#define REG_DELETE_VALUE 0x08
-#define REG_ENUM_VALUE 0x0a
#define REG_FLUSH_KEY 0x0b
#define REG_GET_KEY_SEC 0x0c
#define _REG_UNK_0D 0x0d
#define _REG_UNK_0E 0x0e
#define _REG_UNK_12 0x12
#define _REG_UNK_13 0x13
-#define _REG_UNK_14 0x14
#define REG_SET_KEY_SEC 0x15
#define REG_CREATE_VALUE 0x16
#define _REG_UNK_17 0x17
*/
/* Implemented */
+#define REG_OPEN_HKCR 0x00
#define REG_OPEN_HKLM 0x02
#define REG_OPEN_HKU 0x04
#define REG_CLOSE 0x05
#define REG_ENUM_KEY 0x09
+#define REG_ENUM_VALUE 0x0a
#define REG_OPEN_ENTRY 0x0f
#define REG_QUERY_KEY 0x10
#define REG_INFO 0x11
#define REG_SHUTDOWN 0x18
#define REG_ABORT_SHUTDOWN 0x19
+#define REG_SAVE_KEY 0x14 /* no idea what the real name is */
#define REG_UNKNOWN_1A 0x1a
@@ -63,6 +64,12 @@
#define HKEY_LOCAL_MACHINE 0x80000002
#define HKEY_USERS 0x80000003
+#define KEY_HKLM "HKLM"
+#define KEY_HKU "HKU"
+#define KEY_HKCR "HKCR"
+#define KEY_PRINTING "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print"
+#define KEY_TREE_ROOT ""
+
/* Registry data types */
#define REG_NONE 0
@@ -82,6 +89,65 @@
#define REG_FORCE_SHUTDOWN 0x001
#define REG_REBOOT_ON_SHUTDOWN 0x100
+/* structure to contain registry values */
+
+typedef struct {
+ fstring valuename;
+ uint16 type;
+ uint32 size; /* in bytes */
+ uint8 *data_p;
+} REGISTRY_VALUE;
+
+/* container for regostry values */
+
+typedef struct {
+ TALLOC_CTX *ctx;
+ uint32 num_values;
+ REGISTRY_VALUE **values;
+} REGVAL_CTR;
+
+/* container for registry subkey names */
+
+typedef struct {
+ TALLOC_CTX *ctx;
+ uint32 num_subkeys;
+ char **subkeys;
+} REGSUBKEY_CTR;
+
+
+/*
+ * container for function pointers to enumeration routines
+ * for vitural registry view
+ */
+
+typedef struct {
+ /* functions for enumerating subkeys and values */
+ int (*subkey_fn)( char *key, REGSUBKEY_CTR *subkeys);
+ int (*value_fn) ( char *key, REGVAL_CTR *val );
+ BOOL (*store_subkeys_fn)( char *key, REGSUBKEY_CTR *subkeys );
+ BOOL (*store_values_fn)( char *key, REGVAL_CTR *val );
+} REGISTRY_OPS;
+
+typedef struct {
+ char *keyname; /* full path to name of key */
+ REGISTRY_OPS *ops; /* registry function hooks */
+} REGISTRY_HOOK;
+
+
+
+/* structure to store the registry handles */
+
+typedef struct _RegistryKey {
+
+ struct _RegistryKey *prev, *next;
+
+ POLICY_HND hnd;
+ pstring name; /* full name of registry key */
+ REGISTRY_HOOK *hook;
+
+} REGISTRY_KEY;
+
+
/* REG_Q_OPEN_HKCR */
typedef struct q_reg_open_hkcr_info
{
@@ -107,7 +173,7 @@ typedef struct q_reg_open_hklm_info
uint32 ptr;
uint16 unknown_0; /* 0xE084 - 16 bit unknown */
uint16 unknown_1; /* random. changes */
- uint32 access_mask; /* 0x0000 0002 - 32 bit unknown */
+ uint32 access_mask;
}
REG_Q_OPEN_HKLM;
@@ -246,6 +312,7 @@ typedef struct q_reg_query_value_info
uint32 ptr2; /* pointer */
uint32 len_value2; /* */
+
} REG_Q_ENUM_VALUE;
/* REG_R_ENUM_VALUE */
@@ -258,7 +325,7 @@ typedef struct r_reg_enum_value_info
uint32 type; /* 1 = UNISTR, 3 = BYTES, 4 = DWORD, 7 = MULTI_UNISTR */
uint32 ptr_value; /* pointer */
- BUFFER2 *buf_value; /* value, in byte buffer */
+ BUFFER2 buf_value; /* value, in byte buffer */
uint32 ptr1; /* pointer */
uint32 len_value1; /* */
@@ -388,6 +455,29 @@ typedef struct r_reg_unk_1a_info
} REG_R_UNKNOWN_1A;
+/* REG_Q_UNKNOWN_1A */
+typedef struct q_reg_unknown_14
+{
+ POLICY_HND pol; /* policy handle */
+
+ UNIHDR hdr_file; /* unicode product type header */
+ UNISTR2 uni_file; /* local filename to save key as from regedt32.exe */
+ /* e.g. "c:\temp\test.dat" */
+
+ uint32 unknown; /* 0x0000 0000 */
+
+} REG_Q_SAVE_KEY;
+
+
+/* REG_R_UNKNOWN_1A */
+typedef struct r_reg_unknown_14
+{
+ NTSTATUS status; /* return status */
+
+} REG_R_SAVE_KEY;
+
+
+
/* REG_Q_CLOSE */
typedef struct reg_q_close_info
{
@@ -481,7 +571,7 @@ typedef struct r_reg_info_info
uint32 type; /* key datatype */
uint32 ptr_uni_val; /* key value pointer */
- BUFFER2 *uni_val; /* key value */
+ BUFFER2 uni_val; /* key value */
uint32 ptr_max_len;
uint32 buf_max_len;
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index 78d5c244a6f..11438ae0676 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -4,7 +4,10 @@
Copyright (C) Andrew Tridgell 1992-2000
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
Copyright (C) Paul Ashton 1997-2000
- Copyright (C) Jean François Micouleau 1998-2001.
+ Copyright (C) Jean François Micouleau 1998-2001
+ Copyright (C) Anthony Liguori 2002
+ Copyright (C) Jim McDonough 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
@@ -24,10 +27,8 @@
#ifndef _RPC_SAMR_H /* _RPC_SAMR_H */
#define _RPC_SAMR_H
-
#include "rpc_misc.h"
-
/*******************************************************************
the following information comes from a QuickView on samsrv.dll,
and gives an idea of exactly what is needed:
@@ -144,6 +145,7 @@ SamrTestPrivateFunctionsUser
#define SAMR_GET_DOM_PWINFO 0x38
#define SAMR_CONNECT 0x39
#define SAMR_SET_USERINFO 0x3A
+#define SAMR_CONNECT4 0x3E
/* Access bits to the SAM-object */
@@ -176,17 +178,17 @@ SamrTestPrivateFunctionsUser
/* Access bits to Domain-objects */
-#define DOMAIN_ACCESS_LOOKUP_INFO_1 0x000000001
-#define DOMAIN_ACCESS_SET_INFO_1 0x000000002
-#define DOMAIN_ACCESS_LOOKUP_INFO_2 0x000000004
-#define DOMAIN_ACCESS_SET_INFO_2 0x000000008
-#define DOMAIN_ACCESS_CREATE_USER 0x000000010
-#define DOMAIN_ACCESS_CREATE_GROUP 0x000000020
-#define DOMAIN_ACCESS_CREATE_ALIAS 0x000000040
-#define DOMAIN_ACCESS_UNKNOWN_80 0x000000080
-#define DOMAIN_ACCESS_ENUM_ACCOUNTS 0x000000100
-#define DOMAIN_ACCESS_OPEN_ACCOUNT 0x000000200
-#define DOMAIN_ACCESS_SET_INFO_3 0x000000400
+#define DOMAIN_ACCESS_LOOKUP_INFO_1 0x00000001
+#define DOMAIN_ACCESS_SET_INFO_1 0x00000002
+#define DOMAIN_ACCESS_LOOKUP_INFO_2 0x00000004
+#define DOMAIN_ACCESS_SET_INFO_2 0x00000008
+#define DOMAIN_ACCESS_CREATE_USER 0x00000010
+#define DOMAIN_ACCESS_CREATE_GROUP 0x00000020
+#define DOMAIN_ACCESS_CREATE_ALIAS 0x00000040
+#define DOMAIN_ACCESS_UNKNOWN_80 0x00000080
+#define DOMAIN_ACCESS_ENUM_ACCOUNTS 0x00000100
+#define DOMAIN_ACCESS_OPEN_ACCOUNT 0x00000200
+#define DOMAIN_ACCESS_SET_INFO_3 0x00000400
#define DOMAIN_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED_ACCESS | \
DOMAIN_ACCESS_SET_INFO_3 | \
@@ -220,17 +222,17 @@ SamrTestPrivateFunctionsUser
/* Access bits to User-objects */
-#define USER_ACCESS_GET_NAME_ETC 0x000000001
-#define USER_ACCESS_GET_LOCALE 0x000000002
-#define USER_ACCESS_SET_LOC_COM 0x000000004
-#define USER_ACCESS_GET_LOGONINFO 0x000000008
-#define USER_ACCESS_UNKNOWN_10 0x000000010
-#define USER_ACCESS_SET_ATTRIBUTES 0x000000020
-#define USER_ACCESS_CHANGE_PASSWORD 0x000000040
-#define USER_ACCESS_SET_PASSWORD 0x000000080
-#define USER_ACCESS_GET_GROUPS 0x000000100
-#define USER_ACCESS_UNKNOWN_200 0x000000200
-#define USER_ACCESS_UNKNOWN_400 0x000000400
+#define USER_ACCESS_GET_NAME_ETC 0x00000001
+#define USER_ACCESS_GET_LOCALE 0x00000002
+#define USER_ACCESS_SET_LOC_COM 0x00000004
+#define USER_ACCESS_GET_LOGONINFO 0x00000008
+#define USER_ACCESS_UNKNOWN_10 0x00000010
+#define USER_ACCESS_SET_ATTRIBUTES 0x00000020
+#define USER_ACCESS_CHANGE_PASSWORD 0x00000040
+#define USER_ACCESS_SET_PASSWORD 0x00000080
+#define USER_ACCESS_GET_GROUPS 0x00000100
+#define USER_ACCESS_UNKNOWN_200 0x00000200
+#define USER_ACCESS_UNKNOWN_400 0x00000400
#define USER_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED_ACCESS | \
USER_ACCESS_UNKNOWN_400 | \
@@ -312,9 +314,6 @@ SamrTestPrivateFunctionsUser
#define ALIAS_EXECUTE ( STANDARD_RIGHTS_EXECUTE_ACCESS | \
ALIAS_ACCESS_LOOKUP_INFO )
-
-
-
typedef struct _DISP_USER_INFO {
SAM_ACCOUNT *sam;
} DISP_USER_INFO;
@@ -1647,7 +1646,7 @@ typedef struct r_samr_create_user_info
{
POLICY_HND user_pol; /* policy handle associated with user */
- uint32 unknown_0; /* 0x0007 03ff */
+ uint32 access_granted;
uint32 user_rid; /* user RID */
NTSTATUS status; /* return status */
@@ -1870,6 +1869,19 @@ typedef struct r_samr_connect_info
} SAMR_R_CONNECT;
+/* SAMR_Q_CONNECT4 */
+typedef struct q_samr_connect4_info
+{
+ uint32 ptr_srv_name; /* pointer to server name */
+ UNISTR2 uni_srv_name;
+
+ uint32 unk_0; /* possible server name type, 1 for IP num, 2 for name */
+ uint32 access_mask;
+} SAMR_Q_CONNECT4;
+
+/* SAMR_R_CONNECT4 - same format as connect */
+typedef struct r_samr_connect_info SAMR_R_CONNECT4;
+
/* SAMR_Q_GET_DOM_PWINFO */
typedef struct q_samr_get_dom_pwinfo
{
@@ -2008,6 +2020,4 @@ typedef struct r_samr_set_domain_info
} SAMR_R_SET_DOMAIN_INFO;
-
#endif /* _RPC_SAMR_H */
-
diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h
index 7ec9a509bf3..b7acf44c5de 100755
--- a/source/include/rpc_spoolss.h
+++ b/source/include/rpc_spoolss.h
@@ -202,6 +202,7 @@
#define NOTIFY_TWO_VALUE 2 /* Notify data is stored in value2 */
#define NOTIFY_POINTER 3 /* Data is a pointer to a buffer */
#define NOTIFY_STRING 4 /* Data is a pointer to a buffer w/length */
+#define NOTIFY_SECDESC 5 /* Data is a security descriptor */
#define PRINTER_NOTIFY_TYPE 0x00
#define JOB_NOTIFY_TYPE 0x01
@@ -801,15 +802,16 @@ typedef struct spool_notify_info_data
uint16 field;
uint32 reserved;
uint32 id;
- union
- {
+ union {
uint32 value[2];
- struct
- {
+ struct {
uint32 length;
uint16 *string;
- }
- data;
+ } data;
+ struct {
+ uint32 size;
+ SEC_DESC *desc;
+ } sd;
}
notify_data;
uint32 size;
diff --git a/source/include/rpc_srvsvc.h b/source/include/rpc_srvsvc.h
index 1753c19783b..94d23bb4bc4 100644
--- a/source/include/rpc_srvsvc.h
+++ b/source/include/rpc_srvsvc.h
@@ -4,6 +4,7 @@
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
+ Copyright (C) Nigel Williams 2001
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
@@ -33,6 +34,7 @@
#define SRV_NET_SHARE_GET_INFO 0x10
#define SRV_NET_SHARE_SET_INFO 0x11
#define SRV_NET_SHARE_DEL 0x12
+#define SRV_NET_SHARE_DEL_STICKY 0x13
#define SRV_NET_SRV_GET_INFO 0x15
#define SRV_NET_SRV_SET_INFO 0x16
#define SRV_NET_DISK_ENUM 0x17
@@ -54,7 +56,7 @@ typedef struct disk_enum_container {
uint32 entries_read;
uint32 unknown;
uint32 disk_info_ptr;
- DISK_INFO disk_info[MAX_SERVER_DISK_ENTRIES];
+ DISK_INFO *disk_info;
} DISK_ENUM_CONTAINER;
typedef struct net_srv_disk_enum {
@@ -294,6 +296,29 @@ typedef struct r_net_conn_enum_info
} SRV_R_NET_CONN_ENUM;
+/* SH_INFO_0 */
+typedef struct ptr_share_info0
+{
+ uint32 ptr_netname; /* pointer to net name. */
+} SH_INFO_0;
+
+/* SH_INFO_0_STR (level 0 share info strings) */
+typedef struct str_share_info0
+{
+ SH_INFO_0 *ptrs;
+
+ UNISTR2 uni_netname; /* unicode string of net name */
+
+} SH_INFO_0_STR;
+
+/* SRV_SHARE_INFO_0 */
+typedef struct share_info_0_info
+{
+ SH_INFO_0 info_0;
+ SH_INFO_0_STR info_0_str;
+
+} SRV_SHARE_INFO_0;
+
/* SH_INFO_1 (pointers to level 1 share info strings) */
typedef struct ptr_share_info1
{
@@ -306,6 +331,8 @@ typedef struct ptr_share_info1
/* SH_INFO_1_STR (level 1 share info strings) */
typedef struct str_share_info1
{
+ SH_INFO_1 *ptrs;
+
UNISTR2 uni_netname; /* unicode string of net name */
UNISTR2 uni_remark; /* unicode string of comment */
@@ -336,6 +363,8 @@ typedef struct ptr_share_info2
/* SH_INFO_2_STR (level 2 share info strings) */
typedef struct str_share_info2
{
+ SH_INFO_2 *ptrs;
+
UNISTR2 uni_netname; /* unicode string of net name (e.g NETLOGON) */
UNISTR2 uni_remark; /* unicode string of comment (e.g "Logon server share") */
UNISTR2 uni_path; /* unicode string of local path (e.g c:\winnt\system32\repl\import\scripts) */
@@ -383,6 +412,8 @@ typedef struct ptr_share_info502
uint32 num_uses; /* current uses */
uint32 ptr_path; /* pointer to path name */
uint32 ptr_passwd; /* pointer to password */
+ uint32 reserved; /* this holds the space taken by the sd in the rpc packet */
+ uint32 reserved_offset; /* required for _post operation when marshalling */
uint32 sd_size; /* size of security descriptor */
uint32 ptr_sd; /* pointer to security descriptor */
@@ -398,6 +429,7 @@ typedef struct str_share_info502
UNISTR2 uni_path; /* unicode string of local path (e.g c:\winnt\system32\repl\import\scripts) */
UNISTR2 uni_passwd; /* unicode string of password - presumably for share level security (e.g NULL) */
+ uint32 reserved;
uint32 sd_size;
SEC_DESC *sd;
@@ -411,12 +443,57 @@ typedef struct share_info_502_info
} SRV_SHARE_INFO_502;
-/* SRV_SHARE_INFO_1005 */
+typedef struct ptr_share_info1004
+{
+ uint32 ptr_remark;
+
+} SH_INFO_1004;
+
+typedef struct str_share_info1004
+{
+ SH_INFO_1004 *ptrs;
+
+ UNISTR2 uni_remark;
+
+} SH_INFO_1004_STR;
+
+typedef struct ptr_info_1004_info
+{
+ SH_INFO_1004 info_1004;
+ SH_INFO_1004_STR info_1004_str;
+} SRV_SHARE_INFO_1004;
+
typedef struct share_info_1005_info
{
uint32 dfs_root_flag;
} SRV_SHARE_INFO_1005;
+typedef struct share_info_1006_info
+{
+ uint32 max_uses;
+} SRV_SHARE_INFO_1006;
+
+typedef struct ptr_share_info1007
+{
+ uint32 flags;
+ uint32 ptr_AlternateDirectoryName;
+
+} SH_INFO_1007;
+
+typedef struct str_share_info1007
+{
+ SH_INFO_1007 *ptrs;
+
+ UNISTR2 uni_AlternateDirectoryName;
+
+} SH_INFO_1007_STR;
+
+typedef struct ptr_info_1007_info
+{
+ SH_INFO_1007 info_1007;
+ SH_INFO_1007_STR info_1007_str;
+} SRV_SHARE_INFO_1007;
+
/* SRV_SHARE_INFO_1501 */
typedef struct share_info_1501_info
{
@@ -435,10 +512,16 @@ typedef struct srv_share_info_ctr_info
uint32 num_entries2;
union {
- SRV_SHARE_INFO_1 *info1; /* share info level 1 */
- SRV_SHARE_INFO_2 *info2; /* share info level 2 */
- SRV_SHARE_INFO_501 *info501; /* share info level 501 */
- SRV_SHARE_INFO_502 *info502; /* share info level 502 */
+ SRV_SHARE_INFO_0 *info0;
+ SRV_SHARE_INFO_1 *info1; /* share info level 1 */
+ SRV_SHARE_INFO_2 *info2; /* share info level 2 */
+ SRV_SHARE_INFO_501 *info501; /* share info level 501 */
+ SRV_SHARE_INFO_502 *info502; /* share info level 502 */
+ SRV_SHARE_INFO_1004 *info1004;
+ SRV_SHARE_INFO_1005 *info1005;
+ SRV_SHARE_INFO_1006 *info1006;
+ SRV_SHARE_INFO_1007 *info1007;
+ SRV_SHARE_INFO_1501 *info1501;
void *info;
} share;
@@ -484,19 +567,21 @@ typedef struct q_net_share_get_info_info
} SRV_Q_NET_SHARE_GET_INFO;
-/* JRA. NB. We also need level 1004 and 1006 here. */
-
/* SRV_SHARE_INFO */
typedef struct srv_share_info {
uint32 switch_value;
uint32 ptr_share_ctr;
union {
+ SRV_SHARE_INFO_0 info0;
SRV_SHARE_INFO_1 info1;
SRV_SHARE_INFO_2 info2;
SRV_SHARE_INFO_501 info501;
SRV_SHARE_INFO_502 info502;
+ SRV_SHARE_INFO_1004 info1004;
SRV_SHARE_INFO_1005 info1005;
+ SRV_SHARE_INFO_1006 info1006;
+ SRV_SHARE_INFO_1007 info1007;
SRV_SHARE_INFO_1501 info1501;
} share;
} SRV_SHARE_INFO;
@@ -520,12 +605,16 @@ typedef struct q_net_share_set_info_info
SRV_SHARE_INFO info;
+ uint32 ptr_parm_error;
+ uint32 parm_error;
+
} SRV_Q_NET_SHARE_SET_INFO;
/* SRV_R_NET_SHARE_SET_INFO */
typedef struct r_net_share_set_info
{
- uint32 switch_value; /* switch value */
+ uint32 ptr_parm_error;
+ uint32 parm_error;
WERROR status; /* return status */
@@ -549,7 +638,9 @@ typedef struct q_net_share_add
/* SRV_R_NET_SHARE_ADD */
typedef struct r_net_share_add
{
- uint32 switch_value; /* switch value */
+
+ uint32 ptr_parm_error;
+ uint32 parm_error;
WERROR status; /* return status */
@@ -594,9 +685,12 @@ typedef struct str_file_info3_info
/* SRV_FILE_INFO_3 */
typedef struct srv_file_info_3
{
+ uint32 num_entries_read; /* EntriesRead */
+ uint32 ptr_file_info; /* Buffer */
+
+ uint32 num_entries_read2; /* EntriesRead */
FILE_INFO_3 info_3; /* file entry details */
FILE_INFO_3_STR info_3_str; /* file entry strings */
-
} SRV_FILE_INFO_3;
/* SRV_FILE_INFO_CTR */
diff --git a/source/include/secrets.h b/source/include/secrets.h
index 8a5a573bcc0..183b29d7a8a 100644
--- a/source/include/secrets.h
+++ b/source/include/secrets.h
@@ -35,6 +35,10 @@
#define SECRETS_DOMAIN_SID "SECRETS/SID"
#define SECRETS_SAM_SID "SAM/SID"
+/* The domain GUID and server GUID (NOT the same) are also not secret */
+#define SECRETS_DOMAIN_GUID "SECRETS/DOMGUID"
+#define SECRETS_SERVER_GUID "SECRETS/GUID"
+
#define SECRETS_LDAP_BIND_PW "SECRETS/LDAP_BIND_PW"
/* Authenticated user info is stored in secrets.tdb under these keys */
diff --git a/source/include/smb.h b/source/include/smb.h
index a67101ff099..263dd67c548 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -38,7 +38,9 @@
#define NMB_PORT 137
#define DGRAM_PORT 138
-#define SMB_PORT 139
+#define SMB_PORT1 445
+#define SMB_PORT2 139
+#define SMB_PORTS "445 139"
#define False (0)
#define True (1)
@@ -383,7 +385,7 @@ typedef struct files_struct
int fnum;
struct connection_struct *conn;
int fd;
- int print_jobid;
+ uint32 print_jobid;
SMB_DEV_T dev;
SMB_INO_T inode;
BOOL delete_on_close;
@@ -444,6 +446,15 @@ typedef struct
#include "smb_acls.h"
#include "vfs.h"
+typedef struct smb_vfs_handle_struct
+{
+ void *data;
+ /* Handle on dlopen() call */
+ void *handle;
+ struct smb_vfs_handle_struct *next, *prev;
+
+} smb_vfs_handle_struct;
+
typedef struct connection_struct
{
struct connection_struct *next, *prev;
@@ -461,9 +472,7 @@ typedef struct connection_struct
char *origpath;
struct vfs_ops vfs_ops; /* Filesystem operations */
- /* Handle on dlopen() call */
- void *dl_handle;
- void *vfs_private;
+ struct smb_vfs_handle_struct *vfs_private;
char *user; /* name of user who *opened* this connection */
uid_t uid; /* uid of user who *opened* this connection */
@@ -1594,8 +1603,8 @@ typedef struct user_struct
uint8 session_key[16];
- int session_id; /* used by utmp and pam session code */
-
+ char *session_keystr; /* used by utmp and pam session code.
+ TDB key string */
int homes_snum;
} user_struct;
@@ -1667,4 +1676,8 @@ typedef struct {
#define DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH 14
+/* Common popt structures */
+
+extern struct poptOption popt_common_debug[];
+
#endif /* _SMB_H */
diff --git a/source/include/version.h b/source/include/version.h
index afc40a8cf90..74df1c99141 100644
--- a/source/include/version.h
+++ b/source/include/version.h
@@ -1 +1 @@
-#define VERSION "3.0-alpha17"
+#define VERSION "3.0-alpha18"
diff --git a/source/include/vfs.h b/source/include/vfs.h
index 2f9fedf77d3..1b1a13d7c12 100644
--- a/source/include/vfs.h
+++ b/source/include/vfs.h
@@ -1,7 +1,8 @@
/*
Unix SMB/CIFS implementation.
VFS structures and parameters
- Copyright (C) Tim Potter 1999
+ Copyright (C) Tim Potter 1999
+ Copyright (C) Alexander Bokovoy 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
@@ -16,6 +17,8 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ This work was sponsored by Optifacio Software Services, Inc.
*/
#ifndef _VFS_H
@@ -40,7 +43,48 @@
/* Changed to version 2 for CIFS UNIX extensions (mknod and link added). JRA. */
/* Changed to version 3 for POSIX acl extensions. JRA. */
-#define SMB_VFS_INTERFACE_VERSION 3
+/* Changed to version 4 for cascaded VFS interface. Alexander Bokovoy. */
+#define SMB_VFS_INTERFACE_VERSION 5
+
+
+/* Version of supported cascaded interface backward copmatibility.
+ (version 4 corresponds to SMB_VFS_INTERFACE_VERSION 4)
+ It is used in vfs_init_custom() to detect VFS modules which conform to cascaded
+ VFS interface but implement elder version than current version of Samba uses.
+ This allows to use old modules with new VFS interface as far as combined VFS operation
+ set is coherent (will be in most cases).
+*/
+#define SMB_VFS_INTERFACE_CASCADED 4
+
+/*
+ Each VFS module must provide following global functions:
+ vfs_init -- initialization function
+ vfs_done -- finalization function
+
+ vfs_init must return proper initialized vfs_op_tuple[] array
+ which describes all operations this module claims to intercept. This function
+ is called whenever module is loaded into smbd process using sys_dlopen().
+
+ vfs_init must store somewhere vfs_handle reference if module wants to store per-instance
+ private information for further usage. vfs_handle->data should be used to
+ store such information. Do not try to change other fields in this structure
+ or results likely to be unpredictable.
+
+ vfs_done must perform finalization of the module. In particular,
+ this function must free vfs_ops structure returned to module from smb_vfs_get_opaque_ops()
+ function if it is used (see below). This function is called whenever module
+ is unloaded from smbd process using sys_dlclose().
+
+ Prototypes:
+ vfs_op_tuple *vfs_init(int *vfs_version, const struct vfs_ops *def_vfs_ops,
+ struct smb_vfs_handle_struct *vfs_handle);
+ void vfs_done(connection_struct *conn);
+
+ All intercepted VFS operations must be declared as static functions inside module source
+ in order to keep smbd namespace unpolluted. See source of skel, audit, and recycle bin
+ example VFS modules for more details.
+
+*/
/* VFS operations structure */
@@ -135,4 +179,157 @@ struct vfs_options {
char *value;
};
+/*
+ Available VFS operations. These values must be in sync with vfs_ops struct.
+ In particular, if new operations are added to vfs_ops, appropriate constants
+ should be added to vfs_op_type so that order of them kept same as in vfs_ops.
+*/
+
+typedef enum _vfs_op_type {
+
+ SMB_VFS_OP_NOOP = -1,
+
+ /* Disk operations */
+
+ SMB_VFS_OP_CONNECT = 0,
+ SMB_VFS_OP_DISCONNECT,
+ SMB_VFS_OP_DISK_FREE,
+
+ /* Directory operations */
+
+ SMB_VFS_OP_OPENDIR,
+ SMB_VFS_OP_READDIR,
+ SMB_VFS_OP_MKDIR,
+ SMB_VFS_OP_RMDIR,
+ SMB_VFS_OP_CLOSEDIR,
+
+ /* File operations */
+
+ SMB_VFS_OP_OPEN,
+ SMB_VFS_OP_CLOSE,
+ SMB_VFS_OP_READ,
+ SMB_VFS_OP_WRITE,
+ SMB_VFS_OP_LSEEK,
+ SMB_VFS_OP_RENAME,
+ SMB_VFS_OP_FSYNC,
+ SMB_VFS_OP_STAT,
+ SMB_VFS_OP_FSTAT,
+ SMB_VFS_OP_LSTAT,
+ SMB_VFS_OP_UNLINK,
+ SMB_VFS_OP_CHMOD,
+ SMB_VFS_OP_FCHMOD,
+ SMB_VFS_OP_CHOWN,
+ SMB_VFS_OP_FCHOWN,
+ SMB_VFS_OP_CHDIR,
+ SMB_VFS_OP_GETWD,
+ SMB_VFS_OP_UTIME,
+ SMB_VFS_OP_FTRUNCATE,
+ SMB_VFS_OP_LOCK,
+ SMB_VFS_OP_SYMLINK,
+ SMB_VFS_OP_READLINK,
+ SMB_VFS_OP_LINK,
+ SMB_VFS_OP_MKNOD,
+ SMB_VFS_OP_REALPATH,
+
+ /* NT ACL operations. */
+
+ SMB_VFS_OP_FGET_NT_ACL,
+ SMB_VFS_OP_GET_NT_ACL,
+ SMB_VFS_OP_FSET_NT_ACL,
+ SMB_VFS_OP_SET_NT_ACL,
+
+ /* POSIX ACL operations. */
+
+ SMB_VFS_OP_CHMOD_ACL,
+ SMB_VFS_OP_FCHMOD_ACL,
+
+ SMB_VFS_OP_SYS_ACL_GET_ENTRY,
+ SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE,
+ SMB_VFS_OP_SYS_ACL_GET_PERMSET,
+ SMB_VFS_OP_SYS_ACL_GET_QUALIFIER,
+ SMB_VFS_OP_SYS_ACL_GET_FILE,
+ SMB_VFS_OP_SYS_ACL_GET_FD,
+ SMB_VFS_OP_SYS_ACL_CLEAR_PERMS,
+ SMB_VFS_OP_SYS_ACL_ADD_PERM,
+ SMB_VFS_OP_SYS_ACL_TO_TEXT,
+ SMB_VFS_OP_SYS_ACL_INIT,
+ SMB_VFS_OP_SYS_ACL_CREATE_ENTRY,
+ SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE,
+ SMB_VFS_OP_SYS_ACL_SET_QUALIFIER,
+ SMB_VFS_OP_SYS_ACL_SET_PERMSET,
+ SMB_VFS_OP_SYS_ACL_VALID,
+ SMB_VFS_OP_SYS_ACL_SET_FILE,
+ SMB_VFS_OP_SYS_ACL_SET_FD,
+ SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
+ SMB_VFS_OP_SYS_ACL_GET_PERM,
+ SMB_VFS_OP_SYS_ACL_FREE_TEXT,
+ SMB_VFS_OP_SYS_ACL_FREE_ACL,
+ SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER,
+
+ /* This should always be last enum value */
+
+ SMB_VFS_OP_LAST
+} vfs_op_type;
+
+/*
+ Possible VFS operation layers (per-operation)
+
+ These values are used by VFS subsystem when building vfs_ops for connection
+ from multiple VFS modules. Internally, Samba differentiates only opaque and
+ transparent layers at this process. Other types are used for providing better
+ diagnosing facilities.
+
+ Most modules will provide transparent layers. Opaque layer is for modules
+ which implement actual file system calls (like DB-based VFS). For example,
+ default POSIX VFS which is built in into Samba is an opaque VFS module.
+
+ Other layer types (audit, splitter, scanner) were designed to provide different
+ degree of transparency and for diagnosing VFS module behaviour.
+
+ Each module can implement several layers at the same time provided that only
+ one layer is used per each operation.
+
+*/
+
+typedef enum _vfs_op_layer {
+ SMB_VFS_LAYER_NOOP = -1, /* - For using in VFS module to indicate end of array */
+ /* of operations description */
+ SMB_VFS_LAYER_OPAQUE = 0, /* - Final level, does not call anything beyond itself */
+ SMB_VFS_LAYER_TRANSPARENT, /* - Normal operation, calls underlying layer after */
+ /* possibly changing passed data */
+ SMB_VFS_LAYER_LOGGER, /* - Logs data, calls underlying layer, logging does not */
+ /* use Samba VFS */
+ SMB_VFS_LAYER_SPLITTER, /* - Splits operation, calls underlying layer _and_ own facility, */
+ /* then combines result */
+ SMB_VFS_LAYER_SCANNER /* - Checks data and possibly initiates additional */
+ /* file activity like logging to files _inside_ samba VFS */
+} vfs_op_layer;
+
+/*
+ VFS operation description. Each VFS module initialization function returns to VFS subsystem
+ an array of vfs_op_tuple which describes all operations this module is willing to intercept.
+ VFS subsystem initializes then vfs_ops using this information and passes it
+ to next VFS module as underlying vfs_ops and to connection after all VFS modules are initialized.
+*/
+
+typedef struct _vfs_op_tuple {
+ void* op;
+ vfs_op_type type;
+ vfs_op_layer layer;
+} vfs_op_tuple;
+
+/*
+ Return vfs_ops filled with current opaque VFS operations. This function is designed to
+ be called from VFS module initialization function for those modules which needs 'direct' VFS
+ access (loggers or initiators of file operations other than connection asks for).
+
+ Returned vfs_ops must be cleaned up in VFS module's finalizer function (vfs_done_<module_name>)
+ using safe_free().
+
+ Prototype:
+ struct vfs_ops *smb_vfs_get_opaque_ops();
+
+ This prototype will be available via include/proto.h
+*/
+
#endif /* _VFS_H */
diff --git a/source/intl/lang_tdb.c b/source/intl/lang_tdb.c
index d5e8bd41bd5..a86ea0a3f9a 100644
--- a/source/intl/lang_tdb.c
+++ b/source/intl/lang_tdb.c
@@ -106,8 +106,10 @@ BOOL lang_tdb_init(const char *lang)
if (initialised) {
/* we are re-initialising, free up any old init */
- tdb_close(tdb);
- tdb = NULL;
+ if (tdb) {
+ tdb_close(tdb);
+ tdb = NULL;
+ }
SAFE_FREE(current_lang);
}
diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c
index 07676e22022..07b5e2ecfc6 100644
--- a/source/lib/account_pol.c
+++ b/source/lib/account_pol.c
@@ -2,6 +2,7 @@
* Unix SMB/CIFS implementation.
* account policy storage
* Copyright (C) Jean François Micouleau 1998-2001.
+ * 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
@@ -31,6 +32,7 @@ BOOL init_account_policy(void)
{
static pid_t local_pid;
char *vstring = "INFO/version";
+ uint32 version;
if (tdb && local_pid == sys_getpid())
return True;
@@ -44,9 +46,9 @@ BOOL init_account_policy(void)
/* handle a Samba upgrade */
tdb_lock_bystring(tdb, vstring);
- if (tdb_fetch_int32(tdb, vstring) != DATABASE_VERSION) {
+ if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) {
tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
- tdb_store_int32(tdb, vstring, DATABASE_VERSION);
+ tdb_store_uint32(tdb, vstring, DATABASE_VERSION);
account_policy_set(AP_MIN_PASSWORD_LEN, MINPASSWDLENGTH); /* 5 chars minimum */
account_policy_set(AP_PASSWORD_HISTORY, 0); /* don't keep any old password */
@@ -63,33 +65,50 @@ BOOL init_account_policy(void)
return True;
}
+static const struct {
+ int field;
+ char *string;
+} account_policy_names[] = {
+ {AP_MIN_PASSWORD_LEN, "min password length"},
+ {AP_PASSWORD_HISTORY, "password history"},
+ {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password"},
+ {AP_MAX_PASSWORD_AGE, "maximum password age"},
+ {AP_MIN_PASSWORD_AGE,"minimum password age"},
+ {AP_LOCK_ACCOUNT_DURATION, "lockout duration"},
+ {AP_RESET_COUNT_TIME, "reset count minutes"},
+ {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt"},
+ {AP_TIME_TO_LOGOUT, "disconnect time"},
+ {0, NULL}
+};
+
+/****************************************************************************
+Get the account policy name as a string from its #define'ed number
+****************************************************************************/
+
+static const char *decode_account_policy_name(int field)
+{
+ int i;
+ for (i=0; account_policy_names[i].string; i++) {
+ if (field == account_policy_names[i].field)
+ return account_policy_names[i].string;
+ }
+ return NULL;
+
+}
+
/****************************************************************************
+Get the account policy name as a string from its #define'ed number
****************************************************************************/
-static char *decode_account_policy_name(int field)
+int account_policy_name_to_fieldnum(const char *name)
{
- switch (field) {
- case AP_MIN_PASSWORD_LEN:
- return "min password length";
- case AP_PASSWORD_HISTORY:
- return "password history";
- case AP_USER_MUST_LOGON_TO_CHG_PASS:
- return "user must logon to change password";
- case AP_MAX_PASSWORD_AGE:
- return "maximum password age";
- case AP_MIN_PASSWORD_AGE:
- return "minimum password age";
- case AP_LOCK_ACCOUNT_DURATION:
- return "lockout duration";
- case AP_RESET_COUNT_TIME:
- return "reset count minutes";
- case AP_BAD_ATTEMPT_LOCKOUT:
- return "bad lockout attempt";
- case AP_TIME_TO_LOGOUT:
- return "disconnect time";
- default:
- return "undefined value";
+ int i;
+ for (i=0; account_policy_names[i].string; i++) {
+ if (strcmp(name, account_policy_names[i].string) == 0)
+ return account_policy_names[i].field;
}
+ return 0;
+
}
@@ -101,8 +120,17 @@ BOOL account_policy_get(int field, uint32 *value)
init_account_policy();
+ *value = 0;
+
fstrcpy(name, decode_account_policy_name(field));
- *value=tdb_fetch_int32(tdb, name);
+ if (!*name) {
+ DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field));
+ return False;
+ }
+ if (!tdb_fetch_uint32(tdb, name, value)) {
+ DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for feild %d (%s), returning 0", field, name));
+ return False;
+ }
DEBUG(10,("account_policy_get: %s:%d\n", name, *value));
return True;
}
@@ -117,8 +145,16 @@ BOOL account_policy_set(int field, uint32 value)
init_account_policy();
fstrcpy(name, decode_account_policy_name(field));
- if ( tdb_store_int32(tdb, name, value)== -1)
+ if (!*name) {
+ DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", field));
return False;
+ }
+
+ if (!tdb_store_uint32(tdb, name, value)) {
+ DEBUG(1, ("tdb_store_uint32 failed for feild %d (%s) on value %u", field, name, value));
+ return False;
+ }
+
DEBUG(10,("account_policy_set: %s:%d\n", name, value));
return True;
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index d42dc994b00..6e961366435 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -249,15 +249,15 @@ convert:
size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
void const *src, size_t srclen, void **dest)
{
- void *ob;
+ void *alloced_string;
size_t dest_len;
*dest = NULL;
- dest_len=convert_string_allocate(from, to, src, srclen, (void **)&ob);
+ dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string);
if (dest_len == -1)
return -1;
- *dest = talloc_strdup(ctx, (char *)ob);
- SAFE_FREE(ob);
+ *dest = talloc_memdup(ctx, alloced_string, dest_len);
+ SAFE_FREE(alloced_string);
if (*dest == NULL)
return -1;
return dest_len;
@@ -505,12 +505,12 @@ int push_utf8_pstring(void *dest, const char *src)
*
* @retval The number of bytes occupied by the string in the destination
**/
-int push_utf8_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
+int push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
{
int src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, dest);
+ return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
}
/**
@@ -562,7 +562,8 @@ int pull_ucs2(const void *base_ptr, char *dest, const void *src, int dest_len, i
}
/* ucs2 is always a multiple of 2 bytes */
- src_len &= ~1;
+ if (src_len != -1)
+ src_len &= ~1;
ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
@@ -658,11 +659,11 @@ int pull_utf8_fstring(char *dest, const void *src)
*
* @retval The number of bytes occupied by the string in the destination
**/
-int pull_utf8_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
+int pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
{
int src_len = strlen(src)+1;
*dest = NULL;
- return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, dest);
+ return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
}
/**
diff --git a/source/lib/debug.c b/source/lib/debug.c
index f41c3b64976..842d2dac1d6 100644
--- a/source/lib/debug.c
+++ b/source/lib/debug.c
@@ -423,7 +423,7 @@ BOOL debug_parse_levels(const char *params_str)
if (AllowDebugChange == False)
return True;
- params = str_list_make(params_str);
+ params = str_list_make(params_str, NULL);
if (debug_parse_params(params, DEBUGLEVEL_CLASS,
DEBUGLEVEL_CLASS_ISSET))
@@ -602,6 +602,12 @@ BOOL reopen_logs( void )
force_check_log_size();
(void)umask(oldumask);
+ /* Take over stderr to catch ouput into logs */
+ if (dbf && sys_dup2(dbf->fd, 2) == -1) {
+ close_low_fds(True); /* Close stderr too, if dup2 can't point it
+ at the logfile */
+ }
+
return ret;
}
diff --git a/source/lib/genrand.c b/source/lib/genrand.c
index ee8bc0b1d5a..fe756169a66 100644
--- a/source/lib/genrand.c
+++ b/source/lib/genrand.c
@@ -259,7 +259,7 @@ char *generate_random_str(size_t len)
len = sizeof(retstr) -1;
generate_random_buffer( retstr, len, False);
for (i = 0; i < len; i++)
- retstr[i] = c_list[ retstr[i] % sizeof(c_list) ];
+ retstr[i] = c_list[ retstr[i] % (sizeof(c_list)-1) ];
retstr[i] = '\0';
diff --git a/source/lib/replace.c b/source/lib/replace.c
index 2cc7d48adb3..fd7b2cf7f01 100644
--- a/source/lib/replace.c
+++ b/source/lib/replace.c
@@ -428,3 +428,5 @@ char *rep_inet_ntoa(struct in_addr ip)
}
#endif /* HAVE_SYSLOG */
#endif /* HAVE_VSYSLOG */
+
+
diff --git a/source/lib/smbrun.c b/source/lib/smbrun.c
index 67f82ed0ad4..592543bc43b 100644
--- a/source/lib/smbrun.c
+++ b/source/lib/smbrun.c
@@ -143,7 +143,7 @@ int smbrun(char *cmd, int *outfd)
/* point our stdout at the file we want output to go into */
if (outfd) {
close(1);
- if (dup2(*outfd,1) != 1) {
+ if (sys_dup2(*outfd,1) != 1) {
DEBUG(2,("Failed to create stdout file descriptor\n"));
close(*outfd);
exit(80);
diff --git a/source/lib/substitute.c b/source/lib/substitute.c
index 6d96a1820f1..026df0f67f1 100644
--- a/source/lib/substitute.c
+++ b/source/lib/substitute.c
@@ -25,9 +25,41 @@ fstring local_machine="";
fstring remote_arch="UNKNOWN";
userdom_struct current_user_info;
fstring remote_proto="UNKNOWN";
-fstring remote_machine="";
extern pstring global_myname;
+static fstring remote_machine="";
+
+
+void set_local_machine_name(const char* local_name)
+{
+ fstring tmp_local_machine;
+
+ fstrcpy(tmp_local_machine,local_name);
+ trim_string(tmp_local_machine," "," ");
+ strlower(tmp_local_machine);
+ alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
+}
+
+void set_remote_machine_name(const char* remote_name)
+{
+ fstring tmp_remote_machine;
+
+ fstrcpy(tmp_remote_machine,remote_name);
+ trim_string(tmp_remote_machine," "," ");
+ strlower(tmp_remote_machine);
+ alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
+}
+
+const char* get_remote_machine_name(void)
+{
+ return remote_machine;
+}
+
+const char* get_local_machine_name(void)
+{
+ return local_machine;
+}
+
/*******************************************************************
Given a pointer to a %$(NAME) expand it as an environment variable.
Return the number of characters by which the pointer should be advanced.
@@ -188,14 +220,15 @@ static char *automount_path(const char *user_name)
moved out to a separate function.
*******************************************************************/
-static char *automount_server(const char *user_name)
+static const char *automount_server(const char *user_name)
{
static pstring server_name;
+ const char *local_machine_name = get_local_machine_name();
/* use the local machine name as the default */
/* this will be the default if WITH_AUTOMOUNT is not used or fails */
- if (*local_machine)
- pstrcpy(server_name, local_machine);
+ if (local_machine_name && *local_machine_name)
+ pstrcpy(server_name, local_machine_name);
else
pstrcpy(server_name, global_myname);
@@ -229,6 +262,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len)
char *p, *s;
fstring pidstr;
struct passwd *pass;
+ const char *local_machine_name = get_local_machine_name();
for (s=str; (p=strchr_m(s, '%'));s=p) {
fstring tmp_str;
@@ -261,8 +295,8 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len)
string_sub(p,"%I", client_addr(),l);
break;
case 'L' :
- if (*local_machine)
- string_sub(p,"%L", local_machine,l);
+ if (local_machine_name && *local_machine_name)
+ string_sub(p,"%L", local_machine_name,l);
else
string_sub(p,"%L", global_myname,l);
break;
@@ -286,7 +320,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len)
string_sub(p,"%h", myhostname(),l);
break;
case 'm' :
- string_sub(p,"%m", remote_machine,l);
+ string_sub(p,"%m", get_remote_machine_name(),l);
break;
case 'v' :
string_sub(p,"%v", VERSION,l);
@@ -381,6 +415,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
char *b, *p, *s, *t, *r, *a_string;
fstring pidstr;
struct passwd *pass;
+ const char *local_machine_name = get_local_machine_name();
a_string = strdup(str);
if (a_string == NULL) {
@@ -415,8 +450,8 @@ char *alloc_sub_basic(const char *smb_name, const char *str)
t = realloc_string_sub(t, "%I", client_addr());
break;
case 'L' :
- if (*local_machine)
- t = realloc_string_sub(t, "%L", local_machine);
+ if (local_machine_name && *local_machine_name)
+ t = realloc_string_sub(t, "%L", local_machine_name);
else
t = realloc_string_sub(t, "%L", global_myname);
break;
diff --git a/source/lib/system.c b/source/lib/system.c
index 8b2ba800f53..edda54a78d2 100644
--- a/source/lib/system.c
+++ b/source/lib/system.c
@@ -1219,6 +1219,16 @@ const char *sys_dlerror(void)
#endif
}
+int sys_dup2(int oldfd, int newfd)
+{
+#if defined(HAVE_DUP2)
+ return dup2(oldfd, newfd);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
/**************************************************************************
Wrapper for Admin Logs.
****************************************************************************/
diff --git a/source/lib/username.c b/source/lib/username.c
index 4813c8fd194..5db7f58b1e2 100644
--- a/source/lib/username.c
+++ b/source/lib/username.c
@@ -163,7 +163,7 @@ BOOL map_username(char *user)
}
}
- dosuserlist = str_list_make(dosname);
+ dosuserlist = str_list_make(dosname, NULL);
if (!dosuserlist) {
DEBUG(0,("Unable to build user list\n"));
return False;
diff --git a/source/lib/util.c b/source/lib/util.c
index be108aa4056..ae94b710b2c 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -100,7 +100,7 @@ char *tmpdir(void)
Determine whether we are in the specified group.
****************************************************************************/
-BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
+BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups)
{
int i;
@@ -503,27 +503,32 @@ void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,ti
/*******************************************************************
close the low 3 fd's and open dev/null in their place
********************************************************************/
-void close_low_fds(void)
+void close_low_fds(BOOL stderr_too)
{
int fd;
int i;
close(0); close(1);
-#ifndef __INSURE__
- close(2);
-#endif
+
+ if (stderr_too) {
+ close(2);
+ }
+
/* try and use up these file descriptors, so silly
library routines writing to stdout etc won't cause havoc */
for (i=0;i<3;i++) {
- fd = sys_open("/dev/null",O_RDWR,0);
- if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
- if (fd < 0) {
- DEBUG(0,("Can't open /dev/null\n"));
- return;
- }
- if (fd != i) {
- DEBUG(0,("Didn't get file descriptor %d\n",i));
- return;
- }
+ if (i == 2 && !stderr_too)
+ continue;
+
+ fd = sys_open("/dev/null",O_RDWR,0);
+ if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
+ if (fd < 0) {
+ DEBUG(0,("Can't open /dev/null\n"));
+ return;
+ }
+ if (fd != i) {
+ DEBUG(0,("Didn't get file descriptor %d\n",i));
+ return;
+ }
}
}
@@ -678,7 +683,8 @@ void become_daemon(void)
#endif /* HAVE_SETSID */
/* Close fd's 0,1,2. Needed if started by rsh */
- close_low_fds();
+ close_low_fds(False); /* Don't close stderr, let the debug system
+ attach it to the logfile */
}
diff --git a/source/lib/util_getent.c b/source/lib/util_getent.c
index 2e76121aae1..6699ce3e923 100644
--- a/source/lib/util_getent.c
+++ b/source/lib/util_getent.c
@@ -21,27 +21,6 @@
#include "includes.h"
-#if 0
-static void print_grent_list(struct sys_grent *glist)
-{
- DEBUG(100, ("print_grent_list: %x\n", glist ));
- while (glist) {
- DEBUG(100,("glist: %x ", glist));
- if (glist->gr_name)
- DEBUG(100,(": gr_name = (%x) %s ", glist->gr_name, glist->gr_name));
- if (glist->gr_passwd)
- DEBUG(100,(": gr_passwd = (%x) %s ", glist->gr_passwd, glist->gr_passwd));
- if (glist->gr_mem) {
- int i;
- for (i = 0; glist->gr_mem[i]; i++)
- DEBUG(100,(" : gr_mem[%d] = (%x) %s ", i, glist->gr_mem[i], glist->gr_mem[i]));
- }
- DEBUG(100,(": gr_next = %x\n", glist->next ));
- glist = glist->next;
- }
- DEBUG(100,("FINISHED !\n\n"));
-}
-#endif
/****************************************************************
Returns a single linked list of group entries.
diff --git a/source/lib/util_sid.c b/source/lib/util_sid.c
index 5dd1d75c701..ad09f912346 100644
--- a/source/lib/util_sid.c
+++ b/source/lib/util_sid.c
@@ -365,6 +365,9 @@ BOOL sid_parse(char *inbuf, size_t len, DOM_SID *sid)
{
int i;
if (len < 8) return False;
+
+ ZERO_STRUCTP(sid);
+
sid->sid_rev_num = CVAL(inbuf, 0);
sid->num_auths = CVAL(inbuf, 1);
memcpy(sid->id_auth, inbuf+2, 6);
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index 4f1f2a1470a..5e2b7c5ed97 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -708,7 +708,7 @@ int open_socket_in( int type, int port, int dlevel, uint32 socket_addr, BOOL reb
/* now we've got a socket - we need to bind it */
if( bind( res, (struct sockaddr *)&sock, sizeof(sock) ) == -1 ) {
- if( DEBUGLVL(dlevel) && (port == SMB_PORT || port == NMB_PORT) ) {
+ if( DEBUGLVL(dlevel) && (port == SMB_PORT1 || port == SMB_PORT2 || port == NMB_PORT) ) {
dbgtext( "bind failed on port %d ", port );
dbgtext( "socket_addr = %s.\n", inet_ntoa( sock.sin_addr ) );
dbgtext( "Error = %s\n", strerror(errno) );
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index 88a72f15360..19d92eec8fb 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -212,6 +212,18 @@ int strwicmp(const char *psz1, const char *psz2)
}
+/* Convert a string to upper case, but don't modify it */
+
+char *strupper_static(const char *s)
+{
+ static pstring str;
+
+ pstrcpy(str, s);
+ strupper(str);
+
+ return str;
+}
+
/*******************************************************************
convert a string to "normal" form
********************************************************************/
@@ -299,7 +311,7 @@ BOOL trim_string(char *s,const char *front,const char *back)
}
if (back_len) {
- while (strncmp(s+len-back_len,back,back_len)==0) {
+ while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
s[len-back_len]='\0';
len -= back_len;
ret=True;
@@ -667,7 +679,7 @@ void string_sub(char *s,const char *pattern, const char *insert, size_t len)
li = (ssize_t)strlen(insert);
if (len == 0)
- len = ls;
+ len = ls + 1; /* len is number of *bytes* */
while (lp <= ls && (p = strstr(s,pattern))) {
if (ls + (li-lp) >= len) {
@@ -798,7 +810,7 @@ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
return;
if (len == 0)
- len = ls;
+ len = ls + 1; /* len is number of *bytes* */
while (lp <= ls && (p = strstr(s,pattern))) {
if (ls + (li-lp) >= len) {
@@ -826,7 +838,8 @@ return a new allocate unicode string.
smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
const smb_ucs2_t *insert)
{
- smb_ucs2_t *r, *rp, *sp;
+ smb_ucs2_t *r, *rp;
+ const smb_ucs2_t *sp;
size_t lr, lp, li, lt;
if (!insert || !pattern || !*pattern || !s) return NULL;
@@ -836,7 +849,7 @@ smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
li = (size_t)strlen_w(insert);
if (li > lp) {
- smb_ucs2_t *st = s;
+ const smb_ucs2_t *st = s;
int ld = li - lp;
while ((sp = strstr_w(st, pattern))) {
st = sp + lp;
@@ -879,68 +892,59 @@ smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
}
/****************************************************************************
- splits out the front and back at a separator.
+ Splits out the front and back at a separator.
****************************************************************************/
+
void split_at_last_component(char *path, char *front, char sep, char *back)
{
char *p = strrchr_m(path, sep);
if (p != NULL)
- {
*p = 0;
- }
+
if (front != NULL)
- {
pstrcpy(front, path);
- }
- if (p != NULL)
- {
+
+ if (p != NULL) {
if (back != NULL)
- {
pstrcpy(back, p+1);
- }
*p = '\\';
- }
- else
- {
+ } else {
if (back != NULL)
- {
back[0] = 0;
- }
}
}
-
/****************************************************************************
-write an octal as a string
+ Write an octal as a string.
****************************************************************************/
+
char *octal_string(int i)
{
static char ret[64];
- if (i == -1) {
+ if (i == -1)
return "-1";
- }
slprintf(ret, sizeof(ret)-1, "0%o", i);
return ret;
}
/****************************************************************************
-truncate a string at a specified length
+ Truncate a string at a specified length.
****************************************************************************/
+
char *string_truncate(char *s, int length)
{
- if (s && strlen(s) > length) {
+ if (s && strlen(s) > length)
s[length] = 0;
- }
return s;
}
-
/****************************************************************************
-strchr and strrchr_m are very hard to do on general multi-byte strings.
-we convert via ucs2 for now
+ Strchr and strrchr_m are very hard to do on general multi-byte strings.
+ We convert via ucs2 for now.
****************************************************************************/
+
char *strchr_m(const char *s, char c)
{
wpstring ws;
@@ -949,7 +953,8 @@ char *strchr_m(const char *s, char c)
push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
p = strchr_w(ws, UCS2_CHAR(c));
- if (!p) return NULL;
+ if (!p)
+ return NULL;
*p = 0;
pull_ucs2_pstring(s2, ws);
return (char *)(s+strlen(s2));
@@ -963,26 +968,29 @@ char *strrchr_m(const char *s, char c)
push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
p = strrchr_w(ws, UCS2_CHAR(c));
- if (!p) return NULL;
+ if (!p)
+ return NULL;
*p = 0;
pull_ucs2_pstring(s2, ws);
return (char *)(s+strlen(s2));
}
/*******************************************************************
- convert a string to lower case
+ Convert a string to lower case.
********************************************************************/
+
void strlower_m(char *s)
{
/* this is quite a common operation, so we want it to be
fast. We optimise for the ascii case, knowing that all our
supported multi-byte character sets are ascii-compatible
(ie. they match for the first 128 chars) */
- while (*s && !(((unsigned char)s[0]) & 0x7F)) {
+
+ while (*s && !(((unsigned char)s[0]) & 0x7F))
*s++ = tolower((unsigned char)*s);
- }
- if (!*s) return;
+ if (!*s)
+ return;
/* I assume that lowercased string takes the same number of bytes
* as source string even in UTF-8 encoding. (VIV) */
@@ -990,8 +998,9 @@ void strlower_m(char *s)
}
/*******************************************************************
- duplicate convert a string to lower case
+ Duplicate convert a string to lower case.
********************************************************************/
+
char *strdup_lower(const char *s)
{
char *t = strdup(s);
@@ -1004,19 +1013,21 @@ char *strdup_lower(const char *s)
}
/*******************************************************************
- convert a string to upper case
+ Convert a string to upper case.
********************************************************************/
+
void strupper_m(char *s)
{
/* this is quite a common operation, so we want it to be
fast. We optimise for the ascii case, knowing that all our
supported multi-byte character sets are ascii-compatible
(ie. they match for the first 128 chars) */
- while (*s && !(((unsigned char)s[0]) & 0x7F)) {
+
+ while (*s && !(((unsigned char)s[0]) & 0x7F))
*s++ = toupper((unsigned char)*s);
- }
- if (!*s) return;
+ if (!*s)
+ return;
/* I assume that lowercased string takes the same number of bytes
* as source string even in multibyte encoding. (VIV) */
@@ -1024,8 +1035,9 @@ void strupper_m(char *s)
}
/*******************************************************************
- convert a string to upper case
+ Convert a string to upper case.
********************************************************************/
+
char *strdup_upper(const char *s)
{
char *t = strdup(s);
@@ -1048,7 +1060,8 @@ char *binary_string(char *buf, int len)
int i, j;
const char *hex = "0123456789ABCDEF";
s = malloc(len * 3 + 1);
- if (!s) return NULL;
+ if (!s)
+ return NULL;
for (j=i=0;i<len;i++) {
s[j] = '\\';
s[j+1] = hex[((unsigned char)buf[i]) >> 4];
@@ -1059,8 +1072,8 @@ char *binary_string(char *buf, int len)
return s;
}
-
/* Just a typesafety wrapper for snprintf into a pstring */
+
int pstr_sprintf(pstring s, const char *fmt, ...)
{
va_list ap;
@@ -1072,8 +1085,8 @@ int pstr_sprintf(pstring s, const char *fmt, ...)
return ret;
}
-
/* Just a typesafety wrapper for snprintf into a fstring */
+
int fstr_sprintf(fstring s, const char *fmt, ...)
{
va_list ap;
@@ -1085,18 +1098,19 @@ int fstr_sprintf(fstring s, const char *fmt, ...)
return ret;
}
-
#ifndef HAVE_STRNDUP
/*******************************************************************
-some platforms don't have strndup
+ Some platforms don't have strndup.
********************************************************************/
+
char *strndup(const char *s, size_t n)
{
char *ret;
n = strnlen(s, n);
ret = malloc(n+1);
- if (!ret) return NULL;
+ if (!ret)
+ return NULL;
memcpy(ret, s, n);
ret[n] = 0;
@@ -1111,39 +1125,39 @@ some platforms don't have strnlen
size_t strnlen(const char *s, size_t n)
{
int i;
- for (i=0; s[i] && i<n; i++) /* noop */ ;
+ for (i=0; s[i] && i<n; i++)
+ /* noop */ ;
return i;
}
#endif
-
-
/***********************************************************
List of Strings manipulation functions
***********************************************************/
#define S_LIST_ABS 16 /* List Allocation Block Size */
-char **str_list_make(const char *string)
+char **str_list_make(const char *string, const char *sep)
{
char **list, **rlist;
char *str, *s;
int num, lsize;
pstring tok;
- if (!string || !*string) return NULL;
+ if (!string || !*string)
+ return NULL;
s = strdup(string);
if (!s) {
DEBUG(0,("str_list_make: Unable to allocate memory"));
return NULL;
}
+ if (!sep) sep = LIST_SEP;
num = lsize = 0;
list = NULL;
str = s;
- while (next_token(&str, tok, LIST_SEP, sizeof(tok)))
- {
+ while (next_token(&str, tok, sep, sizeof(tok))) {
if (num == lsize) {
lsize += S_LIST_ABS;
rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
@@ -1178,13 +1192,13 @@ BOOL str_list_copy(char ***dest, char **src)
int num, lsize;
*dest = NULL;
- if (!src) return False;
+ if (!src)
+ return False;
num = lsize = 0;
list = NULL;
- while (src[num])
- {
+ while (src[num]) {
if (num == lsize) {
lsize += S_LIST_ABS;
rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
@@ -1212,17 +1226,22 @@ BOOL str_list_copy(char ***dest, char **src)
}
/* return true if all the elemnts of the list matches exactly */
+
BOOL str_list_compare(char **list1, char **list2)
{
int num;
- if (!list1 || !list2) return (list1 == list2);
+ if (!list1 || !list2)
+ return (list1 == list2);
for (num = 0; list1[num]; num++) {
- if (!list2[num]) return False;
- if (!strcsequal(list1[num], list2[num])) return False;
+ if (!list2[num])
+ return False;
+ if (!strcsequal(list1[num], list2[num]))
+ return False;
}
- if (list2[num]) return False; /* if list2 has more elements than list1 fail */
+ if (list2[num])
+ return False; /* if list2 has more elements than list1 fail */
return True;
}
@@ -1231,9 +1250,11 @@ void str_list_free(char ***list)
{
char **tlist;
- if (!list || !*list) return;
+ if (!list || !*list)
+ return;
tlist = *list;
- for(; *tlist; tlist++) SAFE_FREE(*tlist);
+ for(; *tlist; tlist++)
+ SAFE_FREE(*tlist);
SAFE_FREE(*list);
}
@@ -1242,25 +1263,25 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
char *p, *s, *t;
ssize_t ls, lp, li, ld, i, d;
- if (!list) return False;
- if (!pattern) return False;
- if (!insert) return False;
+ if (!list)
+ return False;
+ if (!pattern)
+ return False;
+ if (!insert)
+ return False;
lp = (ssize_t)strlen(pattern);
li = (ssize_t)strlen(insert);
ld = li -lp;
- while (*list)
- {
+ while (*list) {
s = *list;
ls = (ssize_t)strlen(s);
- while ((p = strstr(s, pattern)))
- {
+ while ((p = strstr(s, pattern))) {
t = *list;
d = p -t;
- if (ld)
- {
+ if (ld) {
t = (char *) malloc(ls +ld +1);
if (!t) {
DEBUG(0,("str_list_substitute: Unable to allocate memory"));
diff --git a/source/lib/wins_srv.c b/source/lib/wins_srv.c
index adf405ae7e2..61e77aca587 100644
--- a/source/lib/wins_srv.c
+++ b/source/lib/wins_srv.c
@@ -236,7 +236,7 @@ char **wins_srv_tags(void)
}
/* add it to the list */
- ret = (char **)Realloc(ret, (count+1) * sizeof(char *));
+ ret = (char **)Realloc(ret, (count+2) * sizeof(char *));
ret[count] = strdup(t_ip.tag);
if (!ret[count]) break;
count++;
diff --git a/source/lib/xfile.c b/source/lib/xfile.c
index 903dfb1ae0a..b5710f3a39e 100644
--- a/source/lib/xfile.c
+++ b/source/lib/xfile.c
@@ -171,7 +171,7 @@ int x_fwrite(const void *p, size_t size, size_t nmemb, XFILE *f)
flush a bit more than necessary, but that is harmless */
if (f->buftype == X_IOLBF && f->bufused) {
int i;
- for (i=size-1; i>=0; i--) {
+ for (i=(size*nmemb)-1; i>=0; i--) {
if (*(i+(const char *)p) == '\n') {
x_fflush(f);
break;
diff --git a/source/libads/ads_struct.c b/source/libads/ads_struct.c
index 638dc0b22e5..b68c822ce35 100644
--- a/source/libads/ads_struct.c
+++ b/source/libads/ads_struct.c
@@ -72,47 +72,6 @@ char *ads_build_dn(const char *realm)
}
-#ifdef HAVE_LDAP
-/*
- find the ldap server from DNS
-*/
-static char *find_ldap_server(ADS_STRUCT *ads)
-{
- char *list = NULL;
- struct in_addr ip;
-
- if (ads->realm &&
- strcasecmp(ads->workgroup, lp_workgroup()) == 0 &&
- ldap_domain2hostlist(ads->realm, &list) == LDAP_SUCCESS) {
- char *p;
- p = strchr(list, ':');
- if (p) *p = 0;
- return list;
- }
-
- /* get desperate, find the domain controller IP */
- if (resolve_name(ads->workgroup, &ip, 0x1B)) {
- return strdup(inet_ntoa(ip));
- }
-
- /* or a BDC ... */
- if (resolve_name(ads->workgroup, &ip, 0x1C)) {
- return strdup(inet_ntoa(ip));
- }
-
- return NULL;
-}
-
-#else
-
-static char *find_ldap_server(ADS_STRUCT *ads)
-{
- /* Without LDAP this doesn't make much sense */
- return NULL;
-}
-
-#endif
-
#ifndef LDAP_PORT
#define LDAP_PORT 389
#endif
@@ -122,46 +81,24 @@ static char *find_ldap_server(ADS_STRUCT *ads)
*/
ADS_STRUCT *ads_init(const char *realm,
const char *workgroup,
- const char *ldap_server,
- const char *bind_path,
- const char *password)
+ const char *ldap_server)
{
ADS_STRUCT *ads;
ads = (ADS_STRUCT *)smb_xmalloc(sizeof(*ads));
ZERO_STRUCTP(ads);
- if (!workgroup) {
- workgroup = lp_workgroup();
+ ads->server.realm = realm? strdup(realm) : NULL;
+ ads->server.workgroup = workgroup ? strdup(workgroup) : NULL;
+ ads->server.ldap_server = ldap_server? strdup(ldap_server) : NULL;
+
+ /* we need to know if this is a foreign realm to know if we can
+ use lp_ads_server() */
+ if (realm && strcasecmp(lp_realm(), realm) != 0) {
+ ads->server.foreign = 1;
}
-
- ads->realm = realm? strdup(realm) : NULL;
- ads->workgroup = strdup(workgroup);
- ads->ldap_server = ldap_server? strdup(ldap_server) : NULL;
- ads->bind_path = bind_path? strdup(bind_path) : NULL;
- ads->ldap_port = LDAP_PORT;
- if (password) ads->password = strdup(password);
-
- if (!ads->realm) {
- ads->realm = strdup(lp_realm());
- if (!ads->realm[0]) {
- SAFE_FREE(ads->realm);
- }
- }
- if (!ads->bind_path && ads->realm) {
- ads->bind_path = ads_build_dn(ads->realm);
- }
- if (!ads->ldap_server) {
- if (strcasecmp(ads->workgroup, lp_workgroup()) == 0) {
- ads->ldap_server = strdup(lp_ads_server());
- }
- if (!ads->ldap_server || !ads->ldap_server[0]) {
- ads->ldap_server = find_ldap_server(ads);
- }
- }
- if (!ads->kdc_server) {
- /* assume its the same as LDAP */
- ads->kdc_server = ads->ldap_server? strdup(ads->ldap_server) : NULL;
+ if (workgroup && strcasecmp(lp_workgroup(), workgroup) != 0) {
+ ads->server.foreign = 1;
}
return ads;
@@ -170,7 +107,7 @@ ADS_STRUCT *ads_init(const char *realm,
/* a simpler ads_init() interface using all defaults */
ADS_STRUCT *ads_init_simple(void)
{
- return ads_init(NULL, NULL, NULL, NULL, NULL);
+ return ads_init(NULL, NULL, NULL);
}
/*
@@ -182,13 +119,19 @@ void ads_destroy(ADS_STRUCT **ads)
#if HAVE_LDAP
if ((*ads)->ld) ldap_unbind((*ads)->ld);
#endif
- SAFE_FREE((*ads)->realm);
- SAFE_FREE((*ads)->ldap_server);
- SAFE_FREE((*ads)->ldap_server_name);
- SAFE_FREE((*ads)->kdc_server);
- SAFE_FREE((*ads)->bind_path);
- SAFE_FREE((*ads)->password);
- SAFE_FREE((*ads)->user_name);
+ SAFE_FREE((*ads)->server.realm);
+ SAFE_FREE((*ads)->server.workgroup);
+ SAFE_FREE((*ads)->server.ldap_server);
+
+ SAFE_FREE((*ads)->auth.realm);
+ SAFE_FREE((*ads)->auth.password);
+ SAFE_FREE((*ads)->auth.user_name);
+ SAFE_FREE((*ads)->auth.kdc_server);
+
+ SAFE_FREE((*ads)->config.realm);
+ SAFE_FREE((*ads)->config.bind_path);
+ SAFE_FREE((*ads)->config.ldap_server_name);
+
ZERO_STRUCTP(*ads);
SAFE_FREE(*ads);
}
diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c
index 1ba5d978e8c..9a486237c9f 100644
--- a/source/libads/kerberos.c
+++ b/source/libads/kerberos.c
@@ -110,16 +110,8 @@ int ads_kinit_password(ADS_STRUCT *ads)
char *s;
int ret;
- if (!ads->user_name) {
- /* by default use the machine account */
- extern pstring global_myname;
- fstring myname;
- fstrcpy(myname, global_myname);
- strlower(myname);
- asprintf(&ads->user_name, "HOST/%s", global_myname);
- }
- asprintf(&s, "%s@%s", ads->user_name, ads->realm);
- ret = kerberos_kinit_password(s, ads->password);
+ asprintf(&s, "%s@%s", ads->auth.user_name, ads->auth.realm);
+ ret = kerberos_kinit_password(s, ads->auth.password);
if (ret) {
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c
index dac90908c45..22b58f47dd9 100644
--- a/source/libads/kerberos_verify.c
+++ b/source/libads/kerberos_verify.c
@@ -67,7 +67,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
return NT_STATUS_LOGON_FAILURE;
}
- ret = krb5_set_default_realm(context, ads->realm);
+ ret = krb5_set_default_realm(context, ads->auth.realm);
if (ret) {
DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret)));
ads_destroy(&ads);
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index 9d15c4e33cc..26724894829 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -37,6 +37,165 @@
* codepoints in UTF-8). This may have to change at some point
**/
+
+/*
+ try a connection to a given ldap server, returning True and setting the servers IP
+ in the ads struct if successful
+ */
+static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
+{
+ char *srv;
+
+ if (!server || !*server) {
+ return False;
+ }
+
+ DEBUG(5,("ads_try_connect: trying ldap server '%s' port %u\n", server, port));
+
+ /* this copes with inet_ntoa brokenness */
+ srv = strdup(server);
+
+ ads->ld = ldap_open(srv, port);
+ if (!ads->ld) {
+ free(srv);
+ return False;
+ }
+ ads->ldap_port = port;
+ ads->ldap_ip = *interpret_addr2(srv);
+ free(srv);
+ return True;
+}
+
+/* used by the IP comparison function */
+struct ldap_ip {
+ struct in_addr ip;
+ unsigned port;
+};
+
+/* compare 2 ldap IPs by nearness to our interfaces - used in qsort */
+static int ldap_ip_compare(struct ldap_ip *ip1, struct ldap_ip *ip2)
+{
+ return ip_compare(&ip1->ip, &ip2->ip);
+}
+
+/* try connecting to a ldap server via DNS */
+static BOOL ads_try_dns(ADS_STRUCT *ads)
+{
+ char *realm, *ptr;
+ char *list = NULL;
+ pstring tok;
+ struct ldap_ip *ip_list;
+ int count, i=0;
+
+ realm = ads->server.realm;
+ if (!realm || !*realm) {
+ realm = lp_realm();
+ }
+ if (!realm || !*realm) {
+ realm = ads->server.workgroup;
+ }
+ if (!realm || !*realm) {
+ realm = lp_workgroup();
+ }
+ if (!realm) {
+ return False;
+ }
+ realm = smb_xstrdup(realm);
+
+ DEBUG(6,("ads_try_dns: looking for realm '%s'\n", realm));
+ if (ldap_domain2hostlist(realm, &list) != LDAP_SUCCESS) {
+ SAFE_FREE(realm);
+ return False;
+ }
+
+ DEBUG(6,("ads_try_dns: ldap realm '%s' host list '%s'\n", realm, list));
+ SAFE_FREE(realm);
+
+ count = count_chars(list, ' ') + 1;
+ ip_list = malloc(count * sizeof(struct ldap_ip));
+ if (!ip_list) {
+ return False;
+ }
+
+ ptr = list;
+ while (next_token(&ptr, tok, " ", sizeof(tok))) {
+ unsigned port = LDAP_PORT;
+ char *p = strchr(tok, ':');
+ if (p) {
+ *p = 0;
+ port = atoi(p+1);
+ }
+ ip_list[i].ip = *interpret_addr2(tok);
+ ip_list[i].port = port;
+ if (!is_zero_ip(ip_list[i].ip)) {
+ i++;
+ }
+ }
+ free(list);
+
+ count = i;
+
+ /* we sort the list of addresses by closeness to our interfaces. This
+ tries to prevent us using a DC on the other side of the country */
+ if (count > 1) {
+ qsort(ip_list, count, sizeof(struct ldap_ip),
+ QSORT_CAST ldap_ip_compare);
+ }
+
+ for (i=0;i<count;i++) {
+ if (ads_try_connect(ads, inet_ntoa(ip_list[i].ip), ip_list[i].port)) {
+ free(ip_list);
+ return True;
+ }
+ }
+
+ SAFE_FREE(ip_list);
+ return False;
+}
+
+/* try connecting to a ldap server via netbios */
+static BOOL ads_try_netbios(ADS_STRUCT *ads)
+{
+ struct in_addr *ip_list;
+ int count;
+ int i;
+ char *workgroup = ads->server.workgroup;
+
+ if (!workgroup) {
+ workgroup = lp_workgroup();
+ }
+
+ DEBUG(6,("ads_try_netbios: looking for workgroup '%s'\n", workgroup));
+
+ /* try the PDC first */
+ if (get_dc_list(True, workgroup, &ip_list, &count)) {
+ for (i=0;i<count;i++) {
+ DEBUG(6,("ads_try_netbios: trying server '%s'\n",
+ inet_ntoa(ip_list[i])));
+ if (ads_try_connect(ads, inet_ntoa(ip_list[i]), LDAP_PORT)) {
+ free(ip_list);
+ return True;
+ }
+ }
+ free(ip_list);
+ }
+
+ /* now any DC, including backups */
+ if (get_dc_list(False, workgroup, &ip_list, &count)) {
+ for (i=0;i<count;i++) {
+ DEBUG(6,("ads_try_netbios: trying server '%s'\n",
+ inet_ntoa(ip_list[i])));
+ if (ads_try_connect(ads, inet_ntoa(ip_list[i]), LDAP_PORT)) {
+ free(ip_list);
+ return True;
+ }
+ }
+ free(ip_list);
+ }
+
+ return False;
+}
+
/**
* Connect to the LDAP server
* @param ads Pointer to an existing ADS_STRUCT
@@ -49,38 +208,35 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
ADS_STATUS status;
ads->last_attempt = time(NULL);
-
ads->ld = NULL;
- if (ads->ldap_server) {
- ads->ld = ldap_open(ads->ldap_server, ads->ldap_port);
+ /* try with a user specified server */
+ if (ads->server.ldap_server &&
+ ads_try_connect(ads, ads->server.ldap_server, LDAP_PORT)) {
+ goto got_connection;
}
- /* if that failed then try each of the BDC's in turn */
- if (!ads->ld) {
- struct in_addr *ip_list;
- int count;
-
- if (get_dc_list(False, ads->workgroup, &ip_list, &count)) {
- int i;
- for (i=0;i<count;i++) {
- ads->ld = ldap_open(inet_ntoa(ip_list[i]),
- ads->ldap_port);
- if (ads->ld) break;
- }
- if (ads->ld) {
- SAFE_FREE(ads->ldap_server);
- ads->ldap_server = strdup(inet_ntoa(ip_list[i]));
- }
- free(ip_list);
- }
+ /* try with a smb.conf ads server setting if we are connecting
+ to the primary workgroup or realm */
+ if (!ads->server.foreign &&
+ ads_try_connect(ads, lp_ads_server(), LDAP_PORT)) {
+ goto got_connection;
}
- if (!ads->ld) {
- return ADS_ERROR_SYSTEM(errno);
+ /* try via DNS */
+ if (ads_try_dns(ads)) {
+ goto got_connection;
+ }
+
+ /* try via netbios lookups */
+ if (!lp_disable_netbios() && ads_try_netbios(ads)) {
+ goto got_connection;
}
- DEBUG(3,("Connected to LDAP server %s\n", ads->ldap_server));
+ return ADS_ERROR_SYSTEM(errno?errno:ENOENT);
+
+got_connection:
+ DEBUG(3,("Connected to LDAP server %s\n", inet_ntoa(ads->ldap_ip)));
status = ads_server_info(ads);
if (!ADS_ERR_OK(status)) {
@@ -90,22 +246,43 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+ if (!ads->auth.user_name) {
+ /* by default use the machine account */
+ extern pstring global_myname;
+ fstring myname;
+ fstrcpy(myname, global_myname);
+ strlower(myname);
+ asprintf(&ads->auth.user_name, "HOST/%s", myname);
+ }
+
+ if (!ads->auth.realm) {
+ ads->auth.realm = strdup(ads->config.realm);
+ }
+
+ if (!ads->auth.kdc_server) {
+ ads->auth.kdc_server = strdup(inet_ntoa(ads->ldap_ip));
+ }
+
#if KRB5_DNS_HACK
/* this is a really nasty hack to avoid ADS DNS problems. It needs a patch
to MIT kerberos to work (tridge) */
{
char *env;
- asprintf(&env, "KRB5_KDC_ADDRESS_%s", ads->server_realm);
- setenv(env, inet_ntoa(*interpret_addr2(ads->ldap_server)), 1);
+ asprintf(&env, "KRB5_KDC_ADDRESS_%s", ads->config.realm);
+ setenv(env, ads->auth.kdc_server, 1);
free(env);
}
#endif
- if (ads->password) {
+ if (ads->auth.password) {
if ((code = ads_kinit_password(ads)))
return ADS_ERROR_KRB5(code);
}
+ if (ads->auth.no_bind) {
+ return ADS_SUCCESS;
+ }
+
return ads_sasl_bind(ads);
}
@@ -161,7 +338,7 @@ static char **ads_push_strvals(TALLOC_CTX *ctx, const char **in_vals)
if (!values) return NULL;
for (i=0; in_vals[i]; i++) {
- push_utf8_talloc(ctx, (void **) &values[i], in_vals[i]);
+ push_utf8_talloc(ctx, &values[i], in_vals[i]);
}
return values;
}
@@ -180,7 +357,7 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals)
if (!values) return NULL;
for (i=0; in_vals[i]; i++) {
- pull_utf8_talloc(ctx, (void **) &values[i], in_vals[i]);
+ pull_utf8_talloc(ctx, &values[i], in_vals[i]);
}
return values;
}
@@ -219,8 +396,8 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
/* 0 means the conversion worked but the result was empty
so we only fail if it's negative. In any case, it always
at least nulls out the dest */
- if ((push_utf8_talloc(ctx, (void **) &utf8_exp, exp) < 0) ||
- (push_utf8_talloc(ctx, (void **) &utf8_path, bind_path) < 0)) {
+ if ((push_utf8_talloc(ctx, &utf8_exp, exp) < 0) ||
+ (push_utf8_talloc(ctx, &utf8_path, bind_path) < 0)) {
rc = LDAP_NO_MEMORY;
goto done;
}
@@ -230,7 +407,7 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path,
else {
/* This would be the utf8-encoded version...*/
/* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */
- if (!(str_list_copy(&search_attrs, (char **) attrs)))
+ if (!(str_list_copy(&search_attrs, attrs)))
{
rc = LDAP_NO_MEMORY;
goto done;
@@ -442,8 +619,8 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
/* 0 means the conversion worked but the result was empty
so we only fail if it's negative. In any case, it always
at least nulls out the dest */
- if ((push_utf8_talloc(ctx, (void **) &utf8_exp, exp) < 0) ||
- (push_utf8_talloc(ctx, (void **) &utf8_path, bind_path) < 0)) {
+ if ((push_utf8_talloc(ctx, &utf8_exp, exp) < 0) ||
+ (push_utf8_talloc(ctx, &utf8_path, bind_path) < 0)) {
rc = LDAP_NO_MEMORY;
goto done;
}
@@ -453,7 +630,7 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
else {
/* This would be the utf8-encoded version...*/
/* if (!(search_attrs = ads_push_strvals(ctx, attrs))) */
- if (!(str_list_copy(&search_attrs, (char **) attrs)))
+ if (!(str_list_copy(&search_attrs, attrs)))
{
rc = LDAP_NO_MEMORY;
goto done;
@@ -494,7 +671,7 @@ ADS_STATUS ads_search(ADS_STRUCT *ads, void **res,
const char *exp,
const char **attrs)
{
- return ads_do_search(ads, ads->bind_path, LDAP_SCOPE_SUBTREE,
+ return ads_do_search(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
exp, attrs, res);
}
@@ -805,11 +982,11 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
if (!(host_spn = talloc_asprintf(ctx, "HOST/%s", hostname)))
goto done;
- if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->realm)))
+ if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm)))
goto done;
ou_str = ads_ou_string(org_unit);
new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", hostname, ou_str,
- ads->bind_path);
+ ads->config.bind_path);
free(ou_str);
if (!new_dn)
goto done;
@@ -925,6 +1102,7 @@ static BOOL ads_dump_field(char *field, void **values, void *data_area)
} handlers[] = {
{"objectGUID", False, dump_binary},
{"nTSecurityDescriptor", False, dump_sd},
+ {"dnsRecord", False, dump_binary},
{"objectSid", False, dump_sid},
{NULL, True, NULL}
};
@@ -999,7 +1177,7 @@ void ads_process_results(ADS_STRUCT *ads, void *res,
char *field;
BOOL string;
- pull_utf8_talloc(ctx, (void **) &field, utf8_field);
+ pull_utf8_talloc(ctx, &field, utf8_field);
string = fn(field, NULL, data_area);
if (string) {
@@ -1061,7 +1239,7 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, const char *org
status = ads_leave_realm(ads, host);
if (!ADS_ERR_OK(status)) {
DEBUG(0, ("Failed to delete host '%s' from the '%s' realm.\n",
- host, ads->realm));
+ host, ads->config.realm));
return status;
}
}
@@ -1224,20 +1402,15 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
char *host = strdup(hostname);
char *principal;
- if (!ads->kdc_server) {
- DEBUG(0, ("Unable to find KDC server\n"));
- return ADS_ERROR(LDAP_SERVER_DOWN);
- }
-
strlower(host);
/*
we need to use the '$' form of the name here, as otherwise the
server might end up setting the password for a user instead
*/
- asprintf(&principal, "%s$@%s", host, ads->realm);
+ asprintf(&principal, "%s$@%s", host, ads->auth.realm);
- status = krb5_set_password(ads->kdc_server, principal, password);
+ status = krb5_set_password(ads->auth.kdc_server, principal, password);
free(host);
free(principal);
@@ -1287,7 +1460,7 @@ char *ads_pull_string(ADS_STRUCT *ads,
if (!values) return NULL;
if (values[0]) {
- rc = pull_utf8_talloc(mem_ctx, (void **)&ux_string,
+ rc = pull_utf8_talloc(mem_ctx, &ux_string,
values[0]);
if (rc != -1)
ret = ux_string;
@@ -1321,7 +1494,7 @@ char **ads_pull_strings(ADS_STRUCT *ads,
ret = talloc(mem_ctx, sizeof(char *) * (n+1));
for (i=0;i<n;i++) {
- if (pull_utf8_talloc(mem_ctx, (void **)&ret[i], values[i]) == -1) {
+ if (pull_utf8_talloc(mem_ctx, &ret[i], values[i]) == -1) {
return NULL;
}
}
@@ -1472,33 +1645,27 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
return ADS_ERROR(LDAP_DECODING_ERROR);
}
- SAFE_FREE(ads->ldap_server_name);
+ SAFE_FREE(ads->config.ldap_server_name);
- ads->ldap_server_name = strdup(p+1);
- p = strchr(ads->ldap_server_name, '$');
+ ads->config.ldap_server_name = strdup(p+1);
+ p = strchr(ads->config.ldap_server_name, '$');
if (!p || p[1] != '@') {
ldap_value_free(values);
ldap_msgfree(res);
- SAFE_FREE(ads->ldap_server_name);
+ SAFE_FREE(ads->config.ldap_server_name);
return ADS_ERROR(LDAP_DECODING_ERROR);
}
*p = 0;
- SAFE_FREE(ads->server_realm);
- SAFE_FREE(ads->bind_path);
+ SAFE_FREE(ads->config.realm);
+ SAFE_FREE(ads->config.bind_path);
- ads->server_realm = strdup(p+2);
- ads->bind_path = ads_build_dn(ads->server_realm);
-
- /* in case the realm isn't configured in smb.conf */
- if (!ads->realm || !ads->realm[0]) {
- SAFE_FREE(ads->realm);
- ads->realm = strdup(ads->server_realm);
- }
+ ads->config.realm = strdup(p+2);
+ ads->config.bind_path = ads_build_dn(ads->config.realm);
DEBUG(3,("got ldap server name %s@%s\n",
- ads->ldap_server_name, ads->realm));
+ ads->config.ldap_server_name, ads->config.realm));
return ADS_SUCCESS;
}
@@ -1514,9 +1681,13 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
* @return the count of SIDs pulled
**/
ADS_STATUS ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
- int *num_trusts, char ***names, DOM_SID **sids)
+ int *num_trusts,
+ char ***names,
+ char ***alt_names,
+ DOM_SID **sids)
{
- const char *attrs[] = {"flatName", "securityIdentifier", NULL};
+ const char *attrs[] = {"name", "flatname", "securityIdentifier",
+ "trustDirection", NULL};
ADS_STATUS status;
void *res, *msg;
int count, i;
@@ -1533,11 +1704,31 @@ ADS_STATUS ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
}
(*names) = talloc(mem_ctx, sizeof(char *) * count);
+ (*alt_names) = talloc(mem_ctx, sizeof(char *) * count);
(*sids) = talloc(mem_ctx, sizeof(DOM_SID) * count);
if (! *names || ! *sids) return ADS_ERROR(LDAP_NO_MEMORY);
for (i=0, msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
- (*names)[i] = ads_pull_string(ads, mem_ctx, msg, "flatName");
+ uint32 direction;
+
+ /* direction is a 2 bit bitfield, 1 means they trust us
+ but we don't trust them, so we should not list them
+ as users from that domain can't login */
+ if (ads_pull_uint32(ads, msg, "trustDirection", &direction) &&
+ direction == 1) {
+ continue;
+ }
+
+ (*names)[i] = ads_pull_string(ads, mem_ctx, msg, "name");
+ (*alt_names)[i] = ads_pull_string(ads, mem_ctx, msg, "flatname");
+
+ if ((*alt_names)[i] && (*alt_names)[i][0]) {
+ /* we prefer the flatname as the primary name
+ for consistency with RPC */
+ char *name = (*alt_names)[i];
+ (*alt_names)[i] = (*names)[i];
+ (*names)[i] = name;
+ }
if (ads_pull_sid(ads, msg, "securityIdentifier", &(*sids)[i])) {
i++;
}
@@ -1562,7 +1753,7 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
void *res;
ADS_STATUS rc;
- rc = ads_do_search(ads, ads->bind_path, LDAP_SCOPE_BASE, "(objectclass=*)",
+ rc = ads_do_search(ads, ads->config.bind_path, LDAP_SCOPE_BASE, "(objectclass=*)",
attrs, &res);
if (!ADS_ERR_OK(rc)) return rc;
if (!ads_pull_sid(ads, res, "objectSid", sid)) {
@@ -1573,4 +1764,66 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid)
return ADS_SUCCESS;
}
+/* this is rather complex - we need to find the allternate (netbios) name
+ for the domain, but there isn't a simple query to do this. Instead
+ we look for the principle names on the DCs account and find one that has
+ the right form, then extract the netbios name of the domain from that
+*/
+ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **workgroup)
+{
+ char *exp;
+ ADS_STATUS rc;
+ char **principles;
+ char *prefix;
+ int prefix_length;
+ int i;
+ void *res;
+ const char *attrs[] = {"servicePrincipalName", NULL};
+
+ (*workgroup) = NULL;
+
+ asprintf(&exp, "(&(objectclass=computer)(dnshostname=%s.%s))",
+ ads->config.ldap_server_name, ads->config.realm);
+ rc = ads_search(ads, &res, exp, attrs);
+ free(exp);
+
+ if (!ADS_ERR_OK(rc)) {
+ return rc;
+ }
+
+ principles = ads_pull_strings(ads, mem_ctx, res, "servicePrincipalName");
+
+ ads_msgfree(ads, res);
+
+ if (!principles) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ asprintf(&prefix, "HOST/%s.%s/",
+ ads->config.ldap_server_name,
+ ads->config.realm);
+
+ prefix_length = strlen(prefix);
+
+ for (i=0;principles[i]; i++) {
+ if (strncasecmp(principles[i], prefix, prefix_length) == 0 &&
+ strcasecmp(ads->config.realm, principles[i]+prefix_length) != 0 &&
+ !strchr(principles[i]+prefix_length, '.')) {
+ /* found an alternate (short) name for the domain. */
+ DEBUG(3,("Found alternate name '%s' for realm '%s'\n",
+ principles[i]+prefix_length,
+ ads->config.realm));
+ (*workgroup) = talloc_strdup(mem_ctx, principles[i]+prefix_length);
+ break;
+ }
+ }
+ free(prefix);
+
+ if (!*workgroup) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ return ADS_SUCCESS;
+}
+
#endif
diff --git a/source/libads/ldap_user.c b/source/libads/ldap_user.c
index b6e3d189c51..b6fef24b5c1 100644
--- a/source/libads/ldap_user.c
+++ b/source/libads/ldap_user.c
@@ -55,10 +55,10 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user,
status = ADS_ERROR(LDAP_NO_MEMORY);
- if (!(upn = talloc_asprintf(ctx, "%s@%s", user, ads->realm)))
+ if (!(upn = talloc_asprintf(ctx, "%s@%s", user, ads->config.realm)))
goto done;
if (!(new_dn = talloc_asprintf(ctx, "cn=%s,cn=Users,%s", name,
- ads->bind_path)))
+ ads->config.bind_path)))
goto done;
if (!(controlstr = talloc_asprintf(ctx, "%u", UF_NORMAL_ACCOUNT)))
goto done;
@@ -94,7 +94,7 @@ ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group,
status = ADS_ERROR(LDAP_NO_MEMORY);
if (!(new_dn = talloc_asprintf(ctx, "cn=%s,cn=Users,%s", group,
- ads->bind_path)))
+ ads->config.bind_path)))
goto done;
if (!(mods = ads_init_mods(ctx)))
goto done;
diff --git a/source/libads/sasl.c b/source/libads/sasl.c
index 1b55453cac9..81dedb0a81e 100644
--- a/source/libads/sasl.c
+++ b/source/libads/sasl.c
@@ -77,7 +77,7 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
/* we need to fetch a service ticket as the ldap user in the
servers realm, regardless of our realm */
- asprintf(&sname, "ldap/%s@%s", ads->ldap_server_name, ads->server_realm);
+ asprintf(&sname, "ldap/%s@%s", ads->config.ldap_server_name, ads->config.realm);
krb5_init_context(&ctx);
krb5_set_default_tgs_ktypes(ctx, enc_types);
krb5_parse_name(ctx, sname, &principal);
@@ -163,7 +163,7 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
gss_release_buffer(&minor_status, &output_token);
- output_token.value = malloc(strlen(ads->bind_path) + 8);
+ output_token.value = malloc(strlen(ads->config.bind_path) + 8);
p = output_token.value;
*p++ = 1; /* no sign or seal */
@@ -171,9 +171,10 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
*p++ = max_msg_size>>16;
*p++ = max_msg_size>>8;
*p++ = max_msg_size;
- snprintf(p, strlen(ads->bind_path)+4, "dn:%s", ads->bind_path);
+ snprintf(p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path);
+ p += strlen(ads->config.bind_path);
- output_token.length = strlen(ads->bind_path) + 8;
+ output_token.length = strlen(ads->config.bind_path) + 8;
gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
&output_token, &conf_state,
diff --git a/source/libads/util.c b/source/libads/util.c
index d48eb10b710..b10b130a313 100644
--- a/source/libads/util.c
+++ b/source/libads/util.c
@@ -39,7 +39,7 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
new_password = strdup(tmp_password);
asprintf(&service_principal, "HOST/%s", host_principal);
- ret = kerberos_set_password(ads->kdc_server, host_principal, password,
+ ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password,
service_principal, new_password);
if (!secrets_store_machine_password(new_password)) {
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 472db69fd0d..93cf3d95db7 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -54,9 +54,6 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
return False;
}
- /* Lanman2 cannot use SMB signing. */
- cli->sign_info.use_smb_signing = False;
-
/* if in share level security then don't send a password now */
if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
passlen = 0;
@@ -209,12 +206,11 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
SSVAL(cli->outbuf,smb_vwv3,2);
SSVAL(cli->outbuf,smb_vwv4,cli->pid);
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
- SSVAL(cli->outbuf,smb_vwv7,passlen);
SSVAL(cli->outbuf,smb_vwv8,0);
SIVAL(cli->outbuf,smb_vwv11,capabilities);
p = smb_buf(cli->outbuf);
- memcpy(p, pword, passlen);
- p += passlen;
+ p += clistr_push(cli, p, pword, -1, STR_TERMINATE); /* password */
+ SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
@@ -257,11 +253,12 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
char *workgroup)
{
uint32 capabilities = cli_session_setup_capabilities(cli);
- fstring pword, ntpword;
+ uchar pword[24];
+ uchar ntpword[24];
char *p;
BOOL tried_signing = False;
- if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
+ if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword)) {
return False;
}
@@ -269,15 +266,21 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
/* non encrypted password supplied. Ignore ntpass. */
passlen = 24;
ntpasslen = 24;
- SMBencrypt((uchar *)pass,cli->secblob.data,(uchar *)pword);
- SMBNTencrypt((uchar *)pass,cli->secblob.data,(uchar *)ntpword);
+ SMBencrypt(pass,cli->secblob.data,pword);
+ SMBNTencrypt(pass,cli->secblob.data,ntpword);
if (!cli->sign_info.use_smb_signing && cli->sign_info.negotiated_smb_signing) {
- cli_calculate_mac_key(cli, (uchar *)pass, (uchar *)ntpword);
+ cli_calculate_mac_key(cli, pass, ntpword);
tried_signing = True;
}
} else {
- memcpy(pword, pass, passlen);
- memcpy(ntpword, ntpass, ntpasslen);
+ /* pre-encrypted password supplied. Only used for security=server, can't do
+ signing becouse we don't have oringial key */
+ memcpy(pword, pass, 24);
+ if (ntpasslen == 24) {
+ memcpy(ntpword, ntpass, 24);
+ } else {
+ ZERO_STRUCT(ntpword);
+ }
}
/* send a session setup command */
@@ -305,8 +308,13 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
cli_setup_bcc(cli, p);
cli_send_smb(cli);
- if (!cli_receive_smb(cli))
+ if (!cli_receive_smb(cli)) {
+ if (tried_signing) {
+ /* We only use it if we have a successful non-guest connect */
+ cli->sign_info.use_smb_signing = False;
+ }
return False;
+ }
show_msg(cli->inbuf);
@@ -482,8 +490,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
/* encrypt the password with the challenge */
memcpy(challenge, chal1.data + 24, 8);
- SMBencrypt((unsigned char *)pass, challenge,lmhash);
- SMBNTencrypt((unsigned char *)pass, challenge,nthash);
+ SMBencrypt(pass, challenge,lmhash);
+ SMBNTencrypt(pass, challenge,nthash);
#if 0
file_save("nthash.dat", nthash, 24);
@@ -1062,7 +1070,7 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
}
if (cli->fd == -1) {
DEBUG(1,("Error connecting to %s (%s)\n",
- inet_ntoa(*ip),strerror(errno)));
+ ip?inet_ntoa(*ip):host,strerror(errno)));
return False;
}
@@ -1182,9 +1190,8 @@ again:
if (!cli_session_setup(cli, user, password, strlen(password)+1,
password, strlen(password)+1,
domain)) {
- if (!(flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
- || cli_session_setup(cli, "", "", 0,
- "", 0, domain)) {
+ if ((flags & CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK)
+ && cli_session_setup(cli, "", "", 0, "", 0, domain)) {
} else {
nt_status = cli_nt_error(cli);
DEBUG(1,("failed session setup with %s\n", nt_errstr(nt_status)));
diff --git a/source/libsmb/clispnego.c b/source/libsmb/clispnego.c
index 469b946088c..16702c375b2 100644
--- a/source/libsmb/clispnego.c
+++ b/source/libsmb/clispnego.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
simple kerberos5/SPNEGO routines
Copyright (C) Andrew Tridgell 2001
+ Copyright (C) Jim McDonough 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
@@ -439,6 +440,28 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
return True;
}
+/*
+ generate a minimal SPNEGO NTLMSSP response packet. Doesn't contain much.
+*/
+DATA_BLOB spnego_gen_auth_response(void)
+{
+ ASN1_DATA data;
+ DATA_BLOB ret;
+
+ memset(&data, 0, sizeof(data));
+
+ asn1_push_tag(&data, ASN1_CONTEXT(1));
+ asn1_push_tag(&data, ASN1_SEQUENCE(0));
+ asn1_push_tag(&data, ASN1_CONTEXT(0));
+ asn1_write_enumerated(&data, 0);
+ asn1_pop_tag(&data);
+ asn1_pop_tag(&data);
+ asn1_pop_tag(&data);
+
+ ret = data_blob(data.data, data.length);
+ asn1_free(&data);
+ return ret;
+}
/*
this is a tiny msrpc packet generator. I am only using this to
@@ -449,6 +472,7 @@ BOOL spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
format specifiers are:
U = unicode string (input is unix string)
+ a = address (1 byte type, 1 byte length, unicode string, all inline)
B = data blob (pointer + length)
b = data blob in header (pointer + length)
d = word (4 bytes)
@@ -473,6 +497,11 @@ BOOL msrpc_gen(DATA_BLOB *blob,
head_size += 8;
data_size += str_charnum(s) * 2;
break;
+ case 'a':
+ n = va_arg(ap, int);
+ s = va_arg(ap, char *);
+ data_size += (str_charnum(s) * 2) + 4;
+ break;
case 'B':
b = va_arg(ap, uint8 *);
head_size += 8;
@@ -512,6 +541,19 @@ BOOL msrpc_gen(DATA_BLOB *blob,
push_string(NULL, blob->data+data_ofs, s, n*2, STR_UNICODE|STR_NOALIGN);
data_ofs += n*2;
break;
+ case 'a':
+ n = va_arg(ap, int);
+ SSVAL(blob->data, data_ofs, n); data_ofs += 2;
+ s = va_arg(ap, char *);
+ n = str_charnum(s);
+ SSVAL(blob->data, data_ofs, n*2); data_ofs += 2;
+ if (0 < n) {
+ push_string(NULL, blob->data+data_ofs, s, n*2,
+ STR_UNICODE|STR_NOALIGN);
+ }
+ data_ofs += n*2;
+ break;
+
case 'B':
b = va_arg(ap, uint8 *);
n = va_arg(ap, int);
@@ -550,6 +592,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
format specifiers are:
U = unicode string (output is unix string)
+ A = ascii string
B = data blob
b = data blob in header
d = word (4 bytes)
@@ -584,6 +627,24 @@ BOOL msrpc_parse(DATA_BLOB *blob,
STR_UNICODE|STR_NOALIGN);
(*ps) = strdup(p);
break;
+ case 'A':
+ len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
+ ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
+
+ /* make sure its in the right format - be strict */
+ if (len1 != len2 || ptr + len1 > blob->length) {
+ return False;
+ }
+ ps = va_arg(ap, char **);
+ if (0 < len1) {
+ pull_string(NULL, p, blob->data + ptr, -1,
+ len1, STR_ASCII|STR_NOALIGN);
+ (*ps) = strdup(p);
+ } else {
+ (*ps) = NULL;
+ }
+ break;
case 'B':
len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c
index 18564bccf43..40a353fa8b6 100644
--- a/source/libsmb/namequery.c
+++ b/source/libsmb/namequery.c
@@ -170,6 +170,11 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t
int sock;
BOOL result = False;
+ if (lp_disable_netbios()) {
+ DEBUG(5,("name_status_find(%s#%02x): netbios is disabled\n", q_name, q_type));
+ return False;
+ }
+
DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name,
q_type, inet_ntoa(to_ip)));
@@ -191,7 +196,7 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t
if (i == count)
goto done;
- pull_ascii(name, status[i].name, 15, -1, STR_TERMINATE);
+ pull_ascii(name, status[i].name, 16, 15, STR_TERMINATE);
result = True;
done:
@@ -211,7 +216,7 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t
/*
comparison function used by sort_ip_list
*/
-static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
+int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
{
int max_bits1=0, max_bits2=0;
int num_interfaces = iface_count();
@@ -273,6 +278,11 @@ struct in_addr *name_query(int fd,const char *name,int name_type,
struct nmb_packet *nmb = &p.packet.nmb;
struct in_addr *ip_list = NULL;
+ if (lp_disable_netbios()) {
+ DEBUG(5,("name_query(%s#%02x): netbios is disabled\n", name, name_type));
+ return NULL;
+ }
+
if (timed_out) {
*timed_out = False;
}
@@ -556,6 +566,11 @@ BOOL name_resolve_bcast(const char *name, int name_type,
int sock, i;
int num_interfaces = iface_count();
+ if (lp_disable_netbios()) {
+ DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type));
+ return False;
+ }
+
*return_ip_list = NULL;
*return_count = 0;
@@ -602,6 +617,11 @@ BOOL resolve_wins(const char *name, int name_type,
char **wins_tags;
struct in_addr src_ip;
+ if (lp_disable_netbios()) {
+ DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type));
+ return False;
+ }
+
*return_iplist = NULL;
*return_count = 0;
@@ -763,7 +783,7 @@ static BOOL resolve_hosts(const char *name,
*********************************************************/
static BOOL internal_resolve_name(const char *name, int name_type,
- struct in_addr **return_iplist, int *return_count)
+ struct in_addr **return_iplist, int *return_count)
{
pstring name_resolve_list;
fstring tok;
@@ -796,6 +816,15 @@ static BOOL internal_resolve_name(const char *name, int name_type,
return True;
}
+ /* Check netbios name cache */
+
+ if (namecache_fetch(name, name_type, return_iplist, return_count)) {
+
+ /* This could be a negative response */
+
+ return (*return_count > 0);
+ }
+
pstrcpy(name_resolve_list, lp_name_resolve_order());
ptr = name_resolve_list;
if (!ptr || !*ptr)
@@ -803,9 +832,16 @@ static BOOL internal_resolve_name(const char *name, int name_type,
while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
if((strequal(tok, "host") || strequal(tok, "hosts"))) {
- if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
- result = True;
- goto done;
+ if (name_type == 0x20) {
+ if (resolve_hosts(name, return_iplist, return_count)) {
+ result = True;
+ goto done;
+ } else {
+
+ /* Store negative lookup result */
+
+ namecache_store(name, name_type, 0, NULL);
+ }
}
} else if(strequal( tok, "lmhosts")) {
if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
@@ -877,6 +913,10 @@ static BOOL internal_resolve_name(const char *name, int name_type,
*return_iplist = nodupes_iplist;
*return_count = nodupes_count;
}
+
+ /* Save in name cache */
+
+ namecache_store(name, name_type, *return_count, *return_iplist);
/* Display some debugging info */
@@ -930,11 +970,16 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
Find the IP address of the master browser or DMB for a workgroup.
*********************************************************/
-BOOL find_master_ip(char *group, struct in_addr *master_ip)
+BOOL find_master_ip(const char *group, struct in_addr *master_ip)
{
struct in_addr *ip_list = NULL;
int count = 0;
+ if (lp_disable_netbios()) {
+ DEBUG(5,("find_master_ip(%s): netbios is disabled\n", group));
+ return False;
+ }
+
if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
*master_ip = ip_list[0];
SAFE_FREE(ip_list);
@@ -957,10 +1002,14 @@ BOOL find_master_ip(char *group, struct in_addr *master_ip)
BOOL lookup_dc_name(const char *srcname, const char *domain,
struct in_addr *dc_ip, char *ret_name)
{
-#if !defined(I_HATE_WINDOWS_REPLY_CODE)
-
+#if !defined(I_HATE_WINDOWS_REPLY_CODE)
fstring dc_name;
BOOL ret;
+
+ if (lp_disable_netbios()) {
+ DEBUG(5,("lookup_dc_name(%s): netbios is disabled\n", domain));
+ return False;
+ }
/*
* Due to the fact win WinNT *sucks* we must do a node status
diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c
index 95434d0ae4e..dfa355a7ec6 100644
--- a/source/libsmb/smbencrypt.c
+++ b/source/libsmb/smbencrypt.c
@@ -28,7 +28,7 @@
This implements the X/Open SMB password encryption
It takes a password ('unix' string), a 8 byte "crypt key"
and puts 24 bytes of encrypted password into p24 */
-void SMBencrypt(const char *passwd, const uchar *c8, uchar *p24)
+void SMBencrypt(const char *passwd, const uchar *c8, uchar p24[24])
{
uchar p21[21];
@@ -66,9 +66,9 @@ void E_md4hash(const char *passwd, uchar p16[16])
}
/**
- * Creates the MD4 Hash of the users password in NT UNICODE.
+ * Creates the DES forward-only Hash of the users password in DOS ASCII charset
* @param passwd password in 'unix' charset.
- * @param p16 return password hashed with md4, caller allocated 16 byte buffer
+ * @param p16 return password hashed with DES, caller allocated 16 byte buffer
*/
void E_deshash(const char *passwd, uchar p16[16])
@@ -77,7 +77,7 @@ void E_deshash(const char *passwd, uchar p16[16])
ZERO_STRUCT(dospwd);
ZERO_STRUCTP(p16);
- /* Password must be converted to DOS charset - null terminated. */
+ /* Password must be converted to DOS charset - null terminated, uppercase. */
push_ascii(dospwd, (const char *)passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE);
E_P16(dospwd, p16);
@@ -175,7 +175,7 @@ void NTLMSSPOWFencrypt(const uchar passwd[8], const uchar *ntlmchalresp, uchar p
/* Does the NT MD4 hash then des encryption. */
-void SMBNTencrypt(const uchar *passwd, uchar *c8, uchar *p24)
+void SMBNTencrypt(const char *passwd, uchar *c8, uchar *p24)
{
uchar p21[21];
@@ -226,14 +226,14 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[
void SMBOWFencrypt_ntv2(const uchar kr[16],
const DATA_BLOB srv_chal,
const DATA_BLOB cli_chal,
- char resp_buf[16])
+ uchar resp_buf[16])
{
HMACMD5Context ctx;
hmac_md5_init_limK_to_64(kr, 16, &ctx);
hmac_md5_update(srv_chal.data, srv_chal.length, &ctx);
hmac_md5_update(cli_chal.data, cli_chal.length, &ctx);
- hmac_md5_final((unsigned char *)resp_buf, &ctx);
+ hmac_md5_final(resp_buf, &ctx);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
@@ -337,7 +337,7 @@ BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
SMB signing - setup the MAC key.
************************************************************/
-void cli_calculate_mac_key(struct cli_state *cli, const unsigned char *ntpasswd, const uchar resp[24])
+void cli_calculate_mac_key(struct cli_state *cli, const char *ntpasswd, const uchar resp[24])
{
/* Get first 16 bytes. */
E_md4hash(ntpasswd,&cli->sign_info.mac_key[0]);
diff --git a/source/libsmb/trust_passwd.c b/source/libsmb/trust_passwd.c
index 3b77f7330eb..fe6b673e39e 100644
--- a/source/libsmb/trust_passwd.c
+++ b/source/libsmb/trust_passwd.c
@@ -35,7 +35,7 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
unsigned char new_trust_passwd_hash[16])
{
NTSTATUS result;
- result = new_cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
+ result = cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
SEC_CHAN_WKSTA : SEC_CHAN_BDC, orig_trust_passwd_hash);
if (!NT_STATUS_IS_OK(result)) {
diff --git a/source/nmbd/asyncdns.c b/source/nmbd/asyncdns.c
index 6c2f8de3b18..c86ee69a097 100644
--- a/source/nmbd/asyncdns.c
+++ b/source/nmbd/asyncdns.c
@@ -122,6 +122,7 @@ void kill_async_dns_child(void)
{
if (child_pid > 0) {
kill(child_pid, SIGTERM);
+ child_pid = -1;
}
}
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index d30efb550ce..05ea4997d5f 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -269,9 +269,8 @@ static BOOL reload_interfaces(time_t t)
static BOOL reload_nmbd_services(BOOL test)
{
BOOL ret;
- extern fstring remote_machine;
- fstrcpy( remote_machine, "nmbd" );
+ set_remote_machine_name("nmbd");
if ( lp_loaded() ) {
pstring fname;
@@ -861,8 +860,10 @@ static void usage(char *pname)
DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
- if ( !open_sockets( is_daemon, global_nmb_port ) )
+ if ( !open_sockets( is_daemon, global_nmb_port ) ) {
+ kill_async_dns_child();
return 1;
+ }
/* Determine all the IP addresses we have. */
load_interfaces();
@@ -871,6 +872,7 @@ static void usage(char *pname)
if( False == create_subnets() )
{
DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
+ kill_async_dns_child();
exit(1);
}
@@ -882,6 +884,7 @@ static void usage(char *pname)
if( !initialise_wins() )
{
DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
+ kill_async_dns_child();
exit(1);
}
@@ -896,6 +899,7 @@ static void usage(char *pname)
if( False == register_my_workgroup_and_names() )
{
DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
+ kill_async_dns_child();
exit(1);
}
@@ -906,5 +910,6 @@ static void usage(char *pname)
if (dbf)
x_fclose(dbf);
+ kill_async_dns_child();
return(0);
}
diff --git a/source/nmbd/nmbd_become_dmb.c b/source/nmbd/nmbd_become_dmb.c
index 7f4a7a21447..ccc1f7e8ada 100644
--- a/source/nmbd/nmbd_become_dmb.c
+++ b/source/nmbd/nmbd_become_dmb.c
@@ -347,7 +347,7 @@ static void become_domain_master_browser_wins(char *workgroup_name)
we can become a domain master browser.
*/
- DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
+ DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \
for domain master browser name %s on workgroup %s\n",
inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
diff --git a/source/nmbd/nmbd_mynames.c b/source/nmbd/nmbd_mynames.c
index 345245c57d0..ba7d509a77f 100644
--- a/source/nmbd/nmbd_mynames.c
+++ b/source/nmbd/nmbd_mynames.c
@@ -225,7 +225,7 @@ void refresh_my_names(time_t t)
wins_refresh_name(namerec);
}
namerec->data.death_time = t + lp_max_ttl();
- namerec->data.refresh_time = t + MIN(lp_max_ttl(), MAX_REFRESH_TIME);
+ namerec->data.refresh_time = t + MIN(lp_max_ttl()/2, MAX_REFRESH_TIME);
}
}
}
diff --git a/source/nmbd/nmbd_nameregister.c b/source/nmbd/nmbd_nameregister.c
index 4ac5473d4ae..b6d3c20d995 100644
--- a/source/nmbd/nmbd_nameregister.c
+++ b/source/nmbd/nmbd_nameregister.c
@@ -106,17 +106,7 @@ static void register_name_response(struct subnet_record *subrec,
success = False;
} else {
/* Unicast - check to see if the response allows us to have the name. */
- if(nmb->header.rcode != 0) {
- /* Error code - we didn't get the name. */
- success = False;
-
- DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n",
- subrec==unicast_subnet?"WINS ":"",
- inet_ntoa(p->ip),
- nmb_namestr(answer_name),
- reg_name,
- nmb->header.rcode));
- } else if (nmb->header.opcode == NMB_WACK_OPCODE) {
+ if (nmb->header.opcode == NMB_WACK_OPCODE) {
/* WINS server is telling us to wait. Pretend we didn't get
the response but don't send out any more register requests. */
@@ -128,6 +118,16 @@ static void register_name_response(struct subnet_record *subrec,
rrec->repeat_time = p->timestamp + nmb->answers->ttl;
rrec->num_msgs--;
return;
+ } else if (nmb->header.rcode != 0) {
+ /* Error code - we didn't get the name. */
+ success = False;
+
+ DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n",
+ subrec==unicast_subnet?"WINS ":"",
+ inet_ntoa(p->ip),
+ nmb_namestr(answer_name),
+ reg_name,
+ nmb->header.rcode));
} else {
success = True;
/* Get the data we need to pass to the success function. */
diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c
index a20ebf16fde..d252b98ed69 100644
--- a/source/nmbd/nmbd_packets.c
+++ b/source/nmbd/nmbd_packets.c
@@ -705,14 +705,33 @@ struct response_record *queue_query_name( struct subnet_record *subrec,
{
struct packet_struct *p;
struct response_record *rrec;
+ struct in_addr to_ip;
if(assert_check_subnet(subrec))
return NULL;
+ to_ip = subrec->bcast_ip;
+
+ /* queries to the WINS server turn up here as queries to IP 0.0.0.0
+ These need to be handled a bit differently */
+ if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) {
+ /* what we really need to do is loop over each of our wins
+ * servers and wins server tags here, but that just doesn't
+ * fit our architecture at the moment (userdata may already
+ * be used when we get here). For now we just query the first
+ * active wins server on the first tag. */
+ char **tags = wins_srv_tags();
+ if (!tags) {
+ return NULL;
+ }
+ to_ip = wins_srv_ip_tag(tags[0], to_ip);
+ wins_srv_tags_free(tags);
+ }
+
if(( p = create_and_init_netbios_packet(nmbname,
(subrec != unicast_subnet),
(subrec == unicast_subnet),
- subrec->bcast_ip)) == NULL)
+ to_ip)) == NULL)
return NULL;
if(lp_bind_interfaces_only()) {
@@ -1670,7 +1689,7 @@ void retransmit_or_expire_response_records(time_t t)
to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip),
subrec->subnet_name));
}
- rrec->repeat_time += rrec->repeat_interval;
+ rrec->repeat_time = t + rrec->repeat_interval;
rrec->repeat_count--;
}
else
@@ -1950,7 +1969,7 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len,
/* Setup the smb part. */
ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
memcpy(tmp,ptr,4);
- set_message(ptr,17,17 + len,True);
+ set_message(ptr,17,23 + len,True);
memcpy(ptr,tmp,4);
SCVAL(ptr,smb_com,SMBtrans);
diff --git a/source/nmbd/nmbd_processlogon.c b/source/nmbd/nmbd_processlogon.c
index 23e4f935cab..d6605d08f56 100644
--- a/source/nmbd/nmbd_processlogon.c
+++ b/source/nmbd/nmbd_processlogon.c
@@ -4,6 +4,8 @@
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Luke Kenneth Casson Leighton 1994-1998
Copyright (C) Jeremy Allison 1994-1998
+ Copyright (C) Jim McDonough 2002
+ Copyright (C) Anthony Liguori 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
@@ -284,19 +286,108 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
/* Construct reply. */
q = outbuf;
- if (SVAL(uniuser, 0) == 0) {
- SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */
- } else {
- SSVAL(q, 0, SAMLOGON_R);
- }
- q += 2;
-
- q += dos_PutUniCode(q, reply_name,sizeof(pstring), True);
- q += dos_PutUniCode(q, ascuser, sizeof(pstring), True);
- q += dos_PutUniCode(q, global_myworkgroup,sizeof(pstring), True);
+ /* we want the simple version unless we are an ADS PDC..which means */
+ /* never, at least for now */
+ if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) {
+ if (SVAL(uniuser, 0) == 0) {
+ SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */
+ } else {
+ SSVAL(q, 0, SAMLOGON_R);
+ }
+
+ q += 2;
+
+ q += dos_PutUniCode(q, reply_name,sizeof(pstring), True);
+ q += dos_PutUniCode(q, ascuser, sizeof(pstring), True);
+ q += dos_PutUniCode(q, global_myworkgroup,sizeof(pstring), True);
+ }
+#ifdef HAVE_ADS
+ else {
+ GUID domain_guid;
+ pstring domain;
+ char *component, *dc, *q1;
+ uint8 size;
+
+ safe_strcpy(domain, lp_realm(), sizeof(domain));
+
+ if (SVAL(uniuser, 0) == 0) {
+ SSVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */
+ } else {
+ SSVAL(q, 0, SAMLOGON_AD_R);
+ }
+ q += 2;
+
+ SSVAL(q, 0, 0);
+ q += 2;
+ SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS|
+ ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE);
+ q += 4;
+
+ /* Push Domain GUID */
+ if (False == secrets_fetch_domain_guid(domain, &domain_guid)) {
+ DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain));
+ return;
+ }
+ memcpy(q, &domain_guid, sizeof(domain_guid));
+ q += sizeof(domain_guid);
+
+ /* Push domain components */
+ dc = domain;
+ q1 = q;
+ while ((component = strsep(&dc, "."))) {
+ size = push_ascii(&q[1], component, -1, 0);
+ SCVAL(q, 0, size);
+ q += (size + 1);
+ }
+ SCVAL(q, 0, 0); q++;
+ SSVAL(q, 0, 0x18c0); /* not sure what this is for, but */
+ q += 2; /* it must follow the domain name. */
+
+ /* Push dns host name */
+ size = push_ascii(&q[1], global_myname, -1, 0);
+ SCVAL(q, 0, size);
+ q += (size + 1);
+ SSVAL(q, 0, 0x18c0); /* not sure what this is for, but */
+ q += 2; /* it must follow the domain name. */
+
+ /* Push NETBIOS of domain */
+ size = push_ascii(&q[1], domain, -1, STR_UPPER);
+ SCVAL(q, 0, size);
+ q += (size + 1);
+ SCVAL(q, 0, 0); q++; /* is this a null terminator or empty field */
+ /* null terminator would not be needed because size is included */
+
+ /* Push NETBIOS of hostname */
+ size = push_ascii(&q[1], my_name, -1, 0);
+ SCVAL(q, 0, size);
+ q += (size + 1);
+ SCVAL(q, 0, 0); q++; /* null terminator or empty field? */
+
+ /* Push user account */
+ size = push_ascii(&q[1], ascuser, -1, 0);
+ SCVAL(q, 0, size);
+ q += (size + 1);
+
+ /* Push 'Default-First-Site-Name' */
+ size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0);
+ SCVAL(q, 0, size);
+ q += (size + 1);
+
+ SSVAL(q, 0, 0xc000); /* unknown */
+ SCVAL(q, 2, PTR_DIFF(q,q1));
+ SCVAL(q, 3, 0x10); /* unknown */
+ q += 4;
+
+ SIVAL(q, 0, 0x00000002); q += 4; /* unknown */
+ SIVAL(q, 0, (iface_ip(p->ip))->s_addr); q += 4;
+ SIVAL(q, 0, 0x00000000); q += 4; /* unknown */
+ SIVAL(q, 0, 0x00000000); q += 4; /* unknown */
+ }
+#endif
/* tell the client what version we are */
- SIVAL(q, 0, 1); /* our ntversion */
+ SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13);
+ /* our ntversion */
SSVAL(q, 4, 0xffff); /* our lmnttoken */
SSVAL(q, 6, 0xffff); /* our lm20token */
q += 8;
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index 4739cfbf7ad..29ceca4e79e 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -79,7 +79,7 @@ static int converse(pam_handle_t *pamh, int nargs,
}
-int _make_remark(pam_handle_t * pamh, int type, const char *text)
+static int _make_remark(pam_handle_t * pamh, int type, const char *text)
{
int retval = PAM_SUCCESS;
@@ -163,6 +163,10 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl)
/* password expired */
_pam_log(LOG_WARNING, "user `%s' password expired", user);
return retval;
+ case PAM_NEW_AUTHTOK_REQD:
+ /* password expired */
+ _pam_log(LOG_WARNING, "user `%s' new password required", user);
+ return retval;
case PAM_USER_UNKNOWN:
/* the user does not exist */
if (ctrl & WINBIND_DEBUG_ARG)
@@ -241,12 +245,12 @@ static char *_pam_delete(register char *xx)
* obtain a password from the user
*/
-int _winbind_read_password(pam_handle_t * pamh
- ,unsigned int ctrl
- ,const char *comment
- ,const char *prompt1
- ,const char *prompt2
- ,const char **pass)
+static int _winbind_read_password(pam_handle_t * pamh
+ ,unsigned int ctrl
+ ,const char *comment
+ ,const char *prompt1
+ ,const char *prompt2
+ ,const char **pass)
{
int authtok_flag;
int retval;
diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c
index bcb339864ae..9ac1515d7d3 100644
--- a/source/nsswitch/wb_client.c
+++ b/source/nsswitch/wb_client.c
@@ -65,7 +65,7 @@ BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid,
/* Call winbindd to convert sid to name */
-BOOL winbind_lookup_sid(DOM_SID *sid,
+BOOL winbind_lookup_sid(const DOM_SID *sid,
fstring dom_name, fstring name,
enum SID_NAME_USE *name_type)
{
@@ -102,7 +102,7 @@ BOOL winbind_lookup_sid(DOM_SID *sid,
/* Call winbindd to convert SID to uid */
-BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
+BOOL winbind_sid_to_uid(uid_t *puid, const DOM_SID *sid)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -168,7 +168,7 @@ BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
/* Call winbindd to convert SID to gid */
-BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
+BOOL winbind_sid_to_gid(gid_t *pgid, const DOM_SID *sid)
{
struct winbindd_request request;
struct winbindd_response response;
diff --git a/source/nsswitch/wb_common.c b/source/nsswitch/wb_common.c
index 89dd6252412..9bc9faafb50 100644
--- a/source/nsswitch/wb_common.c
+++ b/source/nsswitch/wb_common.c
@@ -28,7 +28,6 @@
/* Global variables. These are effectively the client state information */
int winbindd_fd = -1; /* fd for winbindd socket */
-static char *excluded_domain;
/* Free a response structure */
@@ -40,16 +39,6 @@ void free_response(struct winbindd_response *response)
SAFE_FREE(response->extra_data);
}
-/*
- smbd needs to be able to exclude lookups for its own domain
-*/
-void winbind_exclude_domain(const char *domain)
-{
- SAFE_FREE(excluded_domain);
- excluded_domain = strdup(domain);
-}
-
-
/* Initialise a request structure */
void init_request(struct winbindd_request *request, int request_type)
@@ -325,12 +314,6 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
return NSS_STATUS_NOTFOUND;
}
- /* smbd may have excluded this domain */
- if (excluded_domain &&
- strcasecmp(excluded_domain, request->domain) == 0) {
- return NSS_STATUS_NOTFOUND;
- }
-
if (!request) {
ZERO_STRUCT(lrequest);
request = &lrequest;
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index d0af10a0e6f..4d36acc51b3 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -255,8 +255,7 @@ static BOOL wbinfo_check_secret(void)
ZERO_STRUCT(response);
- result = winbindd_request(WINBINDD_CHECK_MACHACC, NULL, &response) ==
- NSS_STATUS_SUCCESS;
+ result = winbindd_request(WINBINDD_CHECK_MACHACC, NULL, &response);
d_printf("checking the trust secret via RPC calls %s\n",
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
@@ -490,9 +489,9 @@ static BOOL wbinfo_auth_crap(char *username)
generate_random_buffer(request.data.auth_crap.chal, 8, False);
- SMBencrypt((uchar *)pass, request.data.auth_crap.chal,
+ SMBencrypt(pass, request.data.auth_crap.chal,
(uchar *)request.data.auth_crap.lm_resp);
- SMBNTencrypt((uchar *)pass, request.data.auth_crap.chal,
+ SMBNTencrypt(pass, request.data.auth_crap.chal,
(uchar *)request.data.auth_crap.nt_resp);
request.data.auth_crap.lm_resp_len = 24;
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index 358d9add3a3..256c0203c0e 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -25,7 +25,7 @@
/* List of all connected clients */
-struct winbindd_cli_state *client_list;
+static struct winbindd_cli_state *client_list;
static int num_clients;
BOOL opt_nocache = False;
BOOL opt_dual_daemon = False;
@@ -375,6 +375,9 @@ void winbind_process_packet(struct winbindd_cli_state *state)
{
/* Process request */
+ /* Ensure null termination of entire request */
+ state->request.domain[sizeof(state->request.domain)-1]='\0';
+
state->pid = state->request.pid;
process_request(state);
@@ -688,6 +691,8 @@ int winbind_setup_common(void)
}
+ namecache_enable(); /* Enable netbios namecache */
+
/* Get list of domains we look up requests for. This includes the
domain which we are a member of as well as any trusted
domains. */
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index 11d399be49a..dd92ecefe61 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -88,7 +88,7 @@ typedef struct {
struct winbindd_domain {
fstring name; /* Domain name */
- fstring full_name; /* full Domain name (realm) */
+ fstring alt_name; /* alt Domain name (if any) */
DOM_SID sid; /* SID for this domain */
/* Lookup methods for this domain (LDAP or RPC) */
@@ -170,11 +170,15 @@ struct winbindd_methods {
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids);
/* find the domain sid */
NTSTATUS (*domain_sid)(struct winbindd_domain *domain,
DOM_SID *sid);
+
+ /* setup the list of alternate names for the domain, if any */
+ NTSTATUS (*alternate_name)(struct winbindd_domain *domain);
};
/* Used to glue a policy handle and cli_state together */
@@ -190,6 +194,8 @@ typedef struct {
#include "rpc_client.h"
#define WINBINDD_ESTABLISH_LOOP 30
+#define WINBINDD_RESCAN_FREQ 300
+
#define DOM_SEQUENCE_NONE ((uint32)-1)
/* SETENV */
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index b61348adfe7..b0b70178a45 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -61,8 +61,8 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope
if (*res) ads_msgfree(ads, *res);
*res = NULL;
- DEBUG(3,("Reopening ads connection to %s after error %s\n",
- ads->ldap_server, ads_errstr(status)));
+ DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n",
+ ads->config.realm, ads_errstr(status)));
if (ads->ld) {
ldap_unbind(ads->ld);
}
@@ -87,7 +87,7 @@ ADS_STATUS ads_search_retry(ADS_STRUCT *ads, void **res,
const char *exp,
const char **attrs)
{
- return ads_do_search_retry(ads, ads->bind_path, LDAP_SCOPE_SUBTREE,
+ return ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE,
exp, attrs, res);
}
@@ -108,8 +108,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
ADS_STRUCT *ads;
ADS_STATUS status;
char *ccache;
- struct in_addr server_ip;
- char *sname;
if (domain->private) {
return (ADS_STRUCT *)domain->private;
@@ -120,30 +118,23 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
SETENV("KRB5CCNAME", ccache, 1);
unlink(ccache);
- if (resolve_name(domain->name, &server_ip, 0x1b)) {
- sname = inet_ntoa(server_ip);
- } else if (resolve_name(domain->name, &server_ip, 0x1c)) {
- sname = inet_ntoa(server_ip);
- } else {
- if (strcasecmp(domain->name, lp_workgroup()) != 0) {
- DEBUG(1,("can't find domain controller for %s\n", domain->name));
- return NULL;
- }
- sname = NULL;
- }
-
- ads = ads_init(primary_realm, domain->name, NULL, NULL, NULL);
+ ads = ads_init(domain->alt_name, domain->name, NULL);
if (!ads) {
DEBUG(1,("ads_init for domain %s failed\n", domain->name));
return NULL;
}
/* the machine acct password might have change - fetch it every time */
- SAFE_FREE(ads->password);
- ads->password = secrets_fetch_machine_password();
+ SAFE_FREE(ads->auth.password);
+ ads->auth.password = secrets_fetch_machine_password();
+
+ if (primary_realm) {
+ SAFE_FREE(ads->auth.realm);
+ ads->auth.realm = strdup(primary_realm);
+ }
status = ads_connect(ads);
- if (!ADS_ERR_OK(status) || !ads->realm) {
+ if (!ADS_ERR_OK(status) || !ads->config.realm) {
extern struct winbindd_methods msrpc_methods;
DEBUG(1,("ads_connect for domain %s failed: %s\n",
domain->name, ads_errstr(status)));
@@ -161,11 +152,9 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
/* remember our primary realm for trusted domain support */
if (!primary_realm) {
- primary_realm = strdup(ads->realm);
+ primary_realm = strdup(ads->config.realm);
}
- fstrcpy(domain->full_name, ads->server_realm);
-
domain->private = (void *)ads;
return ads;
}
@@ -405,7 +394,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
/* accept either the win2000 or the pre-win2000 username */
asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))",
- name, name, ads->realm);
+ name, name, ads->config.realm);
rc = ads_search_retry(ads, &res, exp, attrs);
free(exp);
if (!ADS_ERR_OK(rc)) {
@@ -535,49 +524,6 @@ failed:
return False;
}
-
-/* convert a sid to a distnguished name */
-static NTSTATUS sid_to_distinguished_name(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
- char **dn)
-{
- ADS_STRUCT *ads = NULL;
- const char *attrs[] = {"distinguishedName", NULL};
- ADS_STATUS rc;
- void *msg = NULL;
- char *exp;
- char *sidstr;
- NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
-
- DEBUG(3,("ads: sid_to_distinguished_name\n"));
-
- ads = ads_cached_connection(domain);
- if (!ads) goto done;
-
- sidstr = sid_binstring(sid);
- asprintf(&exp, "(objectSid=%s)", sidstr);
- rc = ads_search_retry(ads, &msg, exp, attrs);
- free(exp);
- free(sidstr);
- if (!ADS_ERR_OK(rc)) {
- DEBUG(1,("sid_to_distinguished_name ads_search: %s\n", ads_errstr(rc)));
- goto done;
- }
-
- *dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName");
-
- status = NT_STATUS_OK;
-
- DEBUG(3,("ads sid_to_distinguished_name mapped %s\n", *dn));
-
-done:
- if (msg) ads_msgfree(ads, msg);
-
- return status;
-}
-
-
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
@@ -831,6 +777,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
ADS_STRUCT *ads;
@@ -842,7 +789,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
ads = ads_cached_connection(domain);
if (!ads) return NT_STATUS_UNSUCCESSFUL;
- rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, dom_sids);
+ rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids);
return ads_ntstatus(rc);
}
@@ -867,6 +814,37 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
return ads_ntstatus(rc);
}
+
+/* find alternate names list for the domain - for ADS this is the
+ netbios name */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ ADS_STRUCT *ads;
+ ADS_STATUS rc;
+ TALLOC_CTX *ctx;
+ char *workgroup;
+
+ ads = ads_cached_connection(domain);
+ if (!ads) return NT_STATUS_UNSUCCESSFUL;
+
+ if (!(ctx = talloc_init_named("alternate_name"))) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = ads_workgroup_name(ads, ctx, &workgroup);
+
+ if (ADS_ERR_OK(rc)) {
+ fstrcpy(domain->name, workgroup);
+ fstrcpy(domain->alt_name, ads->config.realm);
+ strupper(domain->alt_name);
+ strupper(domain->name);
+ }
+
+ talloc_destroy(ctx);
+
+ return ads_ntstatus(rc);
+}
+
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods ads_methods = {
True,
@@ -879,7 +857,8 @@ struct winbindd_methods ads_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
#endif
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index a607727867f..060139af3ed 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -873,13 +873,14 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
struct winbind_cache *cache = get_cache(domain);
/* we don't cache this call */
return cache->backend->trusted_domains(domain, mem_ctx, num_domains,
- names, dom_sids);
+ names, alt_names, dom_sids);
}
/* find the domain sid */
@@ -891,6 +892,15 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
return cache->backend->domain_sid(domain, sid);
}
+/* find the alternate names for the domain, if any */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ struct winbind_cache *cache = get_cache(domain);
+
+ /* we don't cache this call */
+ return cache->backend->alternate_name(domain);
+}
+
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods cache_methods = {
True,
@@ -903,5 +913,6 @@ struct winbindd_methods cache_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index 3ab97ed408f..2dec9f05586 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -90,12 +90,122 @@ struct get_dc_name_cache {
struct get_dc_name_cache *prev, *next;
};
+
+/*
+ find the DC for a domain using methods appropriate for a ADS domain
+*/
+static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
+{
+ ADS_STRUCT *ads;
+ const char *realm = domain;
+
+ if (strcasecmp(realm, lp_workgroup()) == 0) {
+ realm = lp_realm();
+ }
+
+ ads = ads_init(realm, domain, NULL);
+ if (!ads) {
+ return False;
+ }
+
+ /* we don't need to bind, just connect */
+ ads->auth.no_bind = 1;
+
+ DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain));
+
+#ifdef HAVE_ADS
+ /* a full ads_connect() is actually overkill, as we don't srictly need
+ to do the SASL auth in order to get the info we need, but libads
+ doesn't offer a better way right now */
+ ads_connect(ads);
+#endif
+
+ if (!ads->config.realm) {
+ return False;
+ }
+
+ fstrcpy(srv_name, ads->config.ldap_server_name);
+ strupper(srv_name);
+ *dc_ip = ads->ldap_ip;
+ ads_destroy(&ads);
+
+ DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n",
+ srv_name, inet_ntoa(*dc_ip)));
+
+ return True;
+}
+
+/*
+ find the DC for a domain using methods appropriate for a RPC domain
+*/
+static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name)
+{
+ struct in_addr *ip_list = NULL;
+ int count, i;
+
+ /* Lookup domain controller name. Try the real PDC first to avoid
+ SAM sync delays */
+ if (!get_dc_list(True, domain, &ip_list, &count)) {
+ if (!get_dc_list(False, domain, &ip_list, &count)) {
+ DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
+ return False;
+ }
+ }
+
+ /* Pick a nice close server */
+ /* Look for DC on local net */
+ for (i = 0; i < count; i++) {
+ if (!is_local_net(ip_list[i]))
+ continue;
+
+ if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
+ *dc_ip = ip_list[i];
+ SAFE_FREE(ip_list);
+ return True;
+ }
+ zero_ip(&ip_list[i]);
+ }
+
+ /*
+ * Secondly try and contact a random PDC/BDC.
+ */
+
+ i = (sys_random() % count);
+
+ if (!is_zero_ip(ip_list[i]) &&
+ name_status_find(domain, 0x1c, 0x20,
+ ip_list[i], srv_name)) {
+ *dc_ip = ip_list[i];
+ SAFE_FREE(ip_list);
+ return True;
+ }
+ zero_ip(&ip_list[i]); /* Tried and failed. */
+
+ /* Finally return first DC that we can contact using a node
+ status */
+ for (i = 0; i < count; i++) {
+ if (is_zero_ip(ip_list[i]))
+ continue;
+
+ if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
+ *dc_ip = ip_list[i];
+ SAFE_FREE(ip_list);
+ return True;
+ }
+ }
+
+ SAFE_FREE(ip_list);
+
+ return False;
+}
+
+
static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
{
static struct get_dc_name_cache *get_dc_name_cache;
struct get_dc_name_cache *dcc;
- struct in_addr *ip_list, dc_ip;
- int count, i;
+ struct in_addr dc_ip;
+ BOOL ret;
/* Check the cache for previous lookups */
@@ -144,66 +254,22 @@ static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr
DLIST_ADD(get_dc_name_cache, dcc);
- /* Lookup domain controller name. Try the real PDC first to avoid
- SAM sync delays */
- if (!get_dc_list(True, domain, &ip_list, &count)) {
- if (!get_dc_list(False, domain, &ip_list, &count)) {
- DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
- return False;
- }
- }
+ zero_ip(&dc_ip);
- /* Pick a nice close server */
- /* Look for DC on local net */
-
- for (i = 0; i < count; i++) {
- if (!is_local_net(ip_list[i]))
- continue;
-
- if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
- dc_ip = ip_list[i];
- goto done;
- }
- zero_ip(&ip_list[i]);
+ ret = False;
+ if (lp_security() == SEC_ADS) {
+ ret = cm_ads_find_dc(domain, &dc_ip, srv_name);
}
-
- /*
- * Secondly try and contact a random PDC/BDC.
- */
-
- i = (sys_random() % count);
-
- if (!is_zero_ip(ip_list[i]) &&
- name_status_find(domain, 0x1c, 0x20,
- ip_list[i], srv_name)) {
- dc_ip = ip_list[i];
- goto done;
+ if (!ret) {
+ /* fall back on rpc methods if the ADS methods fail */
+ ret = cm_rpc_find_dc(domain, &dc_ip, srv_name);
}
- zero_ip(&ip_list[i]); /* Tried and failed. */
- /* Finally return first DC that we can contact */
-
- for (i = 0; i < count; i++) {
- if (is_zero_ip(ip_list[i]))
- continue;
-
- if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) {
- dc_ip = ip_list[i];
- goto done;
- }
+ if (!ret) {
+ return False;
}
- /* No-one to talk to )-: */
- return False; /* Boo-hoo */
-
- done:
- /* We have the netbios name and IP address of a domain controller.
- Ideally we should sent a SAMLOGON request to determine whether
- the DC is alive and kicking. If we can catch a dead DC before
- performing a cli_connect() we can avoid a 30-second timeout. */
-
/* We have a name so make the cache entry positive now */
-
fstrcpy(dcc->srv_name, srv_name);
DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name,
@@ -211,8 +277,6 @@ static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr
*ip_out = dc_ip;
- SAFE_FREE(ip_list);
-
return True;
}
@@ -262,11 +326,23 @@ static struct failed_connection_cache *failed_connection_cache;
/* Add an entry to the failed conneciton cache */
-static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, NTSTATUS result) {
+static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn,
+ NTSTATUS result)
+{
struct failed_connection_cache *fcc;
SMB_ASSERT(!NT_STATUS_IS_OK(result));
+ /* Check we already aren't in the cache */
+
+ for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
+ if (strequal(fcc->domain_name, new_conn->domain)) {
+ DEBUG(10, ("domain %s already tried and failed\n",
+ fcc->domain_name));
+ return;
+ }
+ }
+
/* Create negative lookup cache entry for this domain and controller */
if (!(fcc = (struct failed_connection_cache *)
@@ -794,7 +870,7 @@ NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
return result;
}
- result = new_cli_nt_setup_creds(conn->cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
+ result = cli_nt_setup_creds(conn->cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
SEC_CHAN_WKSTA : SEC_CHAN_BDC, trust_passwd);
if (!NT_STATUS_IS_OK(result)) {
@@ -808,7 +884,7 @@ NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
}
/* Try again */
- result = new_cli_nt_setup_creds(conn->cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
+ result = cli_nt_setup_creds(conn->cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
SEC_CHAN_WKSTA : SEC_CHAN_BDC, trust_passwd);
}
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index 20563ba7bd7..abb6b9da757 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -196,6 +196,9 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
gid_t gid;
int gr_mem_len;
+ /* Ensure null termination */
+ state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0';
+
DEBUG(3, ("[%5d]: getgrnam %s\n", state->pid,
state->request.data.groupname));
@@ -783,6 +786,9 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
int i;
TALLOC_CTX *mem_ctx;
+ /* Ensure null termination */
+ state->request.data.username[sizeof(state->request.data.username)-1]='\0';
+
DEBUG(3, ("[%5d]: getgroups %s\n", state->pid,
state->request.data.username));
diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h
index 0f0e40a2eca..9eea94e7c0d 100644
--- a/source/nsswitch/winbindd_nss.h
+++ b/source/nsswitch/winbindd_nss.h
@@ -36,7 +36,7 @@
/* Update this when you change the interface. */
-#define WINBIND_INTERFACE_VERSION 4
+#define WINBIND_INTERFACE_VERSION 5
/* Socket commands */
@@ -107,6 +107,12 @@ enum winbindd_cmd {
WINBINDD_NUM_CMDS
};
+#define WINBIND_PAM_INFO3_NDR 0x0001
+#define WINBIND_PAM_INFO3_TEXT 0x0002
+#define WINBIND_PAM_NTKEY 0x0004
+#define WINBIND_PAM_LMKEY 0x0008
+#define WINBIND_PAM_CONTACT_TRUSTDOM 0x0010
+
/* Winbind request structure */
struct winbindd_request {
@@ -132,6 +138,8 @@ struct winbindd_request {
uint16 lm_resp_len;
fstring nt_resp;
uint16 nt_resp_len;
+ fstring workstation;
+ uint32 flags;
} auth_crap;
struct {
fstring user;
@@ -216,6 +224,8 @@ struct winbindd_response {
fstring nt_status_string;
fstring error_string;
int pam_error;
+ char nt_session_key[16];
+ char first_8_lm_hash[8];
} auth;
} data;
diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c
index e608f826c91..a8b508a49c6 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -23,17 +23,41 @@
*/
#include "winbindd.h"
-
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+
+static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
+ struct winbindd_cli_state *state,
+ NET_USER_INFO_3 *info3)
+{
+ prs_struct ps;
+ uint32 size;
+ if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (!net_io_user_info3("", info3, &ps, 1, 3)) {
+ prs_mem_free(&ps);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ size = prs_data_size(&ps);
+ state->response.extra_data = memdup(prs_data_p(&ps), size);
+ if (!state->response.extra_data) {
+ prs_mem_free(&ps);
+ return NT_STATUS_NO_MEMORY;
+ }
+ state->response.length += size;
+ prs_mem_free(&ps);
+ return NT_STATUS_OK;
+}
+
/* Return a password structure from a username. */
enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
{
NTSTATUS result;
fstring name_domain, name_user;
- int passlen;
unsigned char trust_passwd[16];
time_t last_change_time;
uint32 smb_uid_low;
@@ -46,6 +70,12 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
extern pstring global_myname;
+ /* Ensure null termination */
+ state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
+
+ /* Ensure null termination */
+ state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';
+
DEBUG(3, ("[%5d]: pam auth %s\n", state->pid,
state->request.data.auth.user));
@@ -64,16 +94,14 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
goto done;
}
- passlen = strlen(state->request.data.auth.pass);
-
{
unsigned char local_lm_response[24];
unsigned char local_nt_response[24];
generate_random_buffer(chal, 8, False);
- SMBencrypt( (const uchar *)state->request.data.auth.pass, chal, local_lm_response);
+ SMBencrypt(state->request.data.auth.pass, chal, local_lm_response);
- SMBNTencrypt((const uchar *)state->request.data.auth.pass, chal, local_nt_response);
+ SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response);
lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
@@ -140,34 +168,67 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
NET_USER_INFO_3 info3;
struct cli_state *cli = NULL;
TALLOC_CTX *mem_ctx = NULL;
- const char *domain = NULL;
+ char *user = NULL;
+ char *domain = NULL;
+ char *contact_domain;
+ char *workstation;
DATA_BLOB lm_resp, nt_resp;
extern pstring global_myname;
- DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid,
- state->request.data.auth_crap.domain, state->request.data.auth_crap.user));
+ /* Ensure null termination */
+ state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]='\0';
+
+ /* Ensure null termination */
+ state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]='\0';
- if (!(mem_ctx = talloc_init_named("winbind pam auth crap for %s", state->request.data.auth.user))) {
+ if (!(mem_ctx = talloc_init_named("winbind pam auth crap for (utf8) %s", state->request.data.auth.user))) {
DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n"));
result = NT_STATUS_NO_MEMORY;
goto done;
}
+ if (pull_utf8_talloc(mem_ctx, &user, state->request.data.auth_crap.user) < 0) {
+ DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n"));
+ }
+
if (*state->request.data.auth_crap.domain) {
- domain = talloc_strdup(mem_ctx, state->request.data.auth_crap.domain);
+ if (pull_utf8_talloc(mem_ctx, &domain, state->request.data.auth_crap.domain) < 0) {
+ DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n"));
+ }
} else if (lp_winbind_use_default_domain()) {
- domain = talloc_strdup(mem_ctx, lp_workgroup());
+ domain = lp_workgroup();
} else {
- DEBUG(5,("no domain specified with username (%s) - failing auth\n", state->request.data.auth.user));
+ DEBUG(5,("no domain specified with username (%s) - failing auth\n",
+ user));
result = NT_STATUS_INVALID_PARAMETER;
goto done;
}
- if (!domain) {
- DEBUG(0,("winbindd_pam_auth_crap: talloc_strdup failed!\n"));
- result = NT_STATUS_NO_MEMORY;
+ DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid,
+ domain, user));
+
+ if (lp_allow_trusted_domains() && (state->request.data.auth_crap.flags & WINBIND_PAM_CONTACT_TRUSTDOM)) {
+ contact_domain = domain;
+ } else {
+ contact_domain = lp_workgroup();
+ }
+
+ if (*state->request.data.auth_crap.workstation) {
+ if (pull_utf8_talloc(mem_ctx, &workstation, state->request.data.auth_crap.workstation) < 0) {
+ DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n"));
+ }
+ } else {
+ workstation = global_myname;
+ }
+
+ if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp)
+ || state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) {
+ DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n",
+ state->request.data.auth_crap.lm_resp_len,
+ state->request.data.auth_crap.nt_resp_len));
+ result = NT_STATUS_INVALID_PARAMETER;
goto done;
}
@@ -175,13 +236,15 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len);
/*
- * Get the machine account password for our primary domain
+ * Get the machine account password for the domain to contact.
+ * This is either our own domain for a workstation, or possibly
+ * any domain for a PDC with trusted domains.
*/
- if (!secrets_fetch_trust_account_password(
- lp_workgroup(), trust_passwd, &last_change_time)) {
+ if (!secrets_fetch_trust_account_password (
+ contact_domain, trust_passwd, &last_change_time)) {
DEBUG(0, ("winbindd_pam_auth: could not fetch trust account "
- "password for domain %s\n", lp_workgroup()));
+ "password for domain %s\n", contact_domain));
result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
goto done;
}
@@ -189,7 +252,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
ZERO_STRUCT(info3);
/* Don't shut this down - it belongs to the connection cache code */
- result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli);
+ result = cm_get_netlogon_cli(contact_domain, trust_passwd, &cli);
if (!NT_STATUS_IS_OK(result)) {
DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", nt_errstr(result)));
@@ -197,27 +260,43 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
}
result = cli_netlogon_sam_network_logon(cli, mem_ctx,
- state->request.data.auth_crap.user, domain,
- global_myname, state->request.data.auth_crap.chal,
+ user, domain,
+ workstation, state->request.data.auth_crap.chal,
lm_resp, nt_resp,
&info3);
if (NT_STATUS_IS_OK(result)) {
uni_group_cache_store_netlogon(mem_ctx, &info3);
+ if (state->request.data.auth_crap.flags & WINBIND_PAM_INFO3_NDR) {
+ result = append_info3_as_ndr(mem_ctx, state, &info3);
+ }
+
+#if 0
+ /* we don't currently do this stuff right */
+ if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) {
+ SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) == sizeof(info3.user_sess_key));
+ memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
+ }
+ if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) {
+ SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) <= sizeof(info3.user_sess_key));
+ memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
+ }
+#endif
}
done:
state->response.data.auth.nt_status = NT_STATUS_V(result);
- fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
- fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
+ push_utf8_fstring(state->response.data.auth.nt_status_string, nt_errstr(result));
+ push_utf8_fstring(state->response.data.auth.error_string, nt_errstr(result));
state->response.data.auth.pam_error = nt_status_to_pam(result);
- DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n",
- state->request.data.auth_crap.domain,
- state->request.data.auth_crap.user,
- state->response.data.auth.nt_status_string,
- state->response.data.auth.pam_error));
+ DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
+ ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n",
+ domain,
+ user,
+ state->response.data.auth.nt_status_string,
+ state->response.data.auth.pam_error));
if (mem_ctx)
talloc_destroy(mem_ctx);
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 2bb0e8c49f4..5ec34f663d8 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -575,22 +575,23 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
uint32 *num_domains,
char ***names,
+ char ***alt_names,
DOM_SID **dom_sids)
{
CLI_POLICY_HND *hnd;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
uint32 enum_ctx = 0;
- uint32 pref_num_domains = 5;
DEBUG(3,("rpc: trusted_domains\n"));
*num_domains = 0;
+ *alt_names = NULL;
if (!(hnd = cm_get_lsa_handle(lp_workgroup())))
goto done;
result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
- &hnd->pol, &enum_ctx, &pref_num_domains,
+ &hnd->pol, &enum_ctx,
num_domains, names, dom_sids);
done:
return result;
@@ -621,6 +622,13 @@ done:
return status;
}
+/* find alternate names list for the domain - none for rpc */
+static NTSTATUS alternate_name(struct winbindd_domain *domain)
+{
+ return NT_STATUS_OK;
+}
+
+
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods msrpc_methods = {
False,
@@ -633,5 +641,6 @@ struct winbindd_methods msrpc_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- domain_sid
+ domain_sid,
+ alternate_name
};
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index 372898a08a4..44f857d6be0 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -36,6 +36,9 @@ enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state)
fstring name;
fstring dom_name;
+ /* Ensure null termination */
+ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
+
DEBUG(3, ("[%5d]: lookupsid %s\n", state->pid,
state->request.data.sid));
@@ -79,6 +82,12 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
DOM_SID sid;
struct winbindd_domain *domain;
+ /* Ensure null termination */
+ state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0';
+
+ /* Ensure null termination */
+ state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0';
+
DEBUG(3, ("[%5d]: lookupname %s%s%s\n", state->pid,
state->request.data.name.dom_name,
lp_winbind_separator(),
@@ -112,6 +121,9 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
{
DOM_SID sid;
+ /* Ensure null termination */
+ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
+
DEBUG(3, ("[%5d]: sid to uid %s\n", state->pid,
state->request.data.sid));
@@ -139,6 +151,9 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
{
DOM_SID sid;
+ /* Ensure null termination */
+ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
+
DEBUG(3, ("[%5d]: sid to gid %s\n", state->pid,
state->request.data.sid));
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index 55593d6ae57..4f57fd2c722 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -103,6 +103,9 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
struct winbindd_domain *domain;
TALLOC_CTX *mem_ctx;
+ /* Ensure null termination */
+ state->request.data.username[sizeof(state->request.data.username)-1]='\0';
+
DEBUG(3, ("[%5d]: getpwnam %s\n", state->pid,
state->request.data.username));
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index d5668a2bb68..daa3abb3400 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -74,19 +74,17 @@ void free_domain_list(void)
}
/* Add a trusted domain to our list of domains */
-
-static struct winbindd_domain *add_trusted_domain(char *domain_name,
- struct winbindd_methods *methods)
+static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
+ struct winbindd_methods *methods,
+ DOM_SID *sid)
{
struct winbindd_domain *domain;
/* We can't call domain_list() as this function is called from
init_domain_list() and we'll get stuck in a loop. */
-
for (domain = _domain_list; domain; domain = domain->next) {
- if (strcmp(domain_name, domain->name) == 0) {
- DEBUG(3, ("domain %s already in domain list\n",
- domain_name));
+ if (strcmp(domain_name, domain->name) == 0 ||
+ strcmp(domain_name, domain->alt_name) == 0) {
return domain;
}
}
@@ -101,40 +99,95 @@ static struct winbindd_domain *add_trusted_domain(char *domain_name,
ZERO_STRUCTP(domain);
+ /* prioritise the short name */
+ if (strchr_m(domain_name, '.') && alt_name && *alt_name) {
+ fstrcpy(domain->name, alt_name);
+ fstrcpy(domain->alt_name, domain_name);
+ } else {
fstrcpy(domain->name, domain_name);
+ if (alt_name) {
+ fstrcpy(domain->alt_name, alt_name);
+ }
+ }
+
domain->methods = methods;
domain->sequence_number = DOM_SEQUENCE_NONE;
domain->last_seq_check = 0;
+ if (sid) {
+ sid_copy(&domain->sid, sid);
+ }
/* Link to domain list */
-
DLIST_ADD(_domain_list, domain);
+ DEBUG(1,("Added domain %s %s %s\n",
+ domain->name, domain->alt_name,
+ sid?sid_string_static(&domain->sid):""));
+
return domain;
}
-/* Look up global info for the winbind daemon */
+/*
+ rescan our domains looking for new trusted domains
+ */
+void rescan_trusted_domains(void)
+{
+ struct winbindd_domain *domain;
+ TALLOC_CTX *mem_ctx;
+ static time_t last_scan;
+ time_t t = time(NULL);
+
+ /* ony rescan every few minutes */
+ if ((unsigned)(t - last_scan) < WINBINDD_RESCAN_FREQ) {
+ return;
+ }
+ last_scan = time(NULL);
+
+ DEBUG(1, ("scanning trusted domain list\n"));
+
+ if (!(mem_ctx = talloc_init_named("init_domain_list")))
+ return;
+
+ for (domain = _domain_list; domain; domain = domain->next) {
+ NTSTATUS result;
+ char **names;
+ char **alt_names;
+ int num_domains = 0;
+ DOM_SID *dom_sids;
+ int i;
+
+ result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains,
+ &names, &alt_names, &dom_sids);
+ if (!NT_STATUS_IS_OK(result)) {
+ continue;
+ }
+
+ /* Add each domain to the trusted domain list. Each domain inherits
+ the access methods of its parent */
+ for(i = 0; i < num_domains; i++) {
+ DEBUG(10,("Found domain %s\n", names[i]));
+ add_trusted_domain(names[i],
+ alt_names?alt_names[i]:NULL,
+ domain->methods, &dom_sids[i]);
+ }
+ }
+
+ talloc_destroy(mem_ctx);
+}
+
+/* Look up global info for the winbind daemon */
BOOL init_domain_list(void)
{
NTSTATUS result;
- TALLOC_CTX *mem_ctx;
extern struct winbindd_methods cache_methods;
struct winbindd_domain *domain;
- DOM_SID *dom_sids;
- char **names;
- int num_domains = 0;
-
- if (!(mem_ctx = talloc_init_named("init_domain_list")))
- return False;
/* Free existing list */
-
free_domain_list();
/* Add ourselves as the first entry */
-
- domain = add_trusted_domain(lp_workgroup(), &cache_methods);
+ domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL);
/* Now we *must* get the domain sid for our primary domain. Go into
a holding pattern until that is available */
@@ -147,29 +200,12 @@ BOOL init_domain_list(void)
result = cache_methods.domain_sid(domain, &domain->sid);
}
- DEBUG(1,("Added domain %s (%s)\n",
- domain->name,
- sid_string_static(&domain->sid)));
-
- DEBUG(1, ("getting trusted domain list\n"));
+ /* get any alternate name for the primary domain */
+ cache_methods.alternate_name(domain);
- result = cache_methods.trusted_domains(domain, mem_ctx, &num_domains,
- &names, &dom_sids);
+ /* do an initial scan for trusted domains */
+ rescan_trusted_domains();
- /* Add each domain to the trusted domain list */
- if (NT_STATUS_IS_OK(result)) {
- int i;
- for(i = 0; i < num_domains; i++) {
- domain = add_trusted_domain(names[i], &cache_methods);
- if (!domain) continue;
- sid_copy(&domain->sid, &dom_sids[i]);
- DEBUG(1,("Added domain %s (%s)\n",
- domain->name,
- sid_string_static(&domain->sid)));
- }
- }
-
- talloc_destroy(mem_ctx);
return True;
}
@@ -184,7 +220,7 @@ struct winbindd_domain *find_domain_from_name(const char *domain_name)
for (domain = domain_list(); domain != NULL; domain = domain->next) {
if (strequal(domain_name, domain->name) ||
- strequal(domain_name, domain->full_name))
+ (domain->alt_name[0] && strequal(domain_name, domain->alt_name)))
return domain;
}
diff --git a/source/nsswitch/winbindd_wins.c b/source/nsswitch/winbindd_wins.c
index 8f9a7414bdc..8ddd5dc10df 100644
--- a/source/nsswitch/winbindd_wins.c
+++ b/source/nsswitch/winbindd_wins.c
@@ -122,6 +122,9 @@ enum winbindd_result winbindd_wins_byip(struct winbindd_cli_state *state)
int i, count, maxlen, size;
struct node_status *status;
+ /* Ensure null termination */
+ state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0';
+
DEBUG(3, ("[%5d]: wins_byip %s\n", state->pid,
state->request.data.winsreq));
@@ -166,6 +169,9 @@ enum winbindd_result winbindd_wins_byname(struct winbindd_cli_state *state)
fstring response;
char * addr;
+ /* Ensure null termination */
+ state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0';
+
DEBUG(3, ("[%5d]: wins_byname %s\n", state->pid,
state->request.data.winsreq));
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 6e3ce460cd4..b16f4483f84 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -87,6 +87,7 @@ static BOOL defaults_saved = False;
*/
typedef struct
{
+ char *smb_ports;
char *dos_charset;
char *unix_charset;
char *display_charset;
@@ -165,6 +166,7 @@ typedef struct
char *szGuestaccount;
char *szManglingMethod;
int max_log_size;
+ char *szLogLevel;
int mangled_stack;
int max_xmit;
int max_mux;
@@ -256,7 +258,9 @@ typedef struct
BOOL bHostnameLookups;
BOOL bUseSpnego;
BOOL bUnixExtensions;
+ BOOL bDisableNetbios;
int restrict_anonymous;
+ int name_cache_timeout;
}
global;
@@ -313,6 +317,7 @@ typedef struct
char *fstype;
char *szVfsObjectFile;
char *szVfsOptions;
+ char *szVfsPath;
int iMinPrintSpace;
int iMaxPrintJobs;
int iWriteCacheSize;
@@ -339,6 +344,7 @@ typedef struct
BOOL bCaseMangle;
BOOL bHideDotFiles;
BOOL bHideUnReadable;
+ BOOL bHideUnWriteableFiles;
BOOL bBrowseable;
BOOL bAvailable;
BOOL bRead_only;
@@ -431,6 +437,7 @@ static service sDefault = {
NULL, /* fstype */
NULL, /* vfs object */
NULL, /* vfs options */
+ NULL, /* vfs path */
0, /* iMinPrintSpace */
1000, /* iMaxPrintJobs */
0, /* iWriteCacheSize */
@@ -457,6 +464,7 @@ static service sDefault = {
False, /* case mangle */
True, /* bHideDotFiles */
False, /* bHideUnReadable */
+ False, /* bHideUnWriteableFiles */
True, /* bBrowseable */
True, /* bAvailable */
True, /* bRead_only */
@@ -545,7 +553,9 @@ static struct enum_list enum_security[] = {
{SEC_USER, "USER"},
{SEC_SERVER, "SERVER"},
{SEC_DOMAIN, "DOMAIN"},
+#ifdef HAVE_ADS
{SEC_ADS, "ADS"},
+#endif
{-1, NULL}
};
@@ -759,8 +769,8 @@ static struct parm_struct parm_table[] = {
{"Logging Options", P_SEP, P_SEPARATOR},
{"admin log", P_BOOL, P_GLOBAL, &Globals.bAdminLog, NULL, NULL, 0},
- {"log level", P_STRING, P_GLOBAL, NULL, handle_debug_list, NULL, 0},
- {"debuglevel", P_STRING, P_GLOBAL, NULL, handle_debug_list, NULL, 0},
+ {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, 0},
+ {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, 0},
{"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, 0},
{"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, 0},
{"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, 0},
@@ -774,6 +784,7 @@ static struct parm_struct parm_table[] = {
{"Protocol Options", P_SEP, P_SEPARATOR},
+ {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, 0},
{"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, 0},
{"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, 0},
{"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, 0},
@@ -782,6 +793,7 @@ static struct parm_struct parm_table[] = {
{"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL, NULL, 0},
{"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, 0},
{"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, 0},
+ {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, 0},
{"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, 0},
{"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE },
@@ -827,6 +839,8 @@ static struct parm_struct parm_table[] = {
{"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, 0},
{"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_SHARE},
+ {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, 0},
+
{"Printing Options", P_SEP, P_SEPARATOR},
{"total print jobs", P_INTEGER, P_GLOBAL, &Globals.iTotalPrintJobs, NULL, NULL, FLAG_PRINT},
@@ -875,6 +889,7 @@ static struct parm_struct parm_table[] = {
{"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
{"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
{"hide unreadable", P_BOOL, P_LOCAL, &sDefault.bHideUnReadable, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
+ {"hide unwriteable files", P_BOOL, P_LOCAL, &sDefault.bHideUnWriteableFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
{"delete veto files", P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
{"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL },
{"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL },
@@ -1021,6 +1036,7 @@ static struct parm_struct parm_table[] = {
{"vfs object", P_STRING, P_LOCAL, &sDefault.szVfsObjectFile, handle_vfs_object, NULL, FLAG_SHARE},
{"vfs options", P_STRING, P_LOCAL, &sDefault.szVfsOptions, NULL, NULL, FLAG_SHARE},
+ {"vfs path", P_STRING, P_LOCAL, &sDefault.szVfsPath, NULL, NULL, FLAG_SHARE},
{"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
@@ -1057,26 +1073,26 @@ static void init_printer_values(void)
case PRINT_AIX:
case PRINT_LPRNT:
case PRINT_LPROS2:
- string_set(&sDefault.szLpqcommand, "lpq -P%p");
- string_set(&sDefault.szLprmcommand, "lprm -P%p %j");
+ string_set(&sDefault.szLpqcommand, "lpq -P'%p'");
+ string_set(&sDefault.szLprmcommand, "lprm -P'%p' %j");
string_set(&sDefault.szPrintcommand,
- "lpr -r -P%p %s");
+ "lpr -r -P'%p' %s");
break;
case PRINT_LPRNG:
case PRINT_PLP:
- string_set(&sDefault.szLpqcommand, "lpq -P%p");
- string_set(&sDefault.szLprmcommand, "lprm -P%p %j");
+ string_set(&sDefault.szLpqcommand, "lpq -P'%p'");
+ string_set(&sDefault.szLprmcommand, "lprm -P'%p' %j");
string_set(&sDefault.szPrintcommand,
- "lpr -r -P%p %s");
+ "lpr -r -P'%p' %s");
string_set(&sDefault.szQueuepausecommand,
- "lpc stop %p");
+ "lpc stop '%p'");
string_set(&sDefault.szQueueresumecommand,
- "lpc start %p");
+ "lpc start '%p'");
string_set(&sDefault.szLppausecommand,
- "lpc hold %p %j");
+ "lpc hold '%p' %j");
string_set(&sDefault.szLpresumecommand,
- "lpc release %p %j");
+ "lpc release '%p' %j");
break;
case PRINT_CUPS:
@@ -1092,19 +1108,19 @@ static void init_printer_values(void)
string_set(&Globals.szPrintcapname, "cups");
#else
string_set(&sDefault.szLpqcommand,
- "/usr/bin/lpstat -o %p");
+ "/usr/bin/lpstat -o '%p'");
string_set(&sDefault.szLprmcommand,
- "/usr/bin/cancel %p-%j");
+ "/usr/bin/cancel '%p-%j'");
string_set(&sDefault.szPrintcommand,
- "/usr/bin/lp -d %p %s; rm %s");
+ "/usr/bin/lp -d '%p' %s; rm %s");
string_set(&sDefault.szLppausecommand,
- "lp -i %p-%j -H hold");
+ "lp -i '%p-%j' -H hold");
string_set(&sDefault.szLpresumecommand,
- "lp -i %p-%j -H resume");
+ "lp -i '%p-%j' -H resume");
string_set(&sDefault.szQueuepausecommand,
- "/usr/bin/disable %p");
+ "/usr/bin/disable '%p'");
string_set(&sDefault.szQueueresumecommand,
- "/usr/bin/enable %p");
+ "/usr/bin/enable '%p'");
string_set(&Globals.szPrintcapname, "lpstat");
#endif /* HAVE_CUPS */
break;
@@ -1191,7 +1207,7 @@ static void init_globals(void)
string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
- Globals.szPassdbBackend = str_list_make("smbpasswd unixsam");
+ Globals.szPassdbBackend = str_list_make("smbpasswd unixsam", NULL);
/* use the new 'hash2' method by default */
string_set(&Globals.szManglingMethod, "hash2");
@@ -1201,6 +1217,9 @@ static void init_globals(void)
/* using UTF8 by default allows us to support all chars */
string_set(&Globals.unix_charset, "UTF8");
+ /* Use codepage 850 as a default for the dos character set */
+ string_set(&Globals.dos_charset, "CP850");
+
/*
* Allow the default PASSWD_CHAT to be overridden in local.h.
*/
@@ -1262,6 +1281,7 @@ static void init_globals(void)
Globals.bSyslogOnly = False;
Globals.bAdminLog = False;
Globals.bTimestampLogs = True;
+ string_set(&Globals.szLogLevel, "0");
Globals.bDebugHiresTimestamp = False;
Globals.bDebugPid = False;
Globals.bDebugUid = False;
@@ -1358,8 +1378,11 @@ static void init_globals(void)
Globals.bWinbindEnumGroups = True;
Globals.bWinbindUseDefaultDomain = False;
+ Globals.name_cache_timeout = 660; /* In seconds */
+
Globals.bUseSpnego = True;
+ string_set(&Globals.smb_ports, SMB_PORTS);
}
static TALLOC_CTX *lp_talloc;
@@ -1407,7 +1430,10 @@ static char *lp_string(const char *s)
else
StrnCpy(ret, s, len);
- trim_string(ret, "\"", "\"");
+ if (trim_string(ret, "\"", "\"")) {
+ if (strchr(ret,'"') != NULL)
+ StrnCpy(ret, s, len);
+ }
standard_sub_basic(current_user_info.smb_name,ret,len+100);
return (ret);
@@ -1445,6 +1471,7 @@ static char *lp_string(const char *s)
#define FN_LOCAL_INTEGER(fn_name,val) \
int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
+FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
@@ -1498,7 +1525,7 @@ FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
-FN_GLOBAL_STRING(lp_guestaccount, &Globals.szGuestaccount)
+FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
@@ -1527,6 +1554,7 @@ 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)
+FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
@@ -1642,6 +1670,7 @@ FN_LOCAL_LIST(lp_printer_admin, printer_admin)
FN_LOCAL_STRING(lp_fstype, fstype)
FN_LOCAL_STRING(lp_vfsobj, szVfsObjectFile)
FN_LOCAL_STRING(lp_vfs_options, szVfsOptions)
+FN_LOCAL_STRING(lp_vfs_path, szVfsPath)
static FN_LOCAL_STRING(lp_volume, volume)
FN_LOCAL_STRING(lp_mangled_map, szMangledMap)
FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
@@ -1658,6 +1687,7 @@ FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
FN_LOCAL_BOOL(lp_casemangle, bCaseMangle)
FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
+FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
FN_LOCAL_BOOL(lp_browseable, bBrowseable)
FN_LOCAL_BOOL(lp_readonly, bRead_only)
FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
@@ -1715,6 +1745,7 @@ FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
FN_GLOBAL_BOOL(lp_algorithmic_rid_base, &Globals.bAlgorithmicRidBase)
+FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
typedef struct _param_opt_struct param_opt_struct;
struct _param_opt_struct {
@@ -1904,8 +1935,8 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService,
if (i < 0)
return (False);
- if (!(*(ServicePtrs[i]->szPath))
- || strequal(ServicePtrs[i]->szPath, lp_pathname(-1))) {
+ if (!(*(ServicePtrs[iDefaultService]->szPath))
+ || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
pstrcpy(newHomedir, pszHomedir);
} else {
pstrcpy(newHomedir, lp_pathname(iDefaultService));
@@ -1925,7 +1956,7 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService,
ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
DEBUG(3,
- ("adding home's share [%s] for user %s at %s\n", pszHomename,
+ ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
user, newHomedir));
return (True);
@@ -1971,14 +2002,12 @@ static BOOL lp_add_ipc(char *ipc_name, BOOL guest_ok)
return (True);
}
-BOOL (*register_printer_fn)(const char *);
-
/***************************************************************************
add a new printer service, with defaults coming from service iFrom.
***************************************************************************/
-BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
+BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
{
- char *comment = "From Printcap";
+ const char *comment = "From Printcap";
int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
if (i < 0)
@@ -2005,8 +2034,6 @@ BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
DEBUG(3, ("adding printer service %s\n", pszPrintername));
update_server_announce_as_printserver();
- if (register_printer_fn && (!(*register_printer_fn)(pszPrintername)))
- return False;
return (True);
}
@@ -2623,6 +2650,7 @@ static BOOL handle_debug_list( char *pszParmValueIn, char **ptr )
pstring pszParmValue;
pstrcpy(pszParmValue, pszParmValueIn);
+ string_set(ptr, pszParmValueIn);
return debug_parse_levels( pszParmValue );
}
@@ -2844,7 +2872,7 @@ BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue)
break;
case P_LIST:
- *(char ***)parm_ptr = str_list_make(pszParmValue);
+ *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
break;
case P_STRING:
@@ -3485,8 +3513,8 @@ static void set_server_role(void)
case SEC_DOMAIN:
case SEC_ADS:
if (lp_domain_logons()) {
- server_role = ROLE_DOMAIN_BDC;
- DEBUG(10,("set_server_role:ROLE_DOMAIN_BDC\n"));
+ server_role = ROLE_DOMAIN_PDC;
+ DEBUG(10,("set_server_role:ROLE_DOMAIN_PDC\n"));
break;
}
server_role = ROLE_DOMAIN_MEMBER;
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index 4e3d558e987..a9c6f0729bd 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -157,6 +157,12 @@ NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd)
{
GROUP_MAP map;
+ const char *guest_account = lp_guestaccount();
+ if (!(guest_account && *guest_account)) {
+ DEBUG(1, ("NULL guest account!?!?\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
if (!pwd) {
return NT_STATUS_UNSUCCESSFUL;
}
@@ -183,24 +189,36 @@ NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd)
-- abartlet 11-May-02
*/
- if (!pdb_set_user_sid_from_rid(sam_account,
- fallback_pdb_uid_to_user_rid(pwd->pw_uid))) {
- DEBUG(0,("Can't set User SID from RID!\n"));
- return NT_STATUS_INVALID_PARAMETER;
- }
- /* call the mapping code here */
- if(get_group_map_from_gid(pwd->pw_gid, &map, MAPPING_WITHOUT_PRIV)) {
- if (!pdb_set_group_sid(sam_account,&map.sid)){
- DEBUG(0,("Can't set Group SID!\n"));
- return NT_STATUS_INVALID_PARAMETER;
+ /* Ensure this *must* be set right */
+ if (strcmp(pwd->pw_name, guest_account) == 0) {
+ if (!pdb_set_user_sid_from_rid(sam_account, DOMAIN_USER_RID_GUEST)) {
+ return NT_STATUS_UNSUCCESSFUL;
}
- }
- else {
- if (!pdb_set_group_sid_from_rid(sam_account,pdb_gid_to_group_rid(pwd->pw_gid))) {
- DEBUG(0,("Can't set Group SID\n"));
+ if (!pdb_set_group_sid_from_rid(sam_account, DOMAIN_GROUP_RID_GUESTS)) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ } else {
+
+ if (!pdb_set_user_sid_from_rid(sam_account,
+ fallback_pdb_uid_to_user_rid(pwd->pw_uid))) {
+ DEBUG(0,("Can't set User SID from RID!\n"));
return NT_STATUS_INVALID_PARAMETER;
}
+
+ /* call the mapping code here */
+ if(get_group_map_from_gid(pwd->pw_gid, &map, MAPPING_WITHOUT_PRIV)) {
+ if (!pdb_set_group_sid(sam_account,&map.sid)){
+ DEBUG(0,("Can't set Group SID!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ else {
+ if (!pdb_set_group_sid_from_rid(sam_account,pdb_gid_to_group_rid(pwd->pw_gid))) {
+ DEBUG(0,("Can't set Group SID\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
}
/* check if this is a user account or a machine account */
@@ -528,6 +546,9 @@ BOOL pdb_rid_is_user(uint32 rid)
* such that it can be identified as either a user, group etc
* type. there are 5 such categories, and they are documented.
*/
+ /* However, they are not in the RID, just somthing you can query
+ seperatly. Sorry luke :-) */
+
if(pdb_rid_is_well_known(rid)) {
/*
* The only well known user RIDs are DOMAIN_USER_RID_ADMIN
@@ -571,14 +592,6 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use
fstrcpy(name, "Administrator");
}
return True;
-
- } else if (rid == DOMAIN_USER_RID_GUEST) {
- char *p = lp_guestaccount();
- *psid_name_use = SID_NAME_USER;
- if(!next_token(&p, name, NULL, sizeof(fstring)))
- fstrcpy(name, "Guest");
- return True;
-
}
/*
@@ -594,6 +607,7 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use
}
/* This now does the 'generic' mapping in pdb_unix */
+ /* 'guest' is also handled there */
if (pdb_getsampwsid(sam_account, sid)) {
fstrcpy(name, pdb_get_username(sam_account));
*psid_name_use = SID_NAME_USER;
@@ -716,15 +730,9 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi
/* check if it's a mapped group */
if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) {
- if (map.gid!=-1) {
- /* yes it's a mapped group to a valid unix group */
- sid_copy(&local_sid, &map.sid);
- *psid_name_use = map.sid_name_use;
- }
- else {
- /* it's a correct name but not mapped so it points to nothing*/
- return False;
- }
+ /* yes it's a mapped group */
+ sid_copy(&local_sid, &map.sid);
+ *psid_name_use = map.sid_name_use;
} else {
/* it's not a mapped group */
grp = getgrnam(user);
@@ -777,6 +785,8 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
if (pdb_getsampwnam(sam_user, pass->pw_name)) {
sid_copy(psid, pdb_get_user_sid(sam_user));
+ } else if (strcmp(pass->pw_name, lp_guestaccount()) == 0) {
+ sid_append_rid(psid, DOMAIN_USER_RID_GUEST);
} else {
sid_append_rid(psid, fallback_pdb_uid_to_user_rid(uid));
}
@@ -802,25 +812,13 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
Convert a SID to uid - locally.
****************************************************************************/
-BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type)
+BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_type)
{
- DOM_SID dom_sid;
- uint32 rid;
fstring str;
SAM_ACCOUNT *sam_user = NULL;
*name_type = SID_NAME_UNKNOWN;
- sid_copy(&dom_sid, psid);
- sid_split_rid(&dom_sid, &rid);
-
- /*
- * We can only convert to a uid if this is our local
- * Domain SID (ie. we are the controling authority).
- */
- if (!sid_equal(get_global_sam_sid(), &dom_sid))
- return False;
-
if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user)))
return False;
@@ -832,12 +830,37 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type)
}
DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid),
(unsigned int)*puid, pdb_get_username(sam_user)));
- } else {
- DEBUG(5,("local_sid_to_uid: SID %s not mapped becouse RID was not found in passdb.\n", sid_to_string( str, psid)));
pdb_free_sam(&sam_user);
- return False;
+ } else {
+
+ DOM_SID dom_sid;
+ uint32 rid;
+ GROUP_MAP map;
+
+ pdb_free_sam(&sam_user);
+
+ if (get_group_map_from_sid(*psid, &map, MAPPING_WITHOUT_PRIV)) {
+ DEBUG(3, ("local_sid_to_uid: SID '%s' is a group, not a user... \n", sid_to_string(str, psid)));
+ /* It's a group, not a user... */
+ return False;
+ }
+
+ sid_copy(&dom_sid, psid);
+ if (!sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
+ DEBUG(3, ("sid_peek_rid failed - sid '%s' is not in our domain\n", sid_to_string(str, psid)));
+ return False;
+ }
+
+ if (!pdb_rid_is_user(rid)) {
+ DEBUG(3, ("local_sid_to_uid: sid '%s' cannot be mapped to a uid algorithmicly becouse it is a group\n", sid_to_string(str, psid)));
+ return False;
+ }
+
+ *puid = fallback_pdb_user_rid_to_uid(rid);
+
+ DEBUG(5,("local_sid_to_uid: SID %s algorithmicly mapped to %ld mapped becouse SID was not found in passdb.\n",
+ sid_to_string(str, psid), (signed long int)(*puid)));
}
- pdb_free_sam(&sam_user);
*name_type = SID_NAME_USER;
@@ -868,18 +891,13 @@ DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
Convert a SID to gid - locally.
****************************************************************************/
-BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
+BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_type)
{
- DOM_SID dom_sid;
- uint32 rid;
fstring str;
GROUP_MAP map;
*name_type = SID_NAME_UNKNOWN;
- sid_copy(&dom_sid, psid);
- sid_split_rid(&dom_sid, &rid);
-
/*
* We can only convert to a gid if this is our local
* Domain SID (ie. we are the controling authority).
@@ -887,35 +905,45 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
* Or in the Builtin SID too. JFM, 11/30/2001
*/
- if (!sid_equal(get_global_sam_sid(), &dom_sid))
- return False;
-
if (get_group_map_from_sid(*psid, &map, MAPPING_WITHOUT_PRIV)) {
/* the SID is in the mapping table but not mapped */
if (map.gid==-1)
return False;
- if (!sid_peek_check_rid(get_global_sam_sid(), &map.sid, &rid)){
- DEBUG(0,("local_sid_to_gid: sid_peek_check_rid return False! SID: %s\n",
- sid_string_static(&map.sid)));
- return False;
- }
*pgid = map.gid;
*name_type = map.sid_name_use;
- DEBUG(10,("local_sid_to_gid: mapped SID %s (%s) -> gid (%u).\n", sid_to_string( str, psid),
+ DEBUG(10,("local_sid_to_gid: mapped SID %s (%s) -> gid (%u).\n",
+ sid_to_string( str, psid),
map.nt_name, (unsigned int)*pgid));
} else {
- if (pdb_rid_is_user(rid))
+ uint32 rid;
+ SAM_ACCOUNT *sam_user = NULL;
+ if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user)))
+ return False;
+
+ if (pdb_getsampwsid(sam_user, psid)) {
return False;
+ pdb_free_sam(&sam_user);
+ }
+
+ pdb_free_sam(&sam_user);
+ if (!sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
+ DEBUG(3, ("sid_peek_rid failed - sid '%s' is not in our domain\n", sid_to_string(str, psid)));
+ return False;
+ }
+
+ if (pdb_rid_is_user(rid))
+ return False;
+
*pgid = pdb_group_rid_to_gid(rid);
*name_type = SID_NAME_ALIAS;
DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u).\n", sid_to_string( str, psid),
(unsigned int)*pgid));
}
-
+
return True;
}
diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c
index dff4b40f4de..2da6de72701 100644
--- a/source/passdb/pdb_get_set.c
+++ b/source/passdb/pdb_get_set.c
@@ -250,7 +250,7 @@ const char* pdb_get_unix_homedir (const SAM_ACCOUNT *sampass)
return (NULL);
}
-const char* pdb_get_dirdrive (const SAM_ACCOUNT *sampass)
+const char* pdb_get_dir_drive (const SAM_ACCOUNT *sampass)
{
if (sampass)
return (sampass->private.dir_drive);
@@ -1028,15 +1028,14 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
if (!pdb_set_pass_last_set_time (sampass, time(NULL)))
return False;
- account_policy_get(AP_MAX_PASSWORD_AGE, &expire);
-
- if (expire==(uint32)-1) {
+ if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire)
+ || (expire==(uint32)-1)) {
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, True))
+ pdb_get_pass_last_set_time(sampass)
+ + expire, True))
return False;
}
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index 3b0f54b2b3a..f311223d772 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -123,7 +123,7 @@ static BOOL context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_ac
return False;
}
-static BOOL context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, DOM_SID *sid)
+static BOOL context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
{
struct pdb_methods *curmethods;
if ((!context)) {
@@ -353,7 +353,7 @@ NTSTATUS make_pdb_context_list(struct pdb_context **context, char **selected)
NTSTATUS make_pdb_context_string(struct pdb_context **context, const char *selected)
{
NTSTATUS ret;
- char **newsel = str_list_make(selected);
+ char **newsel = str_list_make(selected, NULL);
ret = make_pdb_context_list(context, newsel);
str_list_free(&newsel);
return ret;
@@ -434,7 +434,7 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
return pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username);
}
-BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, DOM_SID *sid)
+BOOL pdb_getsampwsid(SAM_ACCOUNT *sam_acct, const DOM_SID *sid)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 24eb7b9dc1f..f82cb4488fc 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -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
@@ -70,8 +71,14 @@ struct ldapsam_privates {
uint32 low_nua_rid;
uint32 high_nua_rid;
+
+ char *bind_dn;
+ char *bind_secret;
};
+
+static struct ldapsam_privates *static_ldap_state;
+
static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_state);
/*******************************************************************
@@ -153,11 +160,13 @@ static const char *attr[] = {"uid", "pwdLastSet", "logonTime",
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;
}
-
+
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri));
@@ -165,6 +174,16 @@ static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP *
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 */
@@ -173,7 +192,6 @@ static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP *
int rc;
int tls = LDAP_OPT_X_TLS_HARD;
int port = 0;
- int version;
fstring protocol;
fstring host;
const char *p = ldap_state->uri;
@@ -252,43 +270,92 @@ static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP *
/*******************************************************************
- Add a rebind function for authenticated referrals
+ a rebind function for authenticated referrals
+ This version takes a void* that we can shove useful stuff in :-)
******************************************************************/
-static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
- int *method, int freeit )
+static int rebindproc_with_state (LDAP * ld, char **whop, char **credp,
+ int *methodp, int freeit, void *arg)
{
- int rc;
- char *ldap_dn;
- char *ldap_secret;
+ struct ldapsam_privates *ldap_state = arg;
/** @TODO Should we be doing something to check what servers we rebind to?
Could we get a referral to a machine that we don't want to give our
username and password to? */
- if (freeit != 0)
- {
-
- if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
- {
- DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
- return LDAP_OPERATIONS_ERROR; /* No idea what to return */
- }
-
+ if (freeit) {
+ SAFE_FREE(*whop);
+ memset(*credp, '\0', strlen(*credp));
+ SAFE_FREE(*credp);
+ } else {
DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n",
- ldap_dn));
-
- rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
-
- SAFE_FREE(ldap_dn);
- SAFE_FREE(ldap_secret);
+ ldap_state->bind_dn));
- return rc;
+ *whop = strdup(ldap_state->bind_dn);
+ if (!*whop) {
+ return LDAP_NO_MEMORY;
+ }
+ *credp = strdup(ldap_state->bind_secret);
+ if (!*credp) {
+ SAFE_FREE(*whop);
+ return LDAP_NO_MEMORY;
+ }
+ *methodp = LDAP_AUTH_SIMPLE;
}
return 0;
}
/*******************************************************************
+ a rebind function for authenticated referrals
+ This version takes a void* that we can shove useful stuff in :-)
+ and actually does the connection.
+******************************************************************/
+
+static int rebindproc_connect_with_state (LDAP *ldap_struct,
+ LDAP_CONST char *url,
+ ber_tag_t request,
+ ber_int_t msgid, void *arg)
+{
+ struct ldapsam_privates *ldap_state = arg;
+ int rc;
+ DEBUG(5,("ldap_connect_system: Rebinding as \"%s\"\n",
+ ldap_state->bind_dn));
+
+ /** @TODO Should we be doing something to check what servers we rebind to?
+ Could we get a referral to a machine that we don't want to give our
+ username and password to? */
+
+ rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
+
+ return rc;
+}
+
+/*******************************************************************
+ Add a rebind function for authenticated referrals
+******************************************************************/
+
+static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
+ int *method, int freeit )
+{
+ return rebindproc_with_state(ldap_struct, whop, credp,
+ method, freeit, static_ldap_state);
+
+}
+
+/*******************************************************************
+ a rebind function for authenticated referrals
+ this also does the connection, but no void*.
+******************************************************************/
+
+static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
+ ber_int_t msgid)
+{
+ return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid,
+ static_ldap_state);
+}
+
+
+/*******************************************************************
connect to the ldap server under system privilege.
******************************************************************/
static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct)
@@ -297,6 +364,10 @@ static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * l
char *ldap_dn;
char *ldap_secret;
+ /* The rebind proc needs this *HACK*. We are not multithreaded, so
+ this will work, but it's not nice. */
+ static_ldap_state = ldap_state;
+
/* get the password */
if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
{
@@ -304,19 +375,32 @@ static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * l
return False;
}
+ ldap_state->bind_dn = ldap_dn;
+ ldap_state->bind_secret = ldap_secret;
+
/* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
(OpenLDAP) doesnt' seem to support it */
DEBUG(10,("ldap_connect_system: Binding to ldap server as \"%s\"\n",
ldap_dn));
-
- ldap_set_rebind_proc(ldap_struct, (LDAP_REBIND_PROC *)(&rebindproc));
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+# if LDAP_SET_REBIND_PROC_ARGS == 2
+ ldap_set_rebind_proc(ldap_struct, &rebindproc_connect);
+# endif
+# if LDAP_SET_REBIND_PROC_ARGS == 3
+ ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);
+# endif
+#else
+# if LDAP_SET_REBIND_PROC_ARGS == 2
+ ldap_set_rebind_proc(ldap_struct, &rebindproc);
+# endif
+# if LDAP_SET_REBIND_PROC_ARGS == 3
+ ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);
+# endif
+#endif
rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
- SAFE_FREE(ldap_dn);
- SAFE_FREE(ldap_secret);
-
if (rc != LDAP_SUCCESS)
{
DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
@@ -756,18 +840,20 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
/* leave as default */
} else {
pdb_gethexpwd(temp, smblmpwd);
- memset((char *)temp, '\0', sizeof(temp));
+ memset((char *)temp, '\0', strlen(temp)+1);
if (!pdb_set_lanman_passwd(sampass, smblmpwd))
return False;
+ ZERO_STRUCT(smblmpwd);
}
if (!get_single_attribute (ldap_struct, entry, "ntPassword", temp)) {
/* leave as default */
} else {
pdb_gethexpwd(temp, smbntpwd);
- memset((char *)temp, '\0', sizeof(temp));
+ memset((char *)temp, '\0', strlen(temp)+1);
if (!pdb_set_nt_passwd(sampass, smbntpwd))
return False;
+ ZERO_STRUCT(smbntpwd);
}
if (!get_single_attribute (ldap_struct, entry, "acctFlags", temp)) {
@@ -880,7 +966,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass));
if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE))
- make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dirdrive(sampass));
+ make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dir_drive(sampass));
if (IS_SAM_SET(sampass, FLAG_SAM_LOGONSCRIPT))
make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass));
@@ -1153,6 +1239,10 @@ static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * us
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
BOOL ret = False;
+ /* The rebind proc needs this *HACK*. We are not multithreaded, so
+ this will work, but it's not nice. */
+ static_ldap_state = ldap_state;
+
while (!ret) {
if (!ldap_state->entry)
return False;
@@ -1203,7 +1293,7 @@ static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * us
if (entry)
{
if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
- DEBUG(0,("ldapsam_getsampwnam: init_sam_from_ldap failed!\n"));
+ DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
ldap_msgfree(result);
ldap_unbind(ldap_struct);
return False;
@@ -1247,7 +1337,7 @@ static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * us
if (ldap_count_entries(ldap_struct, result) < 1)
{
- DEBUG(0,
+ DEBUG(4,
("We don't find this rid [%i] count=%d\n", rid,
ldap_count_entries(ldap_struct, result)));
ldap_unbind(ldap_struct);
@@ -1258,7 +1348,7 @@ static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * us
if (entry)
{
if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
- DEBUG(0,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
+ DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
ldap_msgfree(result);
ldap_unbind(ldap_struct);
return False;
@@ -1275,7 +1365,7 @@ static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * us
}
}
-static BOOL ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid)
+static BOOL ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
{
uint32 rid;
if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
@@ -1530,6 +1620,13 @@ static void free_private_data(void **vp)
ldap_unbind((*ldap_state)->ldap_struct);
}
+ if ((*ldap_state)->bind_secret) {
+ memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret));
+ }
+
+ SAFE_FREE((*ldap_state)->bind_dn);
+ SAFE_FREE((*ldap_state)->bind_secret);
+
*ldap_state = NULL;
/* No need to free any further, as it is talloc()ed */
diff --git a/source/passdb/pdb_nisplus.c b/source/passdb/pdb_nisplus.c
index 9c5b2e1171b..2d37c3b8fbb 100644
--- a/source/passdb/pdb_nisplus.c
+++ b/source/passdb/pdb_nisplus.c
@@ -735,17 +735,17 @@ static BOOL init_nisp_from_sam(nis_object *obj, const SAM_ACCOUNT *sampass,
/* dir_drive */
/* must support set, unset and change */
- if( (pdb_get_dirdrive(sampass) &&
+ if( (pdb_get_dir_drive(sampass) &&
!ENTRY_VAL(old, NPF_DIR_DRIVE)) ||
(ENTRY_VAL(old, NPF_DIR_DRIVE) &&
- !pdb_get_dirdrive(sampass)) ||
+ !pdb_get_dir_drive(sampass)) ||
(ENTRY_VAL(old, NPF_DIR_DRIVE) &&
- pdb_get_dirdrive(sampass) &&
+ pdb_get_dir_drive(sampass) &&
strcmp( ENTRY_VAL(old, NPF_DIR_DRIVE),
- pdb_get_dirdrive(sampass)))) {
+ pdb_get_dir_drive(sampass)))) {
need_to_modify = True;
- set_single_attribute(obj, NPF_DIR_DRIVE, pdb_get_dirdrive(sampass),
- strlen(pdb_get_dirdrive(sampass)), EN_MODIFIED);
+ set_single_attribute(obj, NPF_DIR_DRIVE, pdb_get_dir_drive(sampass),
+ strlen(pdb_get_dir_drive(sampass)), EN_MODIFIED);
}
/* logon_script */
@@ -860,7 +860,7 @@ static BOOL init_nisp_from_sam(nis_object *obj, const SAM_ACCOUNT *sampass,
set_single_attribute(obj, NPF_HOME_DIR,
homedir, strlen(homedir), 0);
- if(!(dirdrive = pdb_get_dirdrive(sampass)))
+ if(!(dirdrive = pdb_get_dir_drive(sampass)))
dirdrive = empty;
set_single_attribute(obj, NPF_DIR_DRIVE,
@@ -1032,7 +1032,7 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT * user, const char *sname)
Routine to search the nisplus passwd file for an entry matching the username
*************************************************************************/
-BOOL pdb_getsampwsid(SAM_ACCOUNT * user, DOM_SID *sid)
+BOOL pdb_getsampwsid(SAM_ACCOUNT * user, const DOM_SID *sid)
{
uint32 rid;
if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c
index 8c7ba364b8a..d40ea03511c 100644
--- a/source/passdb/pdb_smbpasswd.c
+++ b/source/passdb/pdb_smbpasswd.c
@@ -1149,7 +1149,7 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
uid = pdb_get_uid(sampass);
/* If the user specified a RID, make sure its able to be both stored and retreived */
- if (rid && uid != fallback_pdb_user_rid_to_uid(rid)) {
+ if (rid && rid != DOMAIN_USER_RID_GUEST && uid != fallback_pdb_user_rid_to_uid(rid)) {
DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n"));
return False;
}
@@ -1417,7 +1417,7 @@ static BOOL smbpasswd_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *s
return True;
}
-static BOOL smbpasswd_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid)
+static BOOL smbpasswd_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
{
uint32 rid;
if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c
index 62793189696..27453fc1af7 100644
--- a/source/passdb/pdb_tdb.c
+++ b/source/passdb/pdb_tdb.c
@@ -354,7 +354,8 @@ static uint32 init_buffer_from_sam (struct tdbsam_privates *tdb_state,
* Only updates fields which have been set (not defaults from smb.conf)
*/
- if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE)) dir_drive = pdb_get_dirdrive(sampass);
+ if (IS_SAM_SET(sampass, FLAG_SAM_DRIVE))
+ dir_drive = pdb_get_dir_drive(sampass);
else dir_drive = NULL;
if (dir_drive) dir_drive_len = strlen(dir_drive) +1;
else dir_drive_len = 0;
@@ -541,7 +542,7 @@ static BOOL tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user
/* increment to next in line */
tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
- /* do we have an valid interation pointer? */
+ /* do we have an valid iteration pointer? */
if(tdb_state->passwd_tdb == NULL) {
DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n"));
return False;
@@ -668,7 +669,7 @@ static BOOL tdbsam_getsampwrid (struct pdb_methods *my_methods, SAM_ACCOUNT *use
return tdbsam_getsampwnam (my_methods, user, name);
}
-static BOOL tdbsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid)
+static BOOL tdbsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
{
uint32 rid;
if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
diff --git a/source/passdb/pdb_unix.c b/source/passdb/pdb_unix.c
index b4092b88f8a..06f12164eb8 100644
--- a/source/passdb/pdb_unix.c
+++ b/source/passdb/pdb_unix.c
@@ -49,23 +49,36 @@ static BOOL unixsam_getsampwrid (struct pdb_methods *methods,
{
struct passwd *pass;
BOOL ret = False;
+ const char *guest_account = lp_guestaccount();
+ if (!(guest_account && *guest_account)) {
+ DEBUG(1, ("NULL guest account!?!?\n"));
+ return False;
+ }
+
if (!methods) {
DEBUG(0,("invalid methods\n"));
return False;
}
-
- if (pdb_rid_is_user(rid)) {
- pass = getpwuid_alloc(fallback_pdb_user_rid_to_uid (rid));
-
- if (pass) {
- ret = NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass));
- passwd_free(&pass);
+
+ if (rid == DOMAIN_USER_RID_GUEST) {
+ pass = getpwnam_alloc(guest_account);
+ if (!pass) {
+ DEBUG(1, ("guest account %s does not seem to exist...\n", guest_account));
+ return False;
}
+ } else if (pdb_rid_is_user(rid)) {
+ pass = getpwuid_alloc(fallback_pdb_user_rid_to_uid (rid));
+ } else {
+ return False;
}
+
+ ret = NT_STATUS_IS_OK(pdb_fill_sam_pw(user, pass));
+ passwd_free(&pass);
+
return ret;
}
-static BOOL unixsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, DOM_SID *sid)
+static BOOL unixsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
{
uint32 rid;
if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c
index 3ecaf52e586..ec67b743900 100644
--- a/source/passdb/secrets.c
+++ b/source/passdb/secrets.c
@@ -128,6 +128,47 @@ BOOL secrets_fetch_domain_sid(char *domain, DOM_SID *sid)
return True;
}
+BOOL secrets_store_domain_guid(char *domain, GUID *guid)
+{
+ fstring key;
+
+ slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
+ strupper(key);
+ return secrets_store(key, guid, sizeof(GUID));
+}
+
+BOOL secrets_fetch_domain_guid(char *domain, GUID *guid)
+{
+ GUID *dyn_guid;
+ fstring key;
+ size_t size;
+ GUID new_guid;
+
+ slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
+ strupper(key);
+ dyn_guid = (GUID *)secrets_fetch(key, &size);
+
+ DEBUG(6,("key is %s, guid is at %x, size is %d\n", key, dyn_guid, size));
+
+ if ((NULL == dyn_guid) && (ROLE_DOMAIN_PDC == lp_server_role())) {
+ uuid_generate_random(&new_guid);
+ if (!secrets_store_domain_guid(domain, &new_guid))
+ return False;
+ dyn_guid = (GUID *)secrets_fetch(key, &size);
+ if (dyn_guid == NULL)
+ return False;
+ }
+
+ if (size != sizeof(GUID))
+ {
+ SAFE_FREE(dyn_guid);
+ return False;
+ }
+
+ *guid = *dyn_guid;
+ SAFE_FREE(dyn_guid);
+ return True;
+}
/**
* Form a key for fetching the machine trust account password
@@ -178,7 +219,7 @@ BOOL secrets_fetch_trust_account_password(char *domain, uint8 ret_pwd[16],
if (plaintext) {
/* we have an ADS password - use that */
DEBUG(4,("Using ADS machine password\n"));
- E_md4hash((uchar *)plaintext, ret_pwd);
+ E_md4hash(plaintext, ret_pwd);
SAFE_FREE(plaintext);
return True;
}
@@ -388,7 +429,9 @@ BOOL secrets_store_ldap_pw(const char* dn, char* pw)
/**
- * The linked list is allocated on the supplied talloc context, caller gets to destory
+ * Get trusted domains info from secrets.tdb.
+ *
+ * The linked list is allocated on the supplied talloc context, caller gets to destroy
* when done.
*
* @param ctx Allocation context
@@ -409,10 +452,11 @@ NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, int max_num
int start_idx;
uint32 idx = 0;
size_t size;
+ fstring dom_name;
struct trusted_dom_pass *pass;
NTSTATUS status;
- secrets_init();
+ if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
*num_domains = 0;
start_idx = *enum_ctx;
@@ -455,6 +499,10 @@ NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, int max_num
SAFE_FREE(pass);
continue;
}
+
+ pull_ucs2_fstring(dom_name, pass->uni_name);
+ DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
+ idx, dom_name, sid_string_static(&pass->domain_sid)));
SAFE_FREE(secrets_key);
@@ -475,6 +523,10 @@ NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, int max_num
dom->name = talloc_strdup_w(ctx, pass->uni_name);
(*domains)[idx - start_idx] = dom;
+
+ DEBUG(18, ("Secret record is in required range.\n \
+ start_idx = %d, max_num_domains = %d. Added to returned array.\n",
+ start_idx, max_num_domains));
*enum_ctx = idx + 1;
(*num_domains)++;
@@ -487,6 +539,10 @@ NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, int max_num
/* this is the last entry in the whole enumeration */
status = NT_STATUS_OK;
}
+ } else {
+ DEBUG(18, ("Secret is outside the required range.\n \
+ start_idx = %d, max_num_domains = %d. Not added to returned array\n",
+ start_idx, max_num_domains));
}
idx++;
diff --git a/source/passdb/util_sam_sid.c b/source/passdb/util_sam_sid.c
index 2c574f4a61e..6ec1e48ab3a 100644
--- a/source/passdb/util_sam_sid.c
+++ b/source/passdb/util_sam_sid.c
@@ -95,6 +95,9 @@ static void init_sid_name_map (void)
if ((lp_security() == SEC_USER) && lp_domain_logons()) {
sid_name_map[i].sid = get_global_sam_sid();
+ /* This is not lp_workgroup() for good reason:
+ it must stay around longer than the lp_*()
+ strings do */
sid_name_map[i].name = global_myworkgroup;
sid_name_map[i].known_users = NULL;
i++;
diff --git a/source/printing/pcap.c b/source/printing/pcap.c
index 4bca63fffb1..86489e9587c 100644
--- a/source/printing/pcap.c
+++ b/source/printing/pcap.c
@@ -241,15 +241,12 @@ static BOOL ScanQconfig(char *psz,char *pszPrintername)
Scan printcap file pszPrintcapname for a printer called pszPrintername.
Return True if found, else False. Returns False on error, too, after logging
the error at level 0. For generality, the printcap name may be passed - if
-passed as NULL, the configuration will be queried for the name. pszPrintername
-must be in DOS codepage.
-The xxx_printername_ok functions need fixing to understand they are being
-given a DOS codepage. FIXME !! JRA.
+passed as NULL, the configuration will be queried for the name.
***************************************************************************/
-BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)
+BOOL pcap_printername_ok(const char *pszPrintername, const char *pszPrintcapname)
{
char *line=NULL;
- char *psz;
+ const char *psz;
char *p,*q;
XFILE *pfile;
@@ -305,8 +302,6 @@ BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)
if (strequal(p,pszPrintername))
{
- /* normalise the case */
- pstrcpy(pszPrintername,p);
SAFE_FREE(line);
x_fclose(pfile);
return(True);
diff --git a/source/printing/print_svid.c b/source/printing/print_svid.c
index 44127c3700a..837a2fba483 100644
--- a/source/printing/print_svid.c
+++ b/source/printing/print_svid.c
@@ -126,7 +126,7 @@ void sysv_printer_fn(void (*fn)(char *, char *))
* provide the equivalent of pcap_printername_ok() for SVID/XPG4 conforming
* systems.
*/
-int sysv_printername_ok(char *name)
+int sysv_printername_ok(const char *name)
{
printer_t *tmp;
diff --git a/source/printing/printfsp.c b/source/printing/printfsp.c
index 9f33d57ad52..ff50ac47c49 100644
--- a/source/printing/printfsp.c
+++ b/source/printing/printfsp.c
@@ -54,7 +54,7 @@ files_struct *print_fsp_open(connection_struct *conn, char *fname)
/* setup a full fsp */
fsp->print_jobid = jobid;
- fsp->fd = print_job_fd(jobid);
+ fsp->fd = print_job_fd(SNUM(conn),jobid);
GetTimeOfDay(&fsp->open_time);
fsp->vuid = current_user.vuid;
fsp->size = 0;
@@ -70,7 +70,7 @@ files_struct *print_fsp_open(connection_struct *conn, char *fname)
fsp->is_directory = False;
fsp->directory_delete_on_close = False;
fsp->conn = conn;
- string_set(&fsp->fsp_name,print_job_fname(jobid));
+ string_set(&fsp->fsp_name,print_job_fname(SNUM(conn),jobid));
fsp->wbmpx_ptr = NULL;
fsp->wcp = NULL;
conn->vfs_ops.fstat(fsp,fsp->fd, &sbuf);
@@ -96,7 +96,7 @@ void print_fsp_end(files_struct *fsp, BOOL normal_close)
sys_ftruncate(fsp->fd, 0);
}
- print_job_end(fsp->print_jobid, normal_close);
+ print_job_end(SNUM(fsp->conn),fsp->print_jobid, normal_close);
if (fsp->fsp_name) {
string_free(&fsp->fsp_name);
diff --git a/source/printing/printing.c b/source/printing/printing.c
index 7bfce43af61..cb689c05d66 100644
--- a/source/printing/printing.c
+++ b/source/printing/printing.c
@@ -39,98 +39,97 @@ static struct printif *current_printif = &generic_printif;
jobids are assigned when a job starts spooling.
*/
-static pid_t local_pid;
-
-/* Mapping between printer names and queue id's in job id's. */
-struct printer_queueid_map {
- struct printer_queueid_map *next, *prev;
- char *printername;
- uint32 queueid;
-};
-
-static struct printer_queueid_map *printer_queueid_map_head;
-static uint32 last_queueid;
-
-#define QUEUEID_BITS 12
-#define QUEUEID_MASK ((1<<(QUEUEID_BITS))-1)
-#define QUEUEID_TO_JOBID(queueid) (((queueid) & QUEUEID_MASK) << 20 )
+/***************************************************************************
+ Nightmare. LANMAN jobid's are 16 bit numbers..... We must map them to 32
+ bit RPC jobids.... JRA.
+***************************************************************************/
-/****************************************************************************
- Create an association between a printer name and a queueid. Used to encode
- the printer queueid in jobid's.
- This could be converted to use an internal tdb if searching the list is
- too slow. JRA.
-****************************************************************************/
+static TDB_CONTEXT *rap_tdb;
+static uint16 next_rap_jobid;
-BOOL create_printer_queueid(const char *printername)
+uint16 pjobid_to_rap(int snum, uint32 jobid)
{
- struct printer_queueid_map *p;
+ uint16 rap_jobid;
+ TDB_DATA data, key;
+ char jinfo[8];
- for (p = printer_queueid_map_head; p; p = p->next) {
- if (strequal(p->printername, printername))
- return True;
+ if (!rap_tdb) {
+ /* Create the in-memory tdb. */
+ rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
+ if (!rap_tdb)
+ return 0;
}
- p = (struct printer_queueid_map *)malloc(sizeof(*p));
- if (!p) {
- DEBUG(0,("create_printer_queueid: malloc fail !\n"));
- return False;
- }
- ZERO_STRUCTP(p);
- p->printername = strdup(printername);
- if (!p->printername) {
- DEBUG(0,("create_printer_queueid: malloc fail !\n"));
- SAFE_FREE(p);
- return False;
- }
- p->queueid = (++last_queueid);
- if (p->queueid > QUEUEID_MASK) {
- DEBUG(0,("create_printer_queueid: malloc fail !\n"));
- SAFE_FREE(p->printername);
- SAFE_FREE(p);
- return False;
+ SIVAL(&jinfo,0,(int32)snum);
+ SIVAL(&jinfo,4,jobid);
+
+ key.dptr = (char *)&jinfo;
+ key.dsize = sizeof(jinfo);
+ data = tdb_fetch(rap_tdb, key);
+ if (data.dptr && data.dsize == sizeof(uint16)) {
+ memcpy(&rap_jobid, data.dptr, sizeof(uint16));
+ SAFE_FREE(data.dptr);
+ return rap_jobid;
}
- DLIST_ADD(printer_queueid_map_head, p);
- return True;
+ /* Not found - create and store mapping. */
+ rap_jobid = ++next_rap_jobid;
+ if (rap_jobid == 0)
+ rap_jobid = ++next_rap_jobid;
+ data.dptr = (char *)&rap_jobid;
+ data.dsize = sizeof(rap_jobid);
+ tdb_store(rap_tdb, key, data, TDB_REPLACE);
+ tdb_store(rap_tdb, data, key, TDB_REPLACE);
+ return rap_jobid;
}
-void set_register_printer_fn(void)
+BOOL rap_to_pjobid(uint16 rap_jobid, int *psnum, uint32 *pjobid)
{
- extern BOOL (*register_printer_fn)(const char *);
- register_printer_fn = create_printer_queueid;
-}
-
-/****************************************************************************
- Lookups.
-****************************************************************************/
+ TDB_DATA data, key;
+ char jinfo[8];
-static uint32 get_printer_queueid_byname(const char *printername)
-{
- struct printer_queueid_map *p;
+ if (!rap_tdb)
+ return False;
- for (p = printer_queueid_map_head; p; p = p->next) {
- if (strequal(p->printername, printername))
- return p->queueid;
+ key.dptr = (char *)&rap_jobid;
+ key.dsize = sizeof(rap_jobid);
+ data = tdb_fetch(rap_tdb, key);
+ if (data.dptr && data.dsize == sizeof(jinfo)) {
+ *psnum = IVAL(&jinfo,0);
+ *pjobid = IVAL(&jinfo,4);
+ SAFE_FREE(data.dptr);
+ return True;
}
- return 0;
+ return False;
}
-/****************************************************************************
- Lookups.
-****************************************************************************/
-
-static const char *get_printer_name_byjobid(uint32 jobid)
+static void rap_jobid_delete(int snum, uint32 jobid)
{
- struct printer_queueid_map *p;
- uint32 queueid = (((jobid)>>20) & QUEUEID_MASK);
+ TDB_DATA key, data;
+ uint16 rap_jobid;
+ char jinfo[8];
- for (p = printer_queueid_map_head; p; p = p->next) {
- if (p->queueid == queueid)
- return p->printername;
- }
- return NULL;
+ if (!rap_tdb)
+ return;
+
+ SIVAL(&jinfo,0,(int32)snum);
+ SIVAL(&jinfo,4,jobid);
+
+ key.dptr = (char *)&jinfo;
+ key.dsize = sizeof(jinfo);
+ data = tdb_fetch(rap_tdb, key);
+ if (!data.dptr || (data.dsize != sizeof(uint16)))
+ return;
+
+ memcpy(&rap_jobid, data.dptr, sizeof(uint16));
+ SAFE_FREE(data.dptr);
+ data.dptr = (char *)&rap_jobid;
+ data.dsize = sizeof(rap_jobid);
+ tdb_delete(rap_tdb, key);
+ tdb_delete(rap_tdb, data);
}
+static pid_t local_pid;
+
static int get_queue_status(int, print_status_struct *);
#define MAX_PRINT_DBS_OPEN 1
@@ -186,9 +185,14 @@ static struct tdb_print_db *get_print_db_byname(const char *printername)
DLIST_ADD(print_db_head, p);
}
- pstrcpy(printdb_path, lock_path(printername));
+ pstrcpy(printdb_path, lock_path("printing/"));
+ pstrcat(printdb_path, printername);
pstrcat(printdb_path, ".tdb");
+
+ become_root();
p->tdb = tdb_open_log(printdb_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+ unbecome_root();
+
if (!p->tdb) {
DEBUG(0,("get_print_db: Failed to open printer backend database %s.\n",
printdb_path ));
@@ -200,14 +204,6 @@ static struct tdb_print_db *get_print_db_byname(const char *printername)
return p;
}
-static struct tdb_print_db *get_print_db_byjobid( uint32 jobid)
-{
- const char *printername = get_printer_name_byjobid(jobid);
- if (!printername)
- return NULL;
- return get_print_db_byname(printername);
-}
-
/****************************************************************************
Initialise the printing backend. Called once at startup.
Does not survive a fork
@@ -215,20 +211,28 @@ static struct tdb_print_db *get_print_db_byjobid( uint32 jobid)
BOOL print_backend_init(void)
{
- struct printer_queueid_map *p;
char *sversion = "INFO/version";
+ pstring printing_path;
+ int services = lp_numservices();
+ int snum;
if (local_pid == sys_getpid())
return True;
unlink(lock_path("printing.tdb"));
+ pstrcpy(printing_path,lock_path("printing"));
+ mkdir(printing_path,0755);
+
local_pid = sys_getpid();
/* handle a Samba upgrade */
- for (p = printer_queueid_map_head; p; p = p->next) {
- struct tdb_print_db *pdb = get_print_db_byname(p->printername);
+ for (snum = 0; snum < services; snum++) {
+ struct tdb_print_db *pdb;
+ if (!lp_print_ok(snum))
+ continue;
+ pdb = get_print_db_byname(lp_const_servicename(snum));
if (!pdb)
continue;
tdb_lock_bystring(pdb->tdb, sversion);
@@ -286,11 +290,11 @@ static TDB_DATA print_key(uint32 jobid)
Useful function to find a print job in the database.
****************************************************************************/
-static struct printjob *print_job_find(uint32 jobid)
+static struct printjob *print_job_find(int snum, uint32 jobid)
{
static struct printjob pjob;
TDB_DATA ret;
- struct tdb_print_db *pdb = get_print_db_byjobid(jobid);
+ struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
if (!pdb)
return NULL;
@@ -334,11 +338,16 @@ static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
uint32 sysjob_to_jobid(int unix_jobid)
{
- struct printer_queueid_map *p;
+ int services = lp_numservices();
+ int snum;
+
sysjob_to_jobid_value = (uint32)-1;
- for (p = printer_queueid_map_head; p; p = p->next) {
- struct tdb_print_db *pdb = get_print_db_byname(p->printername);
+ for (snum = 0; snum < services; snum++) {
+ struct tdb_print_db *pdb;
+ if (!lp_print_ok(snum))
+ continue;
+ pdb = get_print_db_byname(lp_const_servicename(snum));
if (pdb)
tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
if (sysjob_to_jobid_value != (uint32)-1)
@@ -385,14 +394,10 @@ static uint32 map_to_spoolss_status(uint32 lpq_status)
return 0;
}
-static void pjob_store_notify(uint32 jobid, struct printjob *old_data,
+static void pjob_store_notify(int snum, uint32 jobid, struct printjob *old_data,
struct printjob *new_data)
{
BOOL new_job = False;
- int snum = print_job_snum(jobid);
-
- if (snum == -1)
- return;
if (!old_data)
new_job = True;
@@ -427,11 +432,11 @@ static void pjob_store_notify(uint32 jobid, struct printjob *old_data,
Store a job structure back to the database.
****************************************************************************/
-static BOOL pjob_store(uint32 jobid, struct printjob *pjob)
+static BOOL pjob_store(int snum, uint32 jobid, struct printjob *pjob)
{
TDB_DATA old_data, new_data;
BOOL ret;
- struct tdb_print_db *pdb = get_print_db_byjobid(jobid);
+ struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
if (!pdb)
return False;
@@ -450,7 +455,7 @@ static BOOL pjob_store(uint32 jobid, struct printjob *pjob)
if (ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob))) {
pjob_store_notify(
- jobid, (struct printjob *)old_data.dptr,
+ snum, jobid, (struct printjob *)old_data.dptr,
(struct printjob *)new_data.dptr);
free(old_data.dptr);
}
@@ -462,12 +467,11 @@ static BOOL pjob_store(uint32 jobid, struct printjob *pjob)
Remove a job structure from the database.
****************************************************************************/
-static void pjob_delete(uint32 jobid)
+static void pjob_delete(int snum, uint32 jobid)
{
- int snum;
- struct printjob *pjob = print_job_find(jobid);
+ struct printjob *pjob = print_job_find(snum, jobid);
uint32 job_status = 0;
- struct tdb_print_db *pdb = get_print_db_byjobid(jobid);
+ struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
if (!pdb)
return;
@@ -486,7 +490,6 @@ static void pjob_delete(uint32 jobid)
JOB_STATUS_DELETED for the port monitor to delete the job
properly. */
- snum = print_job_snum(jobid);
job_status |= JOB_STATUS_DELETING;
notify_job_status(snum, jobid, job_status);
@@ -496,6 +499,7 @@ static void pjob_delete(uint32 jobid)
/* Remove from printing.tdb */
tdb_delete(pdb->tdb, print_key(jobid));
+ rap_jobid_delete(snum, jobid);
}
/****************************************************************************
@@ -523,13 +527,12 @@ static uint32 print_parse_jobid(char *fname)
static void print_unix_job(int snum, print_queue_struct *q)
{
- uint32 queueid = get_printer_queueid_byname(PRINTERNAME(snum));
- uint32 jobid = (q->job + UNIX_JOB_START) | QUEUEID_TO_JOBID(queueid);
+ uint32 jobid = q->job + UNIX_JOB_START;
struct printjob pj, *old_pj;
/* Preserve the timestamp on an existing unix print job */
- old_pj = print_job_find(jobid);
+ old_pj = print_job_find(snum, jobid);
ZERO_STRUCT(pj);
@@ -546,7 +549,7 @@ static void print_unix_job(int snum, print_queue_struct *q)
fstrcpy(pj.user, q->fs_user);
fstrcpy(pj.queuename, lp_const_servicename(snum));
- pjob_store(jobid, &pj);
+ pjob_store(snum, jobid, &pj);
}
@@ -561,7 +564,6 @@ struct traverse_struct {
static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
{
- uint32 queueid;
struct traverse_struct *ts = (struct traverse_struct *)state;
struct printjob pjob;
uint32 jobid;
@@ -577,18 +579,16 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
return 0;
}
- queueid = get_printer_queueid_byname(pjob.queuename);
-
if (!pjob.smbjob) {
/* remove a unix job if it isn't in the system queue any more */
for (i=0;i<ts->qcount;i++) {
- uint32 u_jobid = ((ts->queue[i].job + UNIX_JOB_START) | QUEUEID_TO_JOBID(queueid));
+ uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
if (jobid == u_jobid)
break;
}
if (i == ts->qcount)
- pjob_delete(jobid);
+ pjob_delete(ts->snum, jobid);
else
ts->total_jobs++;
return 0;
@@ -600,14 +600,14 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
exist then kill it. This cleans up after smbd
deaths */
if (!process_exists(pjob.pid))
- pjob_delete(jobid);
+ pjob_delete(ts->snum, jobid);
else
ts->total_jobs++;
return 0;
}
for (i=0;i<ts->qcount;i++) {
- uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file) | QUEUEID_TO_JOBID(queueid);
+ uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
if (jobid == curr_jobid)
break;
}
@@ -627,7 +627,7 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
submitted less than lp_lpqcachetime() seconds ago. */
if ((cur_t - pjob.starttime) > lp_lpqcachetime())
- pjob_delete(jobid);
+ pjob_delete(ts->snum, jobid);
else
ts->total_jobs++;
}
@@ -688,7 +688,7 @@ static pid_t get_updating_pid(fstring printer_name)
in the tdb.
****************************************************************************/
-static void set_updating_pid(fstring printer_name, BOOL delete)
+static void set_updating_pid(const fstring printer_name, BOOL delete)
{
fstring keystr;
TDB_DATA key;
@@ -813,7 +813,7 @@ static void print_queue_update(int snum)
}
/* we have an active SMB print job - update its status */
- pjob = print_job_find(jobid);
+ pjob = print_job_find(snum, jobid);
if (!pjob) {
/* err, somethings wrong. Probably smbd was restarted
with jobs in the queue. All we can do is treat them
@@ -825,7 +825,7 @@ static void print_queue_update(int snum)
pjob->sysjob = queue[i].job;
pjob->status = queue[i].status;
- pjob_store(jobid, pjob);
+ pjob_store(snum, jobid, pjob);
}
/* now delete any queued entries that don't appear in the
@@ -871,36 +871,21 @@ static void print_queue_update(int snum)
Check if a jobid is valid. It is valid if it exists in the database.
****************************************************************************/
-BOOL print_job_exists(uint32 jobid)
+BOOL print_job_exists(int snum, uint32 jobid)
{
- struct tdb_print_db *pdb = get_print_db_byjobid(jobid);
+ struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
if (!pdb)
return False;
return tdb_exists(pdb->tdb, print_key(jobid));
}
/****************************************************************************
- Work out which service a jobid is for.
- Note that we have to look up by queue name to ensure that it works for
- other than the process that started the job.
-****************************************************************************/
-
-int print_job_snum(uint32 jobid)
-{
- struct printjob *pjob = print_job_find(jobid);
- if (!pjob)
- return -1;
-
- return find_service(pjob->queuename);
-}
-
-/****************************************************************************
Give the fd used for a jobid.
****************************************************************************/
-int print_job_fd(uint32 jobid)
+int print_job_fd(int snum, uint32 jobid)
{
- struct printjob *pjob = print_job_find(jobid);
+ struct printjob *pjob = print_job_find(snum, jobid);
if (!pjob)
return -1;
/* don't allow another process to get this info - it is meaningless */
@@ -915,9 +900,9 @@ int print_job_fd(uint32 jobid)
has not been spooled.
****************************************************************************/
-char *print_job_fname(uint32 jobid)
+char *print_job_fname(int snum, uint32 jobid)
{
- struct printjob *pjob = print_job_find(jobid);
+ struct printjob *pjob = print_job_find(snum, jobid);
if (!pjob || pjob->spooled || pjob->pid != local_pid)
return NULL;
return pjob->filename;
@@ -927,7 +912,7 @@ char *print_job_fname(uint32 jobid)
Set the place in the queue for a job.
****************************************************************************/
-BOOL print_job_set_place(uint32 jobid, int place)
+BOOL print_job_set_place(int snum, uint32 jobid, int place)
{
DEBUG(2,("print_job_set_place not implemented yet\n"));
return False;
@@ -937,24 +922,24 @@ BOOL print_job_set_place(uint32 jobid, int place)
Set the name of a job. Only possible for owner.
****************************************************************************/
-BOOL print_job_set_name(uint32 jobid, char *name)
+BOOL print_job_set_name(int snum, uint32 jobid, char *name)
{
- struct printjob *pjob = print_job_find(jobid);
+ struct printjob *pjob = print_job_find(snum, jobid);
if (!pjob || pjob->pid != local_pid)
return False;
fstrcpy(pjob->jobname, name);
- return pjob_store(jobid, pjob);
+ return pjob_store(snum, jobid, pjob);
}
/****************************************************************************
Delete a print job - don't update queue.
****************************************************************************/
-static BOOL print_job_delete1(uint32 jobid)
+static BOOL print_job_delete1(int snum, uint32 jobid)
{
- struct printjob *pjob = print_job_find(jobid);
- int snum, result = 0;
+ struct printjob *pjob = print_job_find(snum, jobid);
+ int result = 0;
if (!pjob)
return False;
@@ -966,12 +951,6 @@ static BOOL print_job_delete1(uint32 jobid)
if (pjob->status == LPQ_DELETING)
return True;
- snum = print_job_snum(jobid);
- if (snum == -1) {
- DEBUG(5,("print_job_delete1: unknown service number for jobid %u\n", (unsigned int)jobid));
- return False;
- }
-
/* Hrm - we need to be able to cope with deleting a job before it
has reached the spooler. */
@@ -982,7 +961,7 @@ static BOOL print_job_delete1(uint32 jobid)
/* Set the tdb entry to be deleting. */
pjob->status = LPQ_DELETING;
- pjob_store(jobid, pjob);
+ pjob_store(snum, jobid, pjob);
if (pjob->spooled && pjob->sysjob != -1)
result = (*(current_printif->job_delete))(snum, pjob);
@@ -991,7 +970,7 @@ static BOOL print_job_delete1(uint32 jobid)
been spooled. */
if (result == 0)
- pjob_delete(jobid);
+ pjob_delete(snum, jobid);
return (result == 0);
}
@@ -1000,9 +979,9 @@ static BOOL print_job_delete1(uint32 jobid)
Return true if the current user owns the print job.
****************************************************************************/
-static BOOL is_owner(struct current_user *user, uint32 jobid)
+static BOOL is_owner(struct current_user *user, int snum, uint32 jobid)
{
- struct printjob *pjob = print_job_find(jobid);
+ struct printjob *pjob = print_job_find(snum, jobid);
user_struct *vuser;
if (!pjob || !user)
@@ -1019,17 +998,11 @@ static BOOL is_owner(struct current_user *user, uint32 jobid)
Delete a print job.
****************************************************************************/
-BOOL print_job_delete(struct current_user *user, uint32 jobid, WERROR *errcode)
+BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
{
- int snum = print_job_snum(jobid);
BOOL owner;
- if (snum == -1) {
- DEBUG(5,("print_job_delete: unknown service number for jobid %d\n", jobid));
- return False;
- }
-
- owner = is_owner(user, jobid);
+ owner = is_owner(user, snum, jobid);
/* Check access against security descriptor or whether the user
owns their job. */
@@ -1041,7 +1014,7 @@ BOOL print_job_delete(struct current_user *user, uint32 jobid, WERROR *errcode)
return False;
}
- if (!print_job_delete1(jobid))
+ if (!print_job_delete1(snum, jobid))
return False;
/* force update the database and say the delete failed if the
@@ -1049,17 +1022,17 @@ BOOL print_job_delete(struct current_user *user, uint32 jobid, WERROR *errcode)
print_queue_update(snum);
- return !print_job_exists(jobid);
+ return !print_job_exists(snum, jobid);
}
/****************************************************************************
Pause a job.
****************************************************************************/
-BOOL print_job_pause(struct current_user *user, uint32 jobid, WERROR *errcode)
+BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
{
- struct printjob *pjob = print_job_find(jobid);
- int snum, ret = -1;
+ struct printjob *pjob = print_job_find(snum, jobid);
+ int ret = -1;
if (!pjob || !user)
return False;
@@ -1067,13 +1040,7 @@ BOOL print_job_pause(struct current_user *user, uint32 jobid, WERROR *errcode)
if (!pjob->spooled || pjob->sysjob == -1)
return False;
- snum = print_job_snum(jobid);
- if (snum == -1) {
- DEBUG(5,("print_job_pause: unknown service number for jobid %u\n", (unsigned int)jobid));
- return False;
- }
-
- if (!is_owner(user, jobid) &&
+ if (!is_owner(user, snum, jobid) &&
!print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("pause denied by security descriptor\n"));
*errcode = WERR_ACCESS_DENIED;
@@ -1104,10 +1071,10 @@ BOOL print_job_pause(struct current_user *user, uint32 jobid, WERROR *errcode)
Resume a job.
****************************************************************************/
-BOOL print_job_resume(struct current_user *user, uint32 jobid, WERROR *errcode)
+BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
{
- struct printjob *pjob = print_job_find(jobid);
- int snum, ret;
+ struct printjob *pjob = print_job_find(snum, jobid);
+ int ret;
if (!pjob || !user)
return False;
@@ -1115,13 +1082,7 @@ BOOL print_job_resume(struct current_user *user, uint32 jobid, WERROR *errcode)
if (!pjob->spooled || pjob->sysjob == -1)
return False;
- snum = print_job_snum(jobid);
- if (snum == -1) {
- DEBUG(5,("print_job_resume: unknown service number for jobid %u\n", (unsigned int)jobid));
- return False;
- }
-
- if (!is_owner(user, jobid) &&
+ if (!is_owner(user, snum, jobid) &&
!print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("resume denied by security descriptor\n"));
*errcode = WERR_ACCESS_DENIED;
@@ -1149,10 +1110,10 @@ BOOL print_job_resume(struct current_user *user, uint32 jobid, WERROR *errcode)
Write to a print file.
****************************************************************************/
-int print_job_write(uint32 jobid, const char *buf, int size)
+int print_job_write(int snum, uint32 jobid, const char *buf, int size)
{
int return_code;
- struct printjob *pjob = print_job_find(jobid);
+ struct printjob *pjob = print_job_find(snum, jobid);
if (!pjob)
return -1;
@@ -1163,7 +1124,7 @@ int print_job_write(uint32 jobid, const char *buf, int size)
return_code = write(pjob->fd, buf, size);
if (return_code>0) {
pjob->size += size;
- pjob_store(jobid, pjob);
+ pjob_store(snum, jobid, pjob);
}
return return_code;
}
@@ -1260,18 +1221,24 @@ int print_queue_length(int snum, print_status_struct *pstatus)
static int get_total_jobs(void)
{
- int total_jobs;
- struct printer_queueid_map *p;
+ int total_jobs = 0;
+ int snum;
+ int services = lp_numservices();
- for (p = printer_queueid_map_head; p; p = p->next) {
+ for (snum = 0; snum < services; snum++) {
+ struct tdb_print_db *pdb;
int jobs;
- struct tdb_print_db *pdb = get_print_db_byname(p->printername);
+
+ if (!lp_print_ok(snum))
+ continue;
+
+ pdb = get_print_db_byname(lp_const_servicename(snum));
if (!pdb)
continue;
/* make sure the database is up to date */
- if (print_cache_expired(lp_servicenumber(p->printername)))
- print_queue_update(lp_servicenumber(p->printername));
+ if (print_cache_expired(snum))
+ print_queue_update(snum);
jobs = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
if (jobs > 0)
@@ -1294,7 +1261,6 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
int njobs = 0;
const char *printername = lp_const_servicename(snum);
struct tdb_print_db *pdb = get_print_db_byname(printername);
- uint32 queueid = queueid = get_printer_queueid_byname(printername);
errno = 0;
@@ -1376,10 +1342,10 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
next_jobid = 1;
for (jobid = NEXT_JOBID(next_jobid); jobid != next_jobid; jobid = NEXT_JOBID(jobid)) {
- if (!print_job_exists(jobid | QUEUEID_TO_JOBID(queueid)))
+ if (!print_job_exists(snum, jobid))
break;
}
- if (jobid == next_jobid || !pjob_store(jobid | QUEUEID_TO_JOBID(queueid), &pjob)) {
+ if (jobid == next_jobid || !pjob_store(snum, jobid, &pjob)) {
DEBUG(3, ("print_job_start: either jobid (%d)==next_jobid(%d) or pjob_store failed.\n",
jobid, next_jobid ));
jobid = -1;
@@ -1392,9 +1358,6 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
goto fail;
}
- /* Ensure the queuid is added to the jobid. */
- jobid |= QUEUEID_TO_JOBID(queueid);
-
/* we have a job entry - now create the spool file */
slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX",
path, PRINT_SPOOL_PREFIX, (unsigned int)jobid);
@@ -1413,7 +1376,7 @@ to open spool file %s.\n", pjob.filename));
goto fail;
}
- pjob_store(jobid, &pjob);
+ pjob_store(snum, jobid, &pjob);
tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
@@ -1425,14 +1388,14 @@ to open spool file %s.\n", pjob.filename));
* tim@fsg.com 09/06/94
*/
if (lp_postscript(snum)) {
- print_job_write(jobid, "%!\n",3);
+ print_job_write(snum, jobid, "%!\n",3);
}
return jobid;
fail:
if (jobid != -1)
- pjob_delete(jobid);
+ pjob_delete(snum, jobid);
tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
@@ -1444,9 +1407,9 @@ to open spool file %s.\n", pjob.filename));
Update the number of pages spooled to jobid
****************************************************************************/
-void print_job_endpage(uint32 jobid)
+void print_job_endpage(int snum, uint32 jobid)
{
- struct printjob *pjob = print_job_find(jobid);
+ struct printjob *pjob = print_job_find(snum, jobid);
if (!pjob)
return;
/* don't allow another process to get this info - it is meaningless */
@@ -1454,7 +1417,7 @@ void print_job_endpage(uint32 jobid)
return;
pjob->page_count++;
- pjob_store(jobid, pjob);
+ pjob_store(snum, jobid, pjob);
}
/****************************************************************************
@@ -1463,10 +1426,10 @@ void print_job_endpage(uint32 jobid)
error.
****************************************************************************/
-BOOL print_job_end(uint32 jobid, BOOL normal_close)
+BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close)
{
- struct printjob *pjob = print_job_find(jobid);
- int snum, ret;
+ struct printjob *pjob = print_job_find(snum, jobid);
+ int ret;
SMB_STRUCT_STAT sbuf;
if (!pjob)
@@ -1475,12 +1438,6 @@ BOOL print_job_end(uint32 jobid, BOOL normal_close)
if (pjob->spooled || pjob->pid != local_pid)
return False;
- snum = print_job_snum(jobid);
- if (snum == -1) {
- DEBUG(5,("print_job_end: unknown service number for jobid %u\n", (unsigned int)jobid));
- return False;
- }
-
if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) {
pjob->size = sbuf.st_size;
close(pjob->fd);
@@ -1505,7 +1462,7 @@ BOOL print_job_end(uint32 jobid, BOOL normal_close)
DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
pjob->filename, pjob->size ? "deleted" : "zero length" ));
unlink(pjob->filename);
- pjob_delete(jobid);
+ pjob_delete(snum, jobid);
return True;
}
@@ -1518,7 +1475,7 @@ BOOL print_job_end(uint32 jobid, BOOL normal_close)
pjob->spooled = True;
pjob->status = LPQ_QUEUED;
- pjob_store(jobid, pjob);
+ pjob_store(snum, jobid, pjob);
/* make sure the database is up to date */
if (print_cache_expired(snum))
@@ -1531,7 +1488,7 @@ fail:
/* The print job was not succesfully started. Cleanup */
/* Still need to add proper error return propagation! 010122:JRR */
unlink(pjob->filename);
- pjob_delete(jobid);
+ pjob_delete(snum, jobid);
return False;
}
@@ -1793,10 +1750,10 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
njobs = print_queue_status(snum, &queue, &status);
for (i=0;i<njobs;i++) {
- BOOL owner = is_owner(user, queue[i].job);
+ BOOL owner = is_owner(user, snum, queue[i].job);
if (owner || can_job_admin) {
- print_job_delete1(queue[i].job);
+ print_job_delete1(snum, queue[i].job);
}
}
diff --git a/source/rpc_parse/parse_lsa.c b/source/rpc_parse/parse_lsa.c
index a6aecb79672..375bbd31d74 100644
--- a/source/rpc_parse/parse_lsa.c
+++ b/source/rpc_parse/parse_lsa.c
@@ -3,8 +3,9 @@
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- * Copyright (C) Andrew Bartlett 2002.
+ * Copyright (C) Paul Ashton 1997,
+ * Copyright (C) Andrew Bartlett 2002,
+ * Copyright (C) Jim McDonough 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
@@ -2117,3 +2118,121 @@ BOOL policy_handle_is_valid(const POLICY_HND *hnd)
ZERO_STRUCT(zero_pol);
return ((memcmp(&zero_pol, hnd, sizeof(POLICY_HND)) == 0) ? False : True );
}
+
+/*******************************************************************
+ Reads or writes an LSA_DNS_DOM_INFO structure.
+********************************************************************/
+
+BOOL lsa_io_dns_dom_info(char *desc, LSA_DNS_DOM_INFO *info,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_dns_dom_info");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+ if(!smb_io_unihdr("nb_name", &info->hdr_nb_dom_name, ps, depth))
+ return False;
+ if(!smb_io_unihdr("dns_name", &info->hdr_dns_dom_name, ps, depth))
+ return False;
+ if(!smb_io_unihdr("forest", &info->hdr_forest_name, ps, depth))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+ if (!prs_uint8s(False, "dom_guid", ps, depth, info->dom_guid.info, GUID_SIZE))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("dom_sid", ps, depth, &info->ptr_dom_sid))
+ return False;
+
+ if(!smb_io_unistr2("nb_name", &info->uni_nb_dom_name,
+ info->hdr_nb_dom_name.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("dns_name", &info->uni_dns_dom_name,
+ info->hdr_dns_dom_name.buffer, ps, depth))
+ return False;
+ if(!smb_io_unistr2("forest", &info->uni_forest_name,
+ info->hdr_forest_name.buffer, ps, depth))
+ return False;
+
+ if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth))
+ return False;
+
+ return True;
+
+}
+
+/*******************************************************************
+ Inits an LSA_Q_QUERY_INFO2 structure.
+********************************************************************/
+
+void init_q_query2(LSA_Q_QUERY_INFO2 *q_q, POLICY_HND *hnd, uint16 info_class)
+{
+ DEBUG(5, ("init_q_query2\n"));
+
+ memcpy(&q_q->pol, hnd, sizeof(q_q->pol));
+
+ q_q->info_class = info_class;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_Q_QUERY_DNSDOMINFO structure.
+********************************************************************/
+
+BOOL lsa_io_q_query_info2(char *desc, LSA_Q_QUERY_INFO2 *q_c,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_q_query_info2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("pol", &q_c->pol, ps, depth))
+ return False;
+
+ if(!prs_uint16("info_class", ps, depth, &q_c->info_class))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_R_QUERY_DNSDOMINFO structure.
+********************************************************************/
+
+BOOL lsa_io_r_query_info2(char *desc, LSA_R_QUERY_INFO2 *r_c,
+ prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "lsa_io_r_query_info2");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr", ps, depth, &r_c->ptr))
+ return False;
+ if(!prs_uint16("info_class", ps, depth, &r_c->info_class))
+ return False;
+ switch(r_c->info_class) {
+ case 0x000c:
+ if (!lsa_io_dns_dom_info("info12", &r_c->info.dns_dom_info,
+ ps, depth))
+ return False;
+ break;
+ default:
+ DEBUG(0,("lsa_io_r_query_info2: unknown info class %d\n",
+ r_c->info_class));
+ return False;
+ }
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_ntstatus("status", ps, depth, &r_c->status))
+ return False;
+
+ return True;
+}
diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c
index 46fdce63ff4..da49a6531d0 100644
--- a/source/rpc_parse/parse_net.c
+++ b/source/rpc_parse/parse_net.c
@@ -1335,7 +1335,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
********************************************************************/
BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
- int depth, uint16 validation_level)
+ int depth, uint16 validation_level)
{
int i;
diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c
index 2ab8c7246e1..4de6b88e9cc 100644
--- a/source/rpc_parse/parse_prs.c
+++ b/source/rpc_parse/parse_prs.c
@@ -893,9 +893,11 @@ BOOL prs_buffer2(BOOL charmode, char *name, prs_struct *ps, int depth, BUFFER2 *
return False;
if (UNMARSHALLING(ps)) {
- str->buffer = (uint16 *)prs_alloc_mem(ps,str->buf_len);
- if (str->buffer == NULL)
- return False;
+ if ( str->buf_len ) {
+ str->buffer = (uint16 *)prs_alloc_mem(ps,str->buf_len);
+ if ( str->buffer == NULL )
+ return False;
+ }
}
p = (char *)str->buffer;
diff --git a/source/rpc_parse/parse_reg.c b/source/rpc_parse/parse_reg.c
index 1ebc1532f31..365ad2dc70b 100644
--- a/source/rpc_parse/parse_reg.c
+++ b/source/rpc_parse/parse_reg.c
@@ -1,4 +1,4 @@
-/*
+/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
@@ -6,6 +6,7 @@
* Copyright (C) Paul Ashton 1997.
* Copyright (C) Marc Jacobsen 1999.
* Copyright (C) Simo Sorce 2000.
+ * Copyright (C) Gerald Carter 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
@@ -28,6 +29,89 @@
#define DBGC_CLASS DBGC_RPC_PARSE
/*******************************************************************
+ Fill in a BUFFER2 for the data given a REGISTRY_VALUE
+ *******************************************************************/
+
+static uint32 reg_init_buffer2( BUFFER2 *buf2, REGISTRY_VALUE *val )
+{
+ UNISTR2 unistr;
+ uint32 real_size = 0;
+ char *string;
+ char *list = NULL;
+ char *list2 = NULL;
+
+ if ( !buf2 || !val )
+ return 0;
+
+ real_size = val->size;
+
+ switch (val->type )
+ {
+ case REG_SZ:
+ string = (char*)val->data_p;
+ DEBUG(10,("reg_init_buffer2: REG_SZ string => [%s]\n", string));
+
+ init_unistr2( &unistr, (char*)val->data_p, strlen((char*)val->data_p)+1 );
+ init_buffer2( buf2, (char*)unistr.buffer, unistr.uni_str_len*2 );
+ real_size = unistr.uni_str_len*2;
+ break;
+
+ case REG_MULTI_SZ:
+ string = (char*)val->data_p;
+ real_size = 0;
+ while ( string && *string )
+ {
+ DEBUG(10,("reg_init_buffer2: REG_MULTI_SZ string => [%s], size => [%d]\n", string, real_size ));
+
+ init_unistr2( &unistr, string, strlen(string)+1 );
+
+ list2 = Realloc( list, real_size + unistr.uni_str_len*2 );
+ if ( !list2 )
+ break;
+ list = list2;
+
+ memcpy( list+real_size, unistr.buffer, unistr.uni_str_len*2 );
+
+ real_size += unistr.uni_str_len*2;
+
+ string += strlen(string)+1;
+ }
+
+ list2 = Realloc( list, real_size + 2 );
+ if ( !list2 )
+ break;
+ list = list2;
+ list[real_size++] = 0x0;
+ list[real_size++] = 0x0;
+
+ init_buffer2( buf2, (char*)list, real_size );
+
+ DEBUG(10,("reg_init_buffer2: REG_MULTI_SZ size => [%d]\n", real_size ));
+
+ break;
+
+ case REG_BINARY:
+ DEBUG(10,("reg_init_buffer2: REG_BINARY size => [%d]\n", val->size ));
+
+ init_buffer2( buf2, val->data_p, val->size );
+ break;
+
+ case REG_DWORD:
+ DEBUG(10,("reg_init_buffer2: REG_DWORD value => [%d]\n", *(uint32*)val->data_p));
+ init_buffer2( buf2, val->data_p, val->size );
+ break;
+
+ default:
+ DEBUG(0,("reg_init_buffer2: Unsupported registry data type [%d]\n", val->type));
+ break;
+ }
+
+ SAFE_FREE( list );
+
+ return real_size;
+}
+
+/*******************************************************************
Inits a structure.
********************************************************************/
@@ -165,6 +249,8 @@ BOOL reg_io_r_open_hklm(char *desc, REG_R_OPEN_HKLM * r_r, prs_struct *ps,
}
+
+
/*******************************************************************
Inits a structure.
********************************************************************/
@@ -583,7 +669,7 @@ BOOL reg_io_r_query_key(char *desc, REG_R_QUERY_KEY *r_r, prs_struct *ps, int d
return False;
if(!smb_io_time("mod_time ", &r_r->mod_time, ps, depth))
return False;
-
+
if(!prs_ntstatus("status", ps, depth, &r_r->status))
return False;
@@ -599,6 +685,7 @@ void init_reg_q_unknown_1a(REG_Q_UNKNOWN_1A *q_o, POLICY_HND *hnd)
memcpy(&q_o->pol, hnd, sizeof(q_o->pol));
}
+
/*******************************************************************
reads or writes a structure.
********************************************************************/
@@ -613,7 +700,7 @@ BOOL reg_io_q_unknown_1a(char *desc, REG_Q_UNKNOWN_1A *r_q, prs_struct *ps, int
if(!prs_align(ps))
return False;
-
+
if(!smb_io_pol_hnd("", &r_q->pol, ps, depth))
return False;
@@ -634,7 +721,7 @@ BOOL reg_io_r_unknown_1a(char *desc, REG_R_UNKNOWN_1A *r_r, prs_struct *ps, int
if(!prs_align(ps))
return False;
-
+
if(!prs_uint32("unknown", ps, depth, &r_r->unknown))
return False;
if(!prs_ntstatus("status" , ps, depth, &r_r->status))
@@ -643,6 +730,57 @@ BOOL reg_io_r_unknown_1a(char *desc, REG_R_UNKNOWN_1A *r_r, prs_struct *ps, int
return True;
}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL reg_io_q_save_key(char *desc, REG_Q_SAVE_KEY *r_q, prs_struct *ps, int depth)
+{
+ if (r_q == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "reg_io_q_save_key");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("", &r_q->pol, ps, depth))
+ return False;
+
+ if(!smb_io_unihdr ("hdr_file", &r_q->hdr_file, ps, depth))
+ return False;
+ if(!smb_io_unistr2("uni_file", &r_q->uni_file, r_q->hdr_file.buffer, ps, depth))
+ return False;
+
+ if(!prs_uint32("unknown", ps, depth, &r_q->unknown))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL reg_io_r_save_key(char *desc, REG_R_SAVE_KEY *r_r, prs_struct *ps, int depth)
+{
+ if (r_r == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "reg_io_r_save_key");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_ntstatus("status" , ps, depth, &r_r->status))
+ return False;
+
+ return True;
+}
+
/*******************************************************************
Inits a structure.
********************************************************************/
@@ -1025,33 +1163,77 @@ BOOL reg_io_q_info(char *desc, REG_Q_INFO *r_q, prs_struct *ps, int depth)
/*******************************************************************
Inits a structure.
+ New version to replace older init_reg_r_info()
+********************************************************************/
+
+BOOL new_init_reg_r_info(uint32 include_keyval, REG_R_INFO *r_r,
+ REGISTRY_VALUE *val, NTSTATUS status)
+{
+ uint32 buf_len = 0;
+ BUFFER2 buf2;
+
+ if(r_r == NULL)
+ return False;
+
+ if ( !val )
+ return False;
+
+ r_r->ptr_type = 1;
+ r_r->type = val->type;
+
+ /* if include_keyval is not set, don't send the key value, just
+ the buflen data. probably used by NT5 to allocate buffer space - SK */
+
+ if ( include_keyval ) {
+ r_r->ptr_uni_val = 1;
+ buf_len = reg_init_buffer2( &r_r->uni_val, val );
+
+ }
+ else {
+ /* dummy buffer used so we can get the size */
+ r_r->ptr_uni_val = 0;
+ buf_len = reg_init_buffer2( &buf2, val );
+ }
+
+ r_r->ptr_max_len = 1;
+ r_r->buf_max_len = buf_len;
+
+ r_r->ptr_len = 1;
+ r_r->buf_len = buf_len;
+
+ r_r->status = status;
+
+ return True;
+}
+
+/*******************************************************************
+ Inits a structure.
********************************************************************/
BOOL init_reg_r_info(uint32 include_keyval, REG_R_INFO *r_r,
BUFFER2* buf, uint32 type, NTSTATUS status)
{
- if(r_r == NULL)
- return False;
-
+ if(r_r == NULL)
+ return False;
- r_r->ptr_type = 1;
- r_r->type = type;
+ r_r->ptr_type = 1;
+ r_r->type = type;
- /* if include_keyval is not set, don't send the key value, just
- the buflen data. probably used by NT5 to allocate buffer space - SK */
- r_r->ptr_uni_val = include_keyval ? 1:0;
- r_r->uni_val = buf;
+ /* if include_keyval is not set, don't send the key value, just
+ the buflen data. probably used by NT5 to allocate buffer space - SK */
- r_r->ptr_max_len = 1;
- r_r->buf_max_len = r_r->uni_val->buf_max_len;
+ r_r->ptr_uni_val = include_keyval ? 1:0;
+ r_r->uni_val = *buf;
- r_r->ptr_len = 1;
- r_r->buf_len = r_r->uni_val->buf_len;
+ r_r->ptr_max_len = 1;
+ r_r->buf_max_len = r_r->uni_val.buf_max_len;
- r_r->status = status;
+ r_r->ptr_len = 1;
+ r_r->buf_len = r_r->uni_val.buf_len;
- return True;
-
+ r_r->status = status;
+
+ return True;
}
/*******************************************************************
@@ -1081,7 +1263,7 @@ BOOL reg_io_r_info(char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth)
return False;
if(r_r->ptr_uni_val != 0) {
- if(!smb_io_buffer2("uni_val", r_r->uni_val, r_r->ptr_uni_val, ps, depth))
+ if(!smb_io_buffer2("uni_val", &r_r->uni_val, r_r->ptr_uni_val, ps, depth))
return False;
}
@@ -1139,6 +1321,46 @@ void init_reg_q_enum_val(REG_Q_ENUM_VALUE *q_i, POLICY_HND *pol,
}
/*******************************************************************
+makes a structure.
+********************************************************************/
+
+void init_reg_r_enum_val(REG_R_ENUM_VALUE *r_u, REGISTRY_VALUE *val )
+{
+ uint32 real_size;
+
+ DEBUG(8,("init_reg_r_enum_val: Enter\n"));
+
+ ZERO_STRUCTP(r_u);
+
+ /* value name */
+
+ DEBUG(10,("init_reg_r_enum_val: Valuename => [%s]\n", val->valuename));
+
+ init_uni_hdr( &r_u->hdr_name, strlen(val->valuename)+1 );
+ init_unistr2( &r_u->uni_name, val->valuename, strlen(val->valuename)+1 );
+
+ /* type */
+
+ r_u->ptr_type = 1;
+ r_u->type = val->type;
+
+ /* REG_SZ & REG_MULTI_SZ must be converted to UNICODE */
+
+ r_u->ptr_value = 1;
+ real_size = reg_init_buffer2( &r_u->buf_value, val );
+
+ /* lengths */
+
+ r_u->ptr1 = 1;
+ r_u->len_value1 = real_size;
+
+ r_u->ptr2 = 1;
+ r_u->len_value2 = real_size;
+
+ DEBUG(8,("init_reg_r_enum_val: Exit\n"));
+}
+
+/*******************************************************************
reads or writes a structure.
********************************************************************/
@@ -1158,6 +1380,7 @@ BOOL reg_io_q_enum_val(char *desc, REG_Q_ENUM_VALUE *q_q, prs_struct *ps, int d
if(!prs_uint32("val_index", ps, depth, &q_q->val_index))
return False;
+
if(!smb_io_unihdr ("hdr_name", &q_q->hdr_name, ps, depth))
return False;
if(!smb_io_unistr2("uni_name", &q_q->uni_name, q_q->hdr_name.buffer, ps, depth))
@@ -1228,7 +1451,7 @@ BOOL reg_io_r_enum_val(char *desc, REG_R_ENUM_VALUE *r_q, prs_struct *ps, int d
if(!prs_uint32("ptr_value", ps, depth, &r_q->ptr_value))
return False;
- if(!smb_io_buffer2("buf_value", r_q->buf_value, r_q->ptr_value, ps, depth))
+ if(!smb_io_buffer2("buf_value", &r_q->buf_value, r_q->ptr_value, ps, depth))
return False;
if(!prs_align(ps))
return False;
@@ -1531,7 +1754,7 @@ BOOL reg_io_q_open_entry(char *desc, REG_Q_OPEN_ENTRY *r_q, prs_struct *ps, int
if(!prs_uint32("unknown_0 ", ps, depth, &r_q->unknown_0))
return False;
- if(!prs_uint32("asccess_desired ", ps, depth, &r_q->access_desired))
+ if(!prs_uint32("access_desired ", ps, depth, &r_q->access_desired))
return False;
return True;
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index c16232204cd..1137993bb60 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -5,8 +5,10 @@
* Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
* Copyright (C) Paul Ashton 1997-2000,
* Copyright (C) Elrond 2000,
- * Copyright (C) Jeremy Allison 2001
- * Copyright (C) Jean François Micouleau 1998-2001.
+ * Copyright (C) Jeremy Allison 2001,
+ * Copyright (C) Jean François Micouleau 1998-2001,
+ * Copyright (C) Anthony Liguori 2002,
+ * Copyright (C) Jim McDonough 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
@@ -5067,7 +5069,7 @@ BOOL samr_io_r_create_user(char *desc, SAMR_R_CREATE_USER * r_u,
if(!smb_io_pol_hnd("user_pol", &r_u->user_pol, ps, depth))
return False;
- if(!prs_uint32("unknown_0", ps, depth, &r_u->unknown_0))
+ if(!prs_uint32("access_granted", ps, depth, &r_u->access_granted))
return False;
if(!prs_uint32("user_rid ", ps, depth, &r_u->user_rid))
return False;
@@ -5945,7 +5947,7 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
const char* user_name = pdb_get_username(pw);
const char* full_name = pdb_get_fullname(pw);
const char* home_dir = pdb_get_homedir(pw);
- const char* dir_drive = pdb_get_dirdrive(pw);
+ const char* dir_drive = pdb_get_dir_drive(pw);
const char* logon_script = pdb_get_logon_script(pw);
const char* profile_path = pdb_get_profile_path(pw);
const char* description = pdb_get_acct_desc(pw);
@@ -6717,6 +6719,84 @@ BOOL samr_io_r_connect(char *desc, SAMR_R_CONNECT * r_u,
}
/*******************************************************************
+inits a SAMR_Q_CONNECT4 structure.
+********************************************************************/
+
+void init_samr_q_connect4(SAMR_Q_CONNECT4 * q_u,
+ char *srv_name, uint32 access_mask)
+{
+ int len_srv_name = strlen(srv_name);
+
+ DEBUG(5, ("init_samr_q_connect\n"));
+
+ /* make PDC server name \\server */
+ q_u->ptr_srv_name = len_srv_name > 0 ? 1 : 0;
+ init_unistr2(&q_u->uni_srv_name, srv_name, len_srv_name + 1);
+
+ /* Only value we've seen, possibly an address type ? */
+ q_u->unk_0 = 2;
+
+ /* example values: 0x0000 0002 */
+ q_u->access_mask = access_mask;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_q_connect4(char *desc, SAMR_Q_CONNECT4 * q_u,
+ prs_struct *ps, int depth)
+{
+ if (q_u == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "samr_io_q_connect4");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_srv_name", ps, depth, &q_u->ptr_srv_name))
+ return False;
+ if(!smb_io_unistr2("", &q_u->uni_srv_name, q_u->ptr_srv_name, ps, depth))
+ return False;
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("unk_0", ps, depth, &q_u->unk_0))
+ return False;
+ if(!prs_uint32("access_mask", ps, depth, &q_u->access_mask))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+reads or writes a structure.
+********************************************************************/
+
+BOOL samr_io_r_connect4(char *desc, SAMR_R_CONNECT4 * r_u,
+ prs_struct *ps, int depth)
+{
+ if (r_u == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "samr_io_r_connect4");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("connect_pol", &r_u->connect_pol, ps, depth))
+ return False;
+
+ if(!prs_ntstatus("status", ps, depth, &r_u->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
inits a SAMR_Q_CONNECT_ANON structure.
********************************************************************/
diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c
index b10a5c43771..3a7f4b57ae6 100644
--- a/source/rpc_parse/parse_spoolss.c
+++ b/source/rpc_parse/parse_spoolss.c
@@ -322,7 +322,7 @@ reads or writes an NOTIFY INFO DATA structure.
static BOOL smb_io_notify_info_data(char *desc,SPOOL_NOTIFY_INFO_DATA *data, prs_struct *ps, int depth)
{
- uint32 useless_ptr=0xADDE0FF0;
+ uint32 useless_ptr=0x0FF0ADDE;
prs_debug(ps, depth, desc, "smb_io_notify_info_data");
depth++;
@@ -378,6 +378,14 @@ static BOOL smb_io_notify_info_data(char *desc,SPOOL_NOTIFY_INFO_DATA *data, prs
break;
+ case NOTIFY_SECDESC:
+ if( !prs_uint32( "sd size", ps, depth, &data->notify_data.sd.size ) )
+ return False;
+ if( !prs_uint32( "pointer", ps, depth, &useless_ptr ) )
+ return False;
+
+ break;
+
default:
DEBUG(3, ("invalid enc_type %d for smb_io_notify_info_data\n",
data->enc_type));
@@ -451,6 +459,13 @@ BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data,
break;
+ case NOTIFY_SECDESC:
+ if( !prs_uint32("secdesc size ", ps, depth, &data->notify_data.sd.size ) )
+ return False;
+ if ( !sec_io_desc( "sec_desc", &data->notify_data.sd.desc, ps, depth ) )
+ return False;
+ break;
+
default:
DEBUG(3, ("invalid enc_type %d for smb_io_notify_info_data_strings\n",
data->enc_type));
@@ -675,9 +690,11 @@ BOOL spoolss_io_devmode(char *desc, prs_struct *ps, int depth, DEVICEMODE *devmo
Let the size determine that */
switch (devmode->specversion) {
+ /* list of observed spec version's */
case 0x0320:
case 0x0400:
case 0x0401:
+ case 0x040d:
break;
default:
@@ -5183,7 +5200,7 @@ static BOOL uniarray_2_dosarray(BUFFER5 *buf5, fstring **ar)
*ar = NULL;
while (src < ((char *)buf5->buffer) + buf5->buf_len*2) {
- rpcstr_pull(f, src, sizeof(f)-1, -1, 0);
+ rpcstr_pull(f, src, sizeof(f)-1, -1, STR_TERMINATE);
src = skip_unibuf(src, 2*buf5->buf_len - PTR_DIFF(src,buf5->buffer));
tar = (fstring *)Realloc(*ar, sizeof(fstring)*(n+2));
if (!tar)
@@ -6171,42 +6188,6 @@ BOOL spoolss_io_r_resetprinter(char *desc, SPOOL_R_RESETPRINTER *r_u, prs_struct
/*******************************************************************
********************************************************************/
-BOOL convert_specific_param(NT_PRINTER_PARAM **param, const UNISTR2 *value,
- uint32 type, const uint8 *data, uint32 len)
-{
- DEBUG(5,("converting a specific param struct\n"));
-
- if (*param == NULL)
- {
- *param=(NT_PRINTER_PARAM *)malloc(sizeof(NT_PRINTER_PARAM));
- if(*param == NULL)
- return False;
- memset((char *)*param, '\0', sizeof(NT_PRINTER_PARAM));
- DEBUGADD(6,("Allocated a new PARAM struct\n"));
- }
- unistr2_to_ascii((*param)->value, value, sizeof((*param)->value)-1);
- (*param)->type = type;
-
- /* le champ data n'est pas NULL termine */
- /* on stocke donc la longueur */
-
- (*param)->data_len=len;
-
- if (len) {
- (*param)->data=(uint8 *)malloc(len * sizeof(uint8));
- if((*param)->data == NULL)
- return False;
- memcpy((*param)->data, data, len);
- }
-
- DEBUGADD(6,("\tvalue:[%s], len:[%d]\n",(*param)->value, (*param)->data_len));
- dump_data(10, (char *)(*param)->data, (*param)->data_len);
-
- return True;
-}
-
-/*******************************************************************
-********************************************************************/
static BOOL spoolss_io_addform(char *desc, FORM *f, uint32 ptr, prs_struct *ps, int depth)
{
@@ -6750,7 +6731,7 @@ BOOL make_spoolss_q_reply_rrpcn(SPOOL_Q_REPLY_RRPCN *q_u, POLICY_HND *hnd,
q_u->unknown0=0x0;
q_u->unknown1=0x0;
- q_u->info_ptr=0xaddee11e;
+ q_u->info_ptr=0x0FF0ADDE;
q_u->info.version=2;
@@ -7528,3 +7509,31 @@ BOOL make_spoolss_q_deleteprinterdata(SPOOL_Q_DELETEPRINTERDATA *q_u,
return True;
}
+
+/*******************************************************************
+ * init a structure.
+ ********************************************************************/
+
+BOOL make_spoolss_q_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, POLICY_HND *handle,
+ uint32 flags, uint32 options, char *localmachine,
+ uint32 printerlocal, SPOOL_NOTIFY_OPTION *option)
+{
+ memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
+
+ q_u->flags = flags;
+ q_u->options = options;
+
+ q_u->localmachine_ptr = 1;
+
+ init_unistr2(&q_u->localmachine, localmachine,
+ strlen(localmachine) + 1);
+
+ q_u->printerlocal = printerlocal;
+
+ if (option)
+ q_u->option_ptr = 1;
+
+ q_u->option = option;
+
+ return True;
+}
diff --git a/source/rpc_parse/parse_srv.c b/source/rpc_parse/parse_srv.c
index 3dc054d2b17..531267c308c 100644
--- a/source/rpc_parse/parse_srv.c
+++ b/source/rpc_parse/parse_srv.c
@@ -3,9 +3,10 @@
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- * Copyright (C) Jeremy Allison 1999.
- * Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2002
+ * Copyright (C) Paul Ashton 1997,
+ * Copyright (C) Jeremy Allison 1999,
+ * Copyright (C) Nigel Williams 2001,
+ * Copyright (C) Jim McDonough (jmcd@us.ibm.com) 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
@@ -28,6 +29,71 @@
#define DBGC_CLASS DBGC_RPC_PARSE
/*******************************************************************
+ Inits a SH_INFO_0_STR structure
+********************************************************************/
+
+void init_srv_share_info0_str(SH_INFO_0_STR *sh0, char *net_name)
+{
+ DEBUG(5,("init_srv_share_info0_str\n"));
+
+ if(net_name)
+ init_unistr2(&sh0->uni_netname, net_name, strlen(net_name)+1);
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+static BOOL srv_io_share_info0_str(char *desc, SH_INFO_0_STR *sh0, prs_struct *ps, int depth)
+{
+ if (sh0 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "srv_io_share_info0_str");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+ if(sh0->ptrs->ptr_netname)
+ if(!smb_io_unistr2("", &sh0->uni_netname, True, ps, depth))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ makes a SH_INFO_0 structure
+********************************************************************/
+
+void init_srv_share_info0(SH_INFO_0 *sh0, char *net_name)
+{
+ DEBUG(5,("init_srv_share_info0: %s\n", net_name));
+
+ sh0->ptr_netname = (net_name != NULL) ? 1 : 0;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+static BOOL srv_io_share_info0(char *desc, SH_INFO_0 *sh0, prs_struct *ps, int depth)
+{
+ if (sh0 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "srv_io_share_info0");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_netname", ps, depth, &sh0->ptr_netname))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
Inits a SH_INFO_1_STR structure
********************************************************************/
@@ -35,8 +101,10 @@ void init_srv_share_info1_str(SH_INFO_1_STR *sh1, char *net_name, char *remark)
{
DEBUG(5,("init_srv_share_info1_str\n"));
- init_unistr2(&sh1->uni_netname, net_name, strlen(net_name)+1);
- init_unistr2(&sh1->uni_remark, remark, strlen(remark)+1);
+ if(net_name)
+ init_unistr2(&sh1->uni_netname, net_name, strlen(net_name)+1);
+ if(remark)
+ init_unistr2(&sh1->uni_remark, remark, strlen(remark)+1);
}
/*******************************************************************
@@ -47,20 +115,24 @@ static BOOL srv_io_share_info1_str(char *desc, SH_INFO_1_STR *sh1, prs_struct *p
{
if (sh1 == NULL)
return False;
-
+
prs_debug(ps, depth, desc, "srv_io_share_info1_str");
depth++;
-
+
if(!prs_align(ps))
return False;
- if(!smb_io_unistr2("", &sh1->uni_netname, True, ps, depth))
- return False;
+ if(sh1->ptrs->ptr_netname)
+ if(!smb_io_unistr2("", &sh1->uni_netname, True, ps, depth))
+ return False;
+
if(!prs_align(ps))
return False;
- if(!smb_io_unistr2("", &sh1->uni_remark, True, ps, depth))
- return False;
-
+
+ if(sh1->ptrs->ptr_remark)
+ if(!smb_io_unistr2("", &sh1->uni_remark, True, ps, depth))
+ return False;
+
return True;
}
@@ -71,7 +143,7 @@ static BOOL srv_io_share_info1_str(char *desc, SH_INFO_1_STR *sh1, prs_struct *p
void init_srv_share_info1(SH_INFO_1 *sh1, char *net_name, uint32 type, char *remark)
{
DEBUG(5,("init_srv_share_info1: %s %8x %s\n", net_name, type, remark));
-
+
sh1->ptr_netname = (net_name != NULL) ? 1 : 0;
sh1->type = type;
sh1->ptr_remark = (remark != NULL) ? 1 : 0;
@@ -139,6 +211,7 @@ static BOOL srv_io_share_info2_str(char *desc, SH_INFO_2 *sh, SH_INFO_2_STR *sh2
if(!prs_align(ps))
return False;
+
if (sh->ptr_netname)
if(!smb_io_unistr2("", &sh2->uni_netname, True, ps, depth))
return False;
@@ -175,7 +248,6 @@ void init_srv_share_info2(SH_INFO_2 *sh2,
sh2->perms = perms;
sh2->max_uses = max_uses;
sh2->num_uses = num_uses;
- sh2->type = type;
sh2->ptr_path = (path != NULL) ? 1 : 0;
sh2->ptr_passwd = (passwd != NULL) ? 1 : 0;
}
@@ -216,6 +288,21 @@ static BOOL srv_io_share_info2(char *desc, SH_INFO_2 *sh2, prs_struct *ps, int d
}
/*******************************************************************
+ Inits a SH_INFO_501_STR structure
+********************************************************************/
+
+void init_srv_share_info501_str(SH_INFO_501_STR *sh501,
+ char *net_name, char *remark)
+{
+ DEBUG(5,("init_srv_share_info501_str\n"));
+
+ if(net_name)
+ init_unistr2(&sh501->uni_netname, net_name, strlen(net_name)+1);
+ if(remark)
+ init_unistr2(&sh501->uni_remark, remark, strlen(remark)+1);
+}
+
+/*******************************************************************
Inits a SH_INFO_2 structure
*******************************************************************/
@@ -259,18 +346,6 @@ static BOOL srv_io_share_info501(char *desc, SH_INFO_501 *sh501, prs_struct *ps,
return True;
}
-/********************************************************************
- Inits a SH_INFO_501_STR structure
-********************************************************************/
-
-void init_srv_share_info501_str(SH_INFO_501_STR *sh501, char *net_name, char *remark)
-{
- DEBUG(5,("init_srv_share_info501_str\n"));
-
- init_unistr2(&sh501->uni_netname, net_name, strlen(net_name)+1);
- init_unistr2(&sh501->uni_remark, remark, strlen(remark)+1);
-}
-
/*******************************************************************
Reads or writes a structure.
********************************************************************/
@@ -301,7 +376,7 @@ static BOOL srv_io_share_info501_str(char *desc, SH_INFO_501_STR *sh501, prs_str
********************************************************************/
void init_srv_share_info502(SH_INFO_502 *sh502,
- char *net_name, uint32 type, char *remark,
+ const char *net_name, uint32 type, char *remark,
uint32 perms, uint32 max_uses, uint32 num_uses,
char *path, char *passwd, SEC_DESC *psd, size_t sd_size)
{
@@ -315,9 +390,9 @@ void init_srv_share_info502(SH_INFO_502 *sh502,
sh502->perms = perms;
sh502->max_uses = max_uses;
sh502->num_uses = num_uses;
- sh502->type = type;
sh502->ptr_path = (path != NULL) ? 1 : 0;
sh502->ptr_passwd = (passwd != NULL) ? 1 : 0;
+ sh502->reserved = 0; /* actual size within rpc */
sh502->sd_size = (uint32)sd_size;
sh502->ptr_sd = (psd != NULL) ? 1 : 0;
}
@@ -353,7 +428,7 @@ static BOOL srv_io_share_info502(char *desc, SH_INFO_502 *sh502, prs_struct *ps,
return False;
if(!prs_uint32("ptr_passwd ", ps, depth, &sh502->ptr_passwd))
return False;
- if(!prs_uint32("sd_size ", ps, depth, &sh502->sd_size))
+ if(!prs_uint32_pre("reserved ", ps, depth, &sh502->reserved, &sh502->reserved_offset))
return False;
if(!prs_uint32("ptr_sd ", ps, depth, &sh502->ptr_sd))
return False;
@@ -366,26 +441,22 @@ static BOOL srv_io_share_info502(char *desc, SH_INFO_502 *sh502, prs_struct *ps,
********************************************************************/
void init_srv_share_info502_str(SH_INFO_502_STR *sh502str,
- SH_INFO_502 *ptrs,
char *net_name, char *remark,
char *path, char *passwd, SEC_DESC *psd, size_t sd_size)
{
DEBUG(5,("init_srv_share_info502_str\n"));
- sh502str->ptrs = ptrs;
-
- if(sh502str->ptrs->ptr_netname)
+ if(net_name)
init_unistr2(&sh502str->uni_netname, net_name, strlen(net_name)+1);
- if(sh502str->ptrs->ptr_remark)
+ if(remark)
init_unistr2(&sh502str->uni_remark, remark, strlen(remark)+1);
- if(sh502str->ptrs->ptr_path)
+ if(path)
init_unistr2(&sh502str->uni_path, path, strlen(path)+1);
- if(sh502str->ptrs->ptr_passwd)
+ if(passwd)
init_unistr2(&sh502str->uni_passwd, passwd, strlen(passwd)+1);
- if(sh502str->ptrs->ptr_sd) {
sh502str->sd = psd;
+ sh502str->reserved = 0;
sh502str->sd_size = sd_size;
- }
}
/*******************************************************************
@@ -436,21 +507,112 @@ static BOOL srv_io_share_info502_str(char *desc, SH_INFO_502_STR *sh502, prs_str
return False;
if(sh502->ptrs->ptr_sd) {
- if(!prs_uint32("sd_size ", ps, depth, &sh502->sd_size))
+ uint32 old_offset;
+ uint32 reserved_offset;
+
+ if(!prs_uint32_pre("reserved ", ps, depth, &sh502->reserved, &reserved_offset))
return False;
+
+ old_offset = prs_offset(ps);
+
if (!sec_io_desc(desc, &sh502->sd, ps, depth))
return False;
+
+ if(UNMARSHALLING(ps)) {
+
+ sh502->ptrs->sd_size = sh502->sd_size = sec_desc_size(sh502->sd);
+
+ prs_set_offset(ps, old_offset + sh502->reserved);
+ }
+
+ prs_align(ps);
+
+ if(MARSHALLING(ps)) {
+
+ sh502->ptrs->reserved = sh502->reserved = prs_offset(ps) - old_offset;
+ }
+
+ if(!prs_uint32_post("reserved ", ps, depth,
+ &sh502->reserved, reserved_offset, sh502->reserved))
+ return False;
+ if(!prs_uint32_post("reserved ", ps, depth,
+ &sh502->ptrs->reserved, sh502->ptrs->reserved_offset, sh502->ptrs->reserved))
+ return False;
}
return True;
}
/*******************************************************************
+ Inits a SH_INFO_1004_STR structure
+********************************************************************/
+
+void init_srv_share_info1004_str(SH_INFO_1004_STR *sh1004, char *remark)
+{
+ DEBUG(5,("init_srv_share_info1004_str\n"));
+
+ if(remark)
+ init_unistr2(&sh1004->uni_remark, remark, strlen(remark)+1);
+}
+
+/*******************************************************************
Reads or writes a structure.
********************************************************************/
-static BOOL srv_io_share_info1005(char* desc, SRV_SHARE_INFO_1005* sh1005,
- prs_struct* ps, int depth)
+static BOOL srv_io_share_info1004_str(char *desc, SH_INFO_1004_STR *sh1004, prs_struct *ps, int depth)
+{
+ if (sh1004 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "srv_io_share_info1004_str");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+ if(sh1004->ptrs->ptr_remark)
+ if(!smb_io_unistr2("", &sh1004->uni_remark, True, ps, depth))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ makes a SH_INFO_1004 structure
+********************************************************************/
+
+void init_srv_share_info1004(SH_INFO_1004 *sh1004, char *remark)
+{
+ DEBUG(5,("init_srv_share_info1004: %s\n", remark));
+
+ sh1004->ptr_remark = (remark != NULL) ? 1 : 0;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+static BOOL srv_io_share_info1004(char *desc, SH_INFO_1004 *sh1004, prs_struct *ps, int depth)
+{
+ if (sh1004 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "srv_io_share_info1004");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("ptr_remark", ps, depth, &sh1004->ptr_remark))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+static BOOL srv_io_share_info1005(char* desc, SRV_SHARE_INFO_1005* sh1005, prs_struct* ps, int depth)
{
if(sh1005 == NULL)
return False;
@@ -471,6 +633,95 @@ static BOOL srv_io_share_info1005(char* desc, SRV_SHARE_INFO_1005* sh1005,
Reads or writes a structure.
********************************************************************/
+static BOOL srv_io_share_info1006(char* desc, SRV_SHARE_INFO_1006* sh1006, prs_struct* ps, int depth)
+{
+ if(sh1006 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "srv_io_share_info1006");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("max uses ", ps, depth, &sh1006->max_uses))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Inits a SH_INFO_1007_STR structure
+********************************************************************/
+
+void init_srv_share_info1007_str(SH_INFO_1007_STR *sh1007, const char *alternate_directory_name)
+{
+ DEBUG(5,("init_srv_share_info1007_str\n"));
+
+ if(alternate_directory_name)
+ init_unistr2(&sh1007->uni_AlternateDirectoryName, alternate_directory_name, strlen(alternate_directory_name)+1);
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+static BOOL srv_io_share_info1007_str(char *desc, SH_INFO_1007_STR *sh1007, prs_struct *ps, int depth)
+{
+ if (sh1007 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "srv_io_share_info1007_str");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+ if(sh1007->ptrs->ptr_AlternateDirectoryName)
+ if(!smb_io_unistr2("", &sh1007->uni_AlternateDirectoryName, True, ps, depth))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ makes a SH_INFO_1007 structure
+********************************************************************/
+
+void init_srv_share_info1007(SH_INFO_1007 *sh1007, uint32 flags, const char *alternate_directory_name)
+{
+ DEBUG(5,("init_srv_share_info1007: %s\n", alternate_directory_name));
+
+ sh1007->flags = flags;
+ sh1007->ptr_AlternateDirectoryName = (alternate_directory_name != NULL) ? 1 : 0;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+static BOOL srv_io_share_info1007(char *desc, SH_INFO_1007 *sh1007, prs_struct *ps, int depth)
+{
+ if (sh1007 == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "srv_io_share_info1007");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!prs_uint32("flags ", ps, depth, &sh1007->flags))
+ return False;
+ if(!prs_uint32("ptr_Alter..", ps, depth, &sh1007->ptr_AlternateDirectoryName))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
static BOOL srv_io_share_info1501(char* desc, SRV_SHARE_INFO_1501* sh1501,
prs_struct* ps, int depth)
{
@@ -511,9 +762,6 @@ static BOOL srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct
if(!prs_uint32("info_level", ps, depth, &ctr->info_level))
return False;
- if (ctr->info_level == 0)
- return True;
-
if(!prs_uint32("switch_value", ps, depth, &ctr->switch_value))
return False;
if(!prs_uint32("ptr_share_info", ps, depth, &ctr->ptr_share_info))
@@ -541,6 +789,33 @@ static BOOL srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct
return False;
switch (ctr->switch_value) {
+
+ case 0:
+ {
+ SRV_SHARE_INFO_0 *info0 = ctr->share.info0;
+ int num_entries = ctr->num_entries;
+ int i;
+
+ if (UNMARSHALLING(ps)) {
+ if (!(info0 = (SRV_SHARE_INFO_0 *)prs_alloc_mem(ps, num_entries * sizeof(SRV_SHARE_INFO_0))))
+ return False;
+ ctr->share.info0 = info0;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ if(!srv_io_share_info0("", &info0[i].info_0, ps, depth))
+ return False;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ info0[i].info_0_str.ptrs = &info0[i].info_0;
+ if(!srv_io_share_info0_str("", &info0[i].info_0_str, ps, depth))
+ return False;
+ }
+
+ break;
+ }
+
case 1:
{
SRV_SHARE_INFO_1 *info1 = ctr->share.info1;
@@ -559,6 +834,7 @@ static BOOL srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct
}
for (i = 0; i < num_entries; i++) {
+ info1[i].info_1_str.ptrs = &info1[i].info_1;
if(!srv_io_share_info1_str("", &info1[i].info_1_str, ps, depth))
return False;
}
@@ -632,8 +908,8 @@ static BOOL srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct
for (i = 0; i < num_entries; i++) {
if(!srv_io_share_info502("", &info502[i].info_502, ps, depth))
return False;
- }
-
+ }
+
for (i = 0; i < num_entries; i++) {
info502[i].info_502_str.ptrs = &info502[i].info_502;
if(!srv_io_share_info502_str("", &info502[i].info_502_str, ps, depth))
@@ -643,6 +919,118 @@ static BOOL srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct
break;
}
+ case 1004:
+ {
+ SRV_SHARE_INFO_1004 *info1004 = ctr->share.info1004;
+ int num_entries = ctr->num_entries;
+ int i;
+
+ if (UNMARSHALLING(ps)) {
+ if (!(info1004 = (SRV_SHARE_INFO_1004 *)prs_alloc_mem(ps,num_entries * sizeof(SRV_SHARE_INFO_1004))))
+ return False;
+ ctr->share.info1004 = info1004;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ if(!srv_io_share_info1004("", &info1004[i].info_1004, ps, depth))
+ return False;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ info1004[i].info_1004_str.ptrs = &info1004[i].info_1004;
+ if(!srv_io_share_info1004_str("", &info1004[i].info_1004_str, ps, depth))
+ return False;
+ }
+
+ break;
+ }
+
+ case 1005:
+ {
+ SRV_SHARE_INFO_1005 *info1005 = ctr->share.info1005;
+ int num_entries = ctr->num_entries;
+ int i;
+
+ if (UNMARSHALLING(ps)) {
+ if (!(info1005 = (SRV_SHARE_INFO_1005 *)prs_alloc_mem(ps,num_entries * sizeof(SRV_SHARE_INFO_1005))))
+ return False;
+ ctr->share.info1005 = info1005;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ if(!srv_io_share_info1005("", &info1005[i], ps, depth))
+ return False;
+ }
+
+ break;
+ }
+
+ case 1006:
+ {
+ SRV_SHARE_INFO_1006 *info1006 = ctr->share.info1006;
+ int num_entries = ctr->num_entries;
+ int i;
+
+ if (UNMARSHALLING(ps)) {
+ if (!(info1006 = (SRV_SHARE_INFO_1006 *)prs_alloc_mem(ps,num_entries * sizeof(SRV_SHARE_INFO_1006))))
+ return False;
+ ctr->share.info1006 = info1006;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ if(!srv_io_share_info1006("", &info1006[i], ps, depth))
+ return False;
+ }
+
+ break;
+ }
+
+ case 1007:
+ {
+ SRV_SHARE_INFO_1007 *info1007 = ctr->share.info1007;
+ int num_entries = ctr->num_entries;
+ int i;
+
+ if (UNMARSHALLING(ps)) {
+ if (!(info1007 = (SRV_SHARE_INFO_1007 *)prs_alloc_mem(ps,num_entries * sizeof(SRV_SHARE_INFO_1007))))
+ return False;
+ ctr->share.info1007 = info1007;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ if(!srv_io_share_info1007("", &info1007[i].info_1007, ps, depth))
+ return False;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ info1007[i].info_1007_str.ptrs = &info1007[i].info_1007;
+ if(!srv_io_share_info1007_str("", &info1007[i].info_1007_str, ps, depth))
+ return False;
+ }
+
+ break;
+ }
+
+ case 1501:
+ {
+ SRV_SHARE_INFO_1501 *info1501 = ctr->share.info1501;
+ int num_entries = ctr->num_entries;
+ int i;
+
+ if (UNMARSHALLING(ps)) {
+ if (!(info1501 = (SRV_SHARE_INFO_1501 *)prs_alloc_mem(ps,num_entries * sizeof(SRV_SHARE_INFO_1501))))
+ return False;
+ ctr->share.info1501 = info1501;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ if(!srv_io_share_info1501("", &info1501[i], ps, depth))
+ return False;
+ }
+
+ break;
+ }
+
default:
DEBUG(5,("%s no share info at switch_value %d\n",
tab_depth(depth), ctr->switch_value));
@@ -667,8 +1055,9 @@ void init_srv_q_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n,
q_n->ctr.info_level = q_n->ctr.switch_value = info_level;
q_n->ctr.ptr_share_info = 1;
- q_n->ctr.num_entries = 0;
- q_n->ctr.ptr_entries = 0;
+ q_n->ctr.num_entries = 0;
+ q_n->ctr.ptr_entries = 0;
+ q_n->ctr.num_entries2 = 0;
q_n->preferred_len = preferred_len;
memcpy(&q_n->enum_hnd, hnd, sizeof(*hnd));
@@ -729,8 +1118,12 @@ BOOL srv_io_r_net_share_enum(char *desc, SRV_R_NET_SHARE_ENUM *r_n, prs_struct *
if(!prs_uint32("total_entries", ps, depth, &r_n->total_entries))
return False;
- if(!smb_io_enum_hnd("enum_hnd", &r_n->enum_hnd, ps, depth))
- return False;
+
+ if(r_n->total_entries != 0) {
+ if(!smb_io_enum_hnd("enum_hnd", &r_n->enum_hnd, ps, depth))
+ return False;
+ }
+
if(!prs_werror("status", ps, depth, &r_n->status))
return False;
@@ -738,6 +1131,25 @@ BOOL srv_io_r_net_share_enum(char *desc, SRV_R_NET_SHARE_ENUM *r_n, prs_struct *
}
/*******************************************************************
+ initialises a structure.
+********************************************************************/
+
+BOOL init_srv_q_net_share_get_info(SRV_Q_NET_SHARE_GET_INFO *q_n, const char *srv_name, const char *share_name, uint32 info_level)
+{
+
+ uint32 ptr_share_name;
+
+ DEBUG(5,("init_srv_q_net_share_get_info\n"));
+
+ init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
+ init_buf_unistr2(&q_n->uni_share_name, &ptr_share_name, share_name);
+
+ q_n->info_level = info_level;
+
+ return True;
+}
+
+/*******************************************************************
Reads or writes a structure.
********************************************************************/
@@ -792,10 +1204,24 @@ static BOOL srv_io_srv_share_info(char *desc, prs_struct *ps, int depth, SRV_SHA
if (r_n->ptr_share_ctr != 0) {
switch (r_n->switch_value) {
+ case 0:
+ if(!srv_io_share_info0("", &r_n->share.info0.info_0, ps, depth))
+ return False;
+
+ /* allow access to pointers in the str part. */
+ r_n->share.info0.info_0_str.ptrs = &r_n->share.info0.info_0;
+
+ if(!srv_io_share_info0_str("", &r_n->share.info0.info_0_str, ps, depth))
+ return False;
+
+ break;
case 1:
if(!srv_io_share_info1("", &r_n->share.info1.info_1, ps, depth))
return False;
+ /* allow access to pointers in the str part. */
+ r_n->share.info1.info_1_str.ptrs = &r_n->share.info1.info_1;
+
if(!srv_io_share_info1_str("", &r_n->share.info1.info_1_str, ps, depth))
return False;
@@ -819,16 +1245,40 @@ static BOOL srv_io_srv_share_info(char *desc, prs_struct *ps, int depth, SRV_SHA
if(!srv_io_share_info502("", &r_n->share.info502.info_502, ps, depth))
return False;
- /*allow access to pointers in the str part. */
+ /* allow access to pointers in the str part. */
r_n->share.info502.info_502_str.ptrs = &r_n->share.info502.info_502;
if(!srv_io_share_info502_str("", &r_n->share.info502.info_502_str, ps, depth))
return False;
break;
+ case 1004:
+ if(!srv_io_share_info1004("", &r_n->share.info1004.info_1004, ps, depth))
+ return False;
+
+ /* allow access to pointers in the str part. */
+ r_n->share.info1004.info_1004_str.ptrs = &r_n->share.info1004.info_1004;
+
+ if(!srv_io_share_info1004_str("", &r_n->share.info1004.info_1004_str, ps, depth))
+ return False;
+ break;
case 1005:
if(!srv_io_share_info1005("", &r_n->share.info1005, ps, depth))
return False;
break;
+ case 1006:
+ if(!srv_io_share_info1006("", &r_n->share.info1006, ps, depth))
+ return False;
+ break;
+ case 1007:
+ if(!srv_io_share_info1007("", &r_n->share.info1007.info_1007, ps, depth))
+ return False;
+
+ /* allow access to pointers in the str part. */
+ r_n->share.info1007.info_1007_str.ptrs = &r_n->share.info1007.info_1007;
+
+ if(!srv_io_share_info1007_str("", &r_n->share.info1007.info_1007_str, ps, depth))
+ return False;
+ break;
case 1501:
if (!srv_io_share_info1501("", &r_n->share.info1501, ps, depth))
return False;
@@ -870,6 +1320,34 @@ BOOL srv_io_r_net_share_get_info(char *desc, SRV_R_NET_SHARE_GET_INFO *r_n, prs_
}
/*******************************************************************
+ intialises a structure.
+********************************************************************/
+
+BOOL init_srv_q_net_share_set_info(SRV_Q_NET_SHARE_SET_INFO *q_n,
+ const char *srv_name,
+ const char *share_name,
+ uint32 info_level,
+ const SRV_SHARE_INFO *info)
+{
+
+ uint32 ptr_share_name;
+
+ DEBUG(5,("init_srv_q_net_share_set_info\n"));
+
+ init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
+ init_buf_unistr2(&q_n->uni_share_name, &ptr_share_name, share_name);
+
+ q_n->info_level = info_level;
+
+ q_n->info = *info;
+
+ q_n->ptr_parm_error = 1;
+ q_n->parm_error = 0;
+
+ return True;
+}
+
+/*******************************************************************
Reads or writes a structure.
********************************************************************/
@@ -904,6 +1382,15 @@ BOOL srv_io_q_net_share_set_info(char *desc, SRV_Q_NET_SHARE_SET_INFO *q_n, prs_
if(!srv_io_srv_share_info("info ", ps, depth, &q_n->info))
return False;
+ if(!prs_align(ps))
+ return False;
+ if(!prs_uint32("ptr_parm_error", ps, depth, &q_n->ptr_parm_error))
+ return False;
+ if(q_n->ptr_parm_error!=0) {
+ if(!prs_uint32("parm_error", ps, depth, &q_n->parm_error))
+ return False;
+ }
+
return True;
}
@@ -911,9 +1398,9 @@ BOOL srv_io_q_net_share_set_info(char *desc, SRV_Q_NET_SHARE_SET_INFO *q_n, prs_
Reads or writes a structure.
********************************************************************/
-BOOL srv_io_r_net_share_set_info(char *desc, SRV_R_NET_SHARE_SET_INFO *q_n, prs_struct *ps, int depth)
+BOOL srv_io_r_net_share_set_info(char *desc, SRV_R_NET_SHARE_SET_INFO *r_n, prs_struct *ps, int depth)
{
- if (q_n == NULL)
+ if (r_n == NULL)
return False;
prs_debug(ps, depth, desc, "srv_io_r_net_share_set_info");
@@ -922,14 +1409,22 @@ BOOL srv_io_r_net_share_set_info(char *desc, SRV_R_NET_SHARE_SET_INFO *q_n, prs_
if(!prs_align(ps))
return False;
- if(!prs_uint32("switch_value ", ps, depth, &q_n->switch_value))
+ if(!prs_uint32("ptr_parm_error ", ps, depth, &r_n->ptr_parm_error))
return False;
- if(!prs_werror("status", ps, depth, &q_n->status))
+
+ if(r_n->ptr_parm_error) {
+
+ if(!prs_uint32("parm_error ", ps, depth, &r_n->parm_error))
+ return False;
+ }
+
+ if(!prs_werror("status", ps, depth, &r_n->status))
return False;
return True;
}
+
/*******************************************************************
Reads or writes a structure.
********************************************************************/
@@ -962,6 +1457,9 @@ BOOL srv_io_q_net_share_add(char *desc, SRV_Q_NET_SHARE_ADD *q_n, prs_struct *ps
if(!srv_io_srv_share_info("info ", ps, depth, &q_n->info))
return False;
+ if(!prs_align(ps))
+ return False;
+
if(!prs_uint32("ptr_err_index", ps, depth, &q_n->ptr_err_index))
return False;
if (q_n->ptr_err_index)
@@ -994,9 +1492,9 @@ void init_srv_q_net_share_add(SRV_Q_NET_SHARE_ADD *q, char *srvname,
Reads or writes a structure.
********************************************************************/
-BOOL srv_io_r_net_share_add(char *desc, SRV_R_NET_SHARE_ADD *q_n, prs_struct *ps, int depth)
+BOOL srv_io_r_net_share_add(char *desc, SRV_R_NET_SHARE_ADD *r_n, prs_struct *ps, int depth)
{
- if (q_n == NULL)
+ if (r_n == NULL)
return False;
prs_debug(ps, depth, desc, "srv_io_r_net_share_add");
@@ -1005,14 +1503,25 @@ BOOL srv_io_r_net_share_add(char *desc, SRV_R_NET_SHARE_ADD *q_n, prs_struct *ps
if(!prs_align(ps))
return False;
- if(!prs_uint32("switch_value ", ps, depth, &q_n->switch_value))
+ if(!prs_uint32("ptr_parm_error", ps, depth, &r_n->ptr_parm_error))
return False;
- if(!prs_werror("status", ps, depth, &q_n->status))
+
+ if(r_n->ptr_parm_error) {
+
+ if(!prs_uint32("parm_error", ps, depth, &r_n->parm_error))
+ return False;
+ }
+
+ if(!prs_werror("status", ps, depth, &r_n->status))
return False;
return True;
}
+/*******************************************************************
+ initialises a structure.
+********************************************************************/
+
void init_srv_q_net_share_del(SRV_Q_NET_SHARE_DEL *del, const char *srvname,
const char *sharename)
{
@@ -1889,8 +2398,8 @@ static BOOL srv_io_file_info3_str(char *desc, FILE_INFO_3_STR *sh1, prs_struct *
********************************************************************/
void init_srv_file_info3(FILE_INFO_3 *fl3,
- uint32 id, uint32 perms, uint32 num_locks,
- char *path_name, char *user_name)
+ uint32 id, uint32 perms, uint32 num_locks,
+ char *path_name, char *user_name)
{
DEBUG(5,("init_srv_file_info3: %s %s\n", path_name, user_name));
@@ -2004,7 +2513,8 @@ static BOOL srv_io_srv_file_ctr(char *desc, SRV_FILE_INFO_CTR *ctr, prs_struct *
********************************************************************/
void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
- char *srv_name, char *qual_name, char *user_name,
+ const char *srv_name, const char *qual_name,
+ const char *user_name,
uint32 file_level, SRV_FILE_INFO_CTR *ctr,
uint32 preferred_len,
ENUM_HND *hnd)
@@ -2295,7 +2805,7 @@ void init_srv_info_102(SRV_INFO_102 *sv102, uint32 platform_id, char *name,
sv102->disc = disc;
sv102->hidden = hidden;
sv102->announce = announce;
- sv102->ann_delta =ann_delta;
+ sv102->ann_delta = ann_delta;
sv102->licenses = licenses;
init_buf_unistr2(&sv102->uni_usr_path, &sv102->ptr_usr_path, usr_path);
}
@@ -2559,7 +3069,7 @@ BOOL srv_io_r_net_srv_set_info(char *desc, SRV_R_NET_SRV_SET_INFO *r_n,
if(!prs_align(ps))
return False;
- if(!prs_uint32("switch_value ", ps, depth, &r_n->switch_value))
+ if(!prs_uint32("switch value ", ps, depth, &r_n->switch_value))
return False;
if(!prs_werror("status", ps, depth, &r_n->status))
@@ -2688,6 +3198,31 @@ BOOL srv_io_r_net_remote_tod(char *desc, SRV_R_NET_REMOTE_TOD *r_n, prs_struct *
}
/*******************************************************************
+ initialises a structure.
+ ********************************************************************/
+
+BOOL init_srv_q_net_disk_enum(SRV_Q_NET_DISK_ENUM *q_n,
+ const char *srv_name,
+ uint32 preferred_len,
+ ENUM_HND *enum_hnd
+ )
+{
+
+
+ DEBUG(5,("init_srv_q_net_srv_disk_enum\n"));
+
+ init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
+
+ q_n->disk_enum_ctr.level = 0;
+ q_n->disk_enum_ctr.disk_info_ptr = 0;
+
+ q_n->preferred_len = preferred_len;
+ memcpy(&q_n->enum_hnd, enum_hnd, sizeof(*enum_hnd));
+
+ return True;
+}
+
+/*******************************************************************
Reads or writes a structure.
********************************************************************/
@@ -2737,7 +3272,9 @@ BOOL srv_io_q_net_disk_enum(char *desc, SRV_Q_NET_DISK_ENUM *q_n, prs_struct *ps
BOOL srv_io_r_net_disk_enum(char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_struct *ps, int depth)
{
+
int i;
+ uint32 entries_read, entries_read2, entries_read3;
if (r_n == NULL)
return False;
@@ -2745,23 +3282,36 @@ BOOL srv_io_r_net_disk_enum(char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_struct *ps
prs_debug(ps, depth, desc, "srv_io_r_net_disk_enum");
depth++;
+ entries_read = entries_read2 = entries_read3 = r_n->disk_enum_ctr.entries_read;
+
if(!prs_align(ps))
return False;
- if(!prs_uint32("entries_read", ps, depth, &r_n->disk_enum_ctr.entries_read))
+ if(!prs_uint32("entries_read", ps, depth, &entries_read))
return False;
if(!prs_uint32("ptr_disk_info", ps, depth, &r_n->disk_enum_ctr.disk_info_ptr))
return False;
/*this may be max, unknown, actual?*/
- if(!prs_uint32("max_elements", ps, depth, &r_n->disk_enum_ctr.entries_read))
+ if(!prs_uint32("max_elements", ps, depth, &entries_read2))
return False;
if(!prs_uint32("unknown", ps, depth, &r_n->disk_enum_ctr.unknown))
return False;
- if(!prs_uint32("actual_elements", ps, depth, &r_n->disk_enum_ctr.entries_read))
+ if(!prs_uint32("actual_elements", ps, depth, &entries_read3))
return False;
+ r_n->disk_enum_ctr.entries_read = entries_read3;
+
+ if(UNMARSHALLING(ps)) {
+
+ DISK_INFO *dinfo;
+
+ if(!(dinfo = (DISK_INFO *)prs_alloc_mem(ps, sizeof(*dinfo) * entries_read3)))
+ return False;
+ r_n->disk_enum_ctr.disk_info = dinfo;
+ }
+
for(i=0; i < r_n->disk_enum_ctr.entries_read; i++) {
if(!prs_uint32("unknown", ps, depth, &r_n->disk_enum_ctr.disk_info[i].unknown))
@@ -2787,6 +3337,25 @@ BOOL srv_io_r_net_disk_enum(char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_struct *ps
}
/*******************************************************************
+ initialises a structure.
+ ********************************************************************/
+
+BOOL init_srv_q_net_name_validate(SRV_Q_NET_NAME_VALIDATE *q_n, const char *srv_name, const char *share_name, int type)
+{
+ uint32 ptr_share_name;
+
+ DEBUG(5,("init_srv_q_net_name_validate\n"));
+
+ init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
+ init_buf_unistr2(&q_n->uni_name, &ptr_share_name, share_name);
+
+ q_n->type = type;
+ q_n->flags = 0;
+
+ return True;
+}
+
+/*******************************************************************
Reads or writes a structure.
********************************************************************/