diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2002-08-17 17:00:51 +0000 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2002-08-17 17:00:51 +0000 |
commit | 3928578b52cfc949be5e0ef444fce1558d75f290 (patch) | |
tree | 651ed4a38e217dfa3f3874e7db8e45e7429af1f0 | |
parent | eac75549c398f208484ae735d5a5931fed6d0e99 (diff) | |
download | samba-3928578b52cfc949be5e0ef444fce1558d75f290.tar.gz samba-3928578b52cfc949be5e0ef444fce1558d75f290.tar.xz samba-3928578b52cfc949be5e0ef444fce1558d75f290.zip |
sync 3.0 branch with head
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. ********************************************************************/ |