summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-07-15 10:35:28 +0000
committerAndrew Tridgell <tridge@samba.org>2002-07-15 10:35:28 +0000
commite90b65284812aaa5ff9e9935ce9bbad7791cbbcd (patch)
tree9e744d1dc2f93934a4b49166a37383d3cb2b2139 /source3/libsmb
parentec167dc9cc0ec2ee461837c25a371d2981744208 (diff)
downloadsamba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.tar.gz
samba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.tar.bz2
samba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.zip
updated the 3.0 branch from the head branch - ready for alpha18
(This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce)
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cli_dfs.c8
-rw-r--r--source3/libsmb/cli_lsarpc.c52
-rw-r--r--source3/libsmb/cli_netlogon.c21
-rw-r--r--source3/libsmb/cli_reg.c9
-rw-r--r--source3/libsmb/cli_samr.c132
-rw-r--r--source3/libsmb/cli_spoolss.c645
-rw-r--r--source3/libsmb/cli_srvsvc.c381
-rw-r--r--source3/libsmb/cli_wkssvc.c18
-rw-r--r--source3/libsmb/cliconnect.c528
-rw-r--r--source3/libsmb/clientgen.c61
-rw-r--r--source3/libsmb/clifile.c2
-rw-r--r--source3/libsmb/clilist.c10
-rw-r--r--source3/libsmb/clirap.c14
-rw-r--r--source3/libsmb/clirap2.c10
-rw-r--r--source3/libsmb/clireadwrite.c64
-rw-r--r--source3/libsmb/clispnego.c43
-rw-r--r--source3/libsmb/errormap.c1
-rw-r--r--source3/libsmb/libsmbclient.c1691
-rw-r--r--source3/libsmb/namequery.c662
-rw-r--r--source3/libsmb/nmblib.c4
-rw-r--r--source3/libsmb/nterr.c1
-rw-r--r--source3/libsmb/pwd_cache.c137
-rw-r--r--source3/libsmb/smbencrypt.c131
-rw-r--r--source3/libsmb/trust_passwd.c10
-rw-r--r--source3/libsmb/unexpected.c2
25 files changed, 2699 insertions, 1938 deletions
diff --git a/source3/libsmb/cli_dfs.c b/source3/libsmb/cli_dfs.c
index 312275926c..7fc27b9c3b 100644
--- a/source3/libsmb/cli_dfs.c
+++ b/source3/libsmb/cli_dfs.c
@@ -20,14 +20,6 @@
#include "includes.h"
-/* Opens a SMB connection to the netdfs pipe */
-
-struct cli_state *cli_dfs_initialise(struct cli_state *cli, char *system_name,
- struct ntuser_creds *creds)
-{
- return cli_pipe_initialise(cli, system_name, PIPE_NETDFS, creds);
-}
-
/* Query DFS support */
NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
diff --git a/source3/libsmb/cli_lsarpc.c b/source3/libsmb/cli_lsarpc.c
index 23cedf1f08..7dfee46fae 100644
--- a/source3/libsmb/cli_lsarpc.c
+++ b/source3/libsmb/cli_lsarpc.c
@@ -5,7 +5,8 @@
Copyright (C) Andrew Tridgell 1992-1997,2000,
Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
Copyright (C) Paul Ashton 1997,2000,
- Copyright (C) Elrond 2000.
+ Copyright (C) Elrond 2000,
+ Copyright (C) Rafal Szczesniak 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
@@ -37,19 +38,6 @@
* security authority", which is half of a password database.
**/
-/** Opens a SMB connection and connects to the LSARPC pipe.
- *
- * @param cli Uninitialised client handle.
- * @param system_name NETBIOS name of the machine to connect to.
- * @param creds User credentials to connect as.
- * @returns Initialised client handle.
- */
-struct cli_state *cli_lsa_initialise(struct cli_state *cli, char *system_name,
- struct ntuser_creds *creds)
-{
- return cli_pipe_initialise(cli, system_name, PIPE_LSARPC, creds);
-}
-
/** Open a LSA policy handle
*
* @param cli Handle on an initialised SMB connection */
@@ -275,7 +263,7 @@ NTSTATUS cli_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
if (!NT_STATUS_IS_OK(result) &&
NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
-
+
/* An actual error occured */
goto done;
@@ -389,8 +377,8 @@ NTSTATUS cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
result = r.status;
- if (!NT_STATUS_IS_OK(result) &&
- NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
+ if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) !=
+ NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
/* An actual error occured */
@@ -537,12 +525,25 @@ NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
-/** Enumerate list of trusted domains */
+/**
+ * Enumerate list of trusted domains
+ *
+ * @param cli client state (cli_state) structure of the connection
+ * @param mem_ctx memory context
+ * @param pol opened lsa policy handle
+ * @param enum_ctx enumeration context ie. index of first returned domain entry
+ * @param pref_num_domains preferred max number of entries returned in one response
+ * @param num_domains total number of trusted domains returned by response
+ * @param domain_names returned trusted domain names
+ * @param domain_sids returned trusted domain sids
+ *
+ * @return nt status code of response
+ **/
NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 *enum_ctx,
- uint32 *num_domains, char ***domain_names,
- DOM_SID **domain_sids)
+ uint32 *pref_num_domains, uint32 *num_domains,
+ char ***domain_names, DOM_SID **domain_sids)
{
prs_struct qbuf, rbuf;
LSA_Q_ENUM_TRUST_DOM q;
@@ -560,7 +561,7 @@ NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Marshall data and send request */
- init_q_enum_trust_dom(&q, pol, *enum_ctx, 0xffffffff);
+ init_q_enum_trust_dom(&q, pol, *enum_ctx, *pref_num_domains);
if (!lsa_io_q_enum_trust_dom("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, LSA_ENUMTRUSTDOM, &qbuf, &rbuf)) {
@@ -577,16 +578,15 @@ NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx,
result = r.status;
- if (!NT_STATUS_IS_OK(result) &&
- NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_NO_MORE_ENTRIES)) {
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, NT_STATUS_NO_MORE_ENTRIES) &&
+ !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
/* An actual error ocured */
goto done;
}
- result = NT_STATUS_OK;
-
/* Return output parameters */
if (r.num_domains) {
@@ -1122,7 +1122,7 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
goto done;
}
- if (!(cli.sec_mode & 1)) {
+ if (!(cli.sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
DEBUG(0,("fetch_domain_sid: machine %s isn't in user level security mode\n",
remote_machine));
goto done;
diff --git a/source3/libsmb/cli_netlogon.c b/source3/libsmb/cli_netlogon.c
index 125590b6d3..d32e0e77e4 100644
--- a/source3/libsmb/cli_netlogon.c
+++ b/source3/libsmb/cli_netlogon.c
@@ -25,15 +25,6 @@
#include "includes.h"
-/* Opens a SMB connection to the netlogon pipe */
-
-struct cli_state *cli_netlogon_initialise(struct cli_state *cli,
- char *system_name,
- struct ntuser_creds *creds)
-{
- return cli_pipe_initialise(cli, system_name, PIPE_NETLOGON, creds);
-}
-
/* LSA Request Challenge. Sends our challenge to server, then gets
server response. These are used to generate the credentials. */
@@ -51,8 +42,8 @@ NTSTATUS new_cli_net_req_chal(struct cli_state *cli, DOM_CHAL *clnt_chal,
/* create and send a MSRPC command with api NET_REQCHAL */
- DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s: %s\n",
- cli->desthost, global_myname, credstr(clnt_chal->data)));
+ DEBUG(4,("new_cli_net_req_chal: LSA Request Challenge from %s to %s: %s\n",
+ global_myname, cli->desthost, credstr(clnt_chal->data)));
/* store the parameters */
init_q_req_chal(&q, cli->srv_name_slash, global_myname, clnt_chal);
@@ -108,7 +99,7 @@ NTSTATUS new_cli_net_auth2(struct cli_state *cli,
/* create and send a MSRPC command with api NET_AUTH2 */
- DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
+ DEBUG(4,("new_cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname,
credstr(cli->clnt_cred.challenge.data), neg_flags));
@@ -147,7 +138,7 @@ NTSTATUS new_cli_net_auth2(struct cli_state *cli,
/*
* Server replied with bad credential. Fail.
*/
- DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \
+ DEBUG(0,("new_cli_net_auth2: server %s replied with bad credential (bad machine \
password ?).\n", cli->desthost ));
result = NT_STATUS_ACCESS_DENIED;
goto done;
@@ -180,7 +171,7 @@ NTSTATUS new_cli_nt_setup_creds(struct cli_state *cli,
result = new_cli_net_req_chal(cli, &clnt_chal, &srv_chal);
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(0,("cli_nt_setup_creds: request challenge failed\n"));
+ DEBUG(0,("new_cli_nt_setup_creds: request challenge failed\n"));
return result;
}
@@ -206,7 +197,7 @@ NTSTATUS new_cli_nt_setup_creds(struct cli_state *cli,
result = new_cli_net_auth2(cli, sec_chan, 0x000001ff,
&srv_chal);
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(0,("cli_nt_setup_creds: auth2 challenge failed %s\n",
+ DEBUG(1,("cli_nt_setup_creds: auth2 challenge failed %s\n",
nt_errstr(result)));
}
diff --git a/source3/libsmb/cli_reg.c b/source3/libsmb/cli_reg.c
index c09ccabb29..aaf18882f7 100644
--- a/source3/libsmb/cli_reg.c
+++ b/source3/libsmb/cli_reg.c
@@ -25,15 +25,6 @@
#include "includes.h"
-/* Opens a SMB connection to the WINREG pipe */
-
-struct cli_state *cli_winreg_initialise(struct cli_state *cli,
- char *system_name,
- struct ntuser_creds *creds)
-{
- return cli_pipe_initialise(cli, system_name, PIPE_WINREG, creds);
-}
-
/* Shutdown a server */
NTSTATUS cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx,
diff --git a/source3/libsmb/cli_samr.c b/source3/libsmb/cli_samr.c
index 85a7375f99..91577b3325 100644
--- a/source3/libsmb/cli_samr.c
+++ b/source3/libsmb/cli_samr.c
@@ -24,14 +24,6 @@
#include "includes.h"
-/* Opens a SMB connection to the SAMR pipe */
-
-struct cli_state *cli_samr_initialise(struct cli_state *cli, char *system_name,
- struct ntuser_creds *creds)
-{
- return cli_pipe_initialise(cli, system_name, PIPE_SAMR, creds);
-}
-
/* Connect to SAMR database */
NTSTATUS cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx,
@@ -55,15 +47,13 @@ NTSTATUS cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_connect(&q, cli->desthost, access_mask);
if (!samr_io_q_connect("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_connect("", &r, &rbuf, 0)) {
+ if (!samr_io_r_connect("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -104,15 +94,13 @@ NTSTATUS cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_close_hnd(&q, connect_pol);
if (!samr_io_q_close_hnd("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_close_hnd("", &r, &rbuf, 0)) {
+ if (!samr_io_r_close_hnd("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -154,15 +142,13 @@ NTSTATUS cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_open_domain(&q, connect_pol, access_mask, domain_sid);
if (!samr_io_q_open_domain("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_open_domain("", &r, &rbuf, 0)) {
+ if (!samr_io_r_open_domain("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -204,15 +190,13 @@ NTSTATUS cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_open_user(&q, domain_pol, access_mask, user_rid);
if (!samr_io_q_open_user("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_open_user("", &r, &rbuf, 0)) {
+ if (!samr_io_r_open_user("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -254,15 +238,13 @@ NTSTATUS cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_open_group(&q, domain_pol, access_mask, group_rid);
if (!samr_io_q_open_group("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_open_group("", &r, &rbuf, 0)) {
+ if (!samr_io_r_open_group("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -304,15 +286,13 @@ NTSTATUS cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_query_userinfo(&q, user_pol, switch_value);
if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_query_userinfo("", &r, &rbuf, 0)) {
+ if (!samr_io_r_query_userinfo("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -350,17 +330,15 @@ NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_query_groupinfo(&q, group_pol, info_level);
if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
r.ctr = ctr;
- if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0)) {
+ if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -397,15 +375,13 @@ NTSTATUS cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_query_usergroups(&q, user_pol);
if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_query_usergroups("", &r, &rbuf, 0)) {
+ if (!samr_io_r_query_usergroups("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -431,7 +407,7 @@ NTSTATUS cli_samr_query_useraliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
SAMR_Q_QUERY_USERALIASES q;
SAMR_R_QUERY_USERALIASES r;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- uint ptr=1;
+ unsigned int ptr=1;
ZERO_STRUCT(q);
ZERO_STRUCT(r);
@@ -446,15 +422,13 @@ NTSTATUS cli_samr_query_useraliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_query_useraliases(&q, user_pol, num_sids, &ptr, sid);
if (!samr_io_q_query_useraliases("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_QUERY_USERALIASES, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_QUERY_USERALIASES, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_query_useraliases("", &r, &rbuf, 0)) {
+ if (!samr_io_r_query_useraliases("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -494,15 +468,13 @@ NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_query_groupmem(&q, group_pol);
if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_query_groupmem("", &r, &rbuf, 0)) {
+ if (!samr_io_r_query_groupmem("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
@@ -545,24 +517,21 @@ NTSTATUS cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf))
goto done;
- }
/* Unmarshall response */
- if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) {
+ if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0))
goto done;
- }
/* Return output parameters */
result = r.status;
if (!NT_STATUS_IS_OK(result) &&
- NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) {
+ NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES))
goto done;
- }
*num_dom_groups = r.num_entries2;
@@ -971,7 +940,7 @@ NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *domain_pol, uint32 flags,
- uint32 num_names, char **names,
+ uint32 num_names, const char **names,
uint32 *num_rids, uint32 **rids,
uint32 **rid_types)
{
@@ -1272,3 +1241,54 @@ NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
+
+/* Get domain password info */
+
+NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint16 *unk_0, uint16 *unk_1, uint16 *unk_2)
+{
+ prs_struct qbuf, rbuf;
+ SAMR_Q_GET_DOM_PWINFO q;
+ SAMR_R_GET_DOM_PWINFO r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Marshall data and send request */
+
+ init_samr_q_get_dom_pwinfo(&q, cli->desthost);
+
+ if (!samr_io_q_get_dom_pwinfo("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SAMR_GET_DOM_PWINFO, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!samr_io_r_get_dom_pwinfo("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ if (NT_STATUS_IS_OK(result)) {
+ if (unk_0)
+ *unk_0 = r.unk_0;
+ if (unk_1)
+ *unk_1 = r.unk_1;
+ if (unk_2)
+ *unk_2 = r.unk_2;
+ }
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
diff --git a/source3/libsmb/cli_spoolss.c b/source3/libsmb/cli_spoolss.c
index 0458b29d54..18e17758d6 100644
--- a/source3/libsmb/cli_spoolss.c
+++ b/source3/libsmb/cli_spoolss.c
@@ -31,20 +31,6 @@
* @{
**/
-/** Opens a SMB connection and connects to the SPOOLSS pipe.
- *
- * @param cli Uninitialised client handle.
- * @param system_name NETBIOS name of the machine to connect to.
- * @param creds User credentials to connect as.
- * @returns Initialised client handle.
- */
-struct cli_state *cli_spoolss_initialise(struct cli_state *cli,
- char *system_name,
- struct ntuser_creds *creds)
-{
- return cli_pipe_initialise(cli, system_name, PIPE_SPOOLSS, creds);
-}
-
/**********************************************************************
Initialize a new spoolss buff for use by a client rpc
**********************************************************************/
@@ -420,8 +406,8 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
ZERO_STRUCT(q);
ZERO_STRUCT(r);
- fstrcpy (server, cli->desthost);
- strupper (server);
+ slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+ strupper (server);
/* Initialise input parameters */
@@ -620,7 +606,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
result = r.status;
- if (NT_STATUS_IS_OK(result)) {
+ if (W_ERROR_IS_OK(result)) {
switch (level) {
case 0:
decode_printer_info_0(mem_ctx, r.buffer, 1, &ctr->printers_0);
@@ -1492,48 +1478,6 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
-/*********************************************************************************
- Win32 API - SetPrinterData()
- ********************************************************************************/
-
-WERROR cli_spoolss_setprinterdata (struct cli_state *cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *pol, char* valname, char* value)
-{
- prs_struct qbuf, rbuf;
- SPOOL_Q_SETPRINTERDATA q;
- SPOOL_R_SETPRINTERDATA r;
- WERROR result = W_ERROR(ERRgeneral);
-
- ZERO_STRUCT(q);
- ZERO_STRUCT(r);
-
- /* Initialise input parameters */
-
- prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
- prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-
- /* write the request */
- make_spoolss_q_setprinterdata(&q, mem_ctx, pol, valname, value);
-
- /* Marshall data and send request */
- if (!spoolss_io_q_setprinterdata ("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req (cli, SPOOLSS_SETPRINTERDATA, &qbuf, &rbuf))
- goto done;
-
- /* Unmarshall response */
- if (spoolss_io_r_setprinterdata ("", &r, &rbuf, 0))
- goto done;
-
- result = r.status;
-
-done:
- prs_mem_free(&qbuf);
- prs_mem_free(&rbuf);
-
- return result;
-}
-
static void decode_jobs_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
uint32 num_jobs, JOB_INFO_1 **jobs)
{
@@ -1612,11 +1556,123 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
switch(level) {
case 1:
decode_jobs_1(mem_ctx, r.buffer, r.returned,
- &ctr->job.job_info_1);
+ ctr->job.job_info_1);
break;
case 2:
decode_jobs_2(mem_ctx, r.buffer, r.returned,
- &ctr->job.job_info_2);
+ ctr->job.job_info_2);
+ break;
+ default:
+ DEBUG(3, ("unsupported info level %d", level));
+ break;
+ }
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Set job */
+
+WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 jobid, uint32 level,
+ uint32 command)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_SETJOB q;
+ SPOOL_R_SETJOB r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_setjob(&q, hnd, jobid, level, command);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_setjob("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_SETJOB, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_setjob("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Get job */
+
+WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 offered, uint32 *needed,
+ POLICY_HND *hnd, uint32 jobid, uint32 level,
+ JOB_INFO_CTR *ctr)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_GETJOB q;
+ SPOOL_R_GETJOB r;
+ WERROR result = W_ERROR(ERRgeneral);
+ NEW_BUFFER buffer;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ init_buffer(&buffer, offered, mem_ctx);
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_getjob(&q, hnd, jobid, level, &buffer, offered);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_getjob("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_GETJOB, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_getjob("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ if (needed)
+ *needed = r.needed;
+
+ if (!W_ERROR_IS_OK(r.status))
+ goto done;
+
+ switch(level) {
+ case 1:
+ decode_jobs_1(mem_ctx, r.buffer, 1, ctr->job.job_info_1);
+ break;
+ case 2:
+ decode_jobs_2(mem_ctx, r.buffer, 1, ctr->job.job_info_2);
break;
default:
DEBUG(3, ("unsupported info level %d", level));
@@ -1630,4 +1686,471 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
+/* Startpageprinter. Sent to notify the spooler when a page is about to be
+ sent to a printer. */
+
+WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_STARTPAGEPRINTER q;
+ SPOOL_R_STARTPAGEPRINTER r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_startpageprinter(&q, hnd);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_startpageprinter("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_STARTPAGEPRINTER, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_startpageprinter("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Endpageprinter. Sent to notify the spooler when a page has finished
+ being sent to a printer. */
+
+WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_ENDPAGEPRINTER q;
+ SPOOL_R_ENDPAGEPRINTER r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_endpageprinter(&q, hnd);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_endpageprinter("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_ENDPAGEPRINTER, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_endpageprinter("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Startdocprinter. Sent to notify the spooler that a document is about
+ to be spooled for printing. */
+
+WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, char *docname,
+ char *outputfile, char *datatype,
+ uint32 *jobid)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_STARTDOCPRINTER q;
+ SPOOL_R_STARTDOCPRINTER r;
+ WERROR result = W_ERROR(ERRgeneral);
+ uint32 level = 1;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_startdocprinter(&q, hnd, level, docname, outputfile,
+ datatype);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_startdocprinter("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_STARTDOCPRINTER, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_startdocprinter("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ if (W_ERROR_IS_OK(result))
+ *jobid = r.jobid;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Enddocprinter. Sent to notify the spooler that a document has finished
+ being spooled. */
+
+WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_ENDDOCPRINTER q;
+ SPOOL_R_ENDDOCPRINTER r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_enddocprinter(&q, hnd);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_enddocprinter("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_ENDDOCPRINTER, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_enddocprinter("", &r, &rbuf, 0))
+ goto done;
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Get printer data */
+
+WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 offered, uint32 *needed,
+ POLICY_HND *hnd, char *valuename,
+ uint32 *data_type, char **data,
+ uint32 *data_size)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_GETPRINTERDATA q;
+ SPOOL_R_GETPRINTERDATA r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_getprinterdata(&q, hnd, valuename, offered);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_getprinterdata("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTERDATA, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_getprinterdata("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ if (needed)
+ *needed = r.needed;
+
+ if (!W_ERROR_IS_OK(r.status))
+ goto done;
+
+ /* Return output parameters */
+
+ if (data_type)
+ *data_type = r.type;
+
+ if (data) {
+ *data = (char *)talloc(mem_ctx, r.needed);
+ memcpy(*data, r.data, r.needed);
+ }
+
+ if (data_size)
+ *data_size = r.needed;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Set printer data */
+
+WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, char *value,
+ uint32 data_type, char *data,
+ uint32 data_size)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_SETPRINTERDATA q;
+ SPOOL_R_SETPRINTERDATA r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_setprinterdata(&q, hnd, value, data, data_size);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_setprinterdata("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTERDATA, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_setprinterdata("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ if (!W_ERROR_IS_OK(r.status))
+ goto done;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Enum printer data */
+
+WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 ndx,
+ uint32 value_offered, uint32 data_offered,
+ uint32 *value_needed, uint32 *data_needed,
+ char **value, uint32 *data_type, char **data,
+ uint32 *data_size)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_ENUMPRINTERDATA q;
+ SPOOL_R_ENUMPRINTERDATA r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_enumprinterdata(&q, hnd, ndx, value_offered, data_offered);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_enumprinterdata("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERDATA, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_enumprinterdata("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ if (!W_ERROR_IS_OK(r.status))
+ goto done;
+
+ /* Return data */
+
+ if (value_needed)
+ *value_needed = r.realvaluesize;
+
+ if (data_needed)
+ *data_needed = r.realdatasize;
+
+ if (data_type)
+ *data_type = r.type;
+
+ if (value) {
+ fstring the_value;
+
+ rpcstr_pull(the_value, r.value, sizeof(the_value), -1,
+ STR_TERMINATE);
+
+ *value = talloc_strdup(mem_ctx, the_value);
+ }
+
+ if (data)
+ *data = talloc_memdup(mem_ctx, r.data, r.realdatasize);
+
+ if (data_size)
+ *data_size = r.realdatasize;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Write data to printer */
+
+WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 data_size, char *data,
+ uint32 *num_written)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_WRITEPRINTER q;
+ SPOOL_R_WRITEPRINTER r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_writeprinter(&q, hnd, data_size, data);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_writeprinter("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_WRITEPRINTER, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_writeprinter("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ if (!W_ERROR_IS_OK(r.status))
+ goto done;
+
+ if (num_written)
+ *num_written = r.buffer_written;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+/* Delete printer data */
+
+WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, char *valuename)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_DELETEPRINTERDATA q;
+ SPOOL_R_DELETEPRINTERDATA r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ make_spoolss_q_deleteprinterdata(&q, hnd, valuename);
+
+ /* Marshall data and send request */
+
+ if (!spoolss_io_q_deleteprinterdata("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SPOOLSS_DELETEPRINTERDATA, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!spoolss_io_r_deleteprinterdata("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ if (!W_ERROR_IS_OK(r.status))
+ goto done;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
/** @} **/
diff --git a/source3/libsmb/cli_srvsvc.c b/source3/libsmb/cli_srvsvc.c
index 9d33149540..2dc12d726c 100644
--- a/source3/libsmb/cli_srvsvc.c
+++ b/source3/libsmb/cli_srvsvc.c
@@ -4,6 +4,7 @@
Copyright (C) Andrew Tridgell 1994-2000
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
Copyright (C) Tim Potter 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
@@ -22,15 +23,6 @@
#include "includes.h"
-/* Opens a SMB connection to the svrsvc pipe */
-
-struct cli_state *cli_svrsvc_initialise(struct cli_state *cli,
- char *system_name,
- struct ntuser_creds *creds)
-{
- return cli_pipe_initialise(cli, system_name, PIPE_SRVSVC, creds);
-}
-
NTSTATUS cli_srvsvc_net_srv_get_info(struct cli_state *cli,
TALLOC_CTX *mem_ctx,
uint32 switch_value, SRV_INFO_CTR *ctr)
@@ -77,3 +69,374 @@ NTSTATUS cli_srvsvc_net_srv_get_info(struct cli_state *cli,
return result;
}
+
+WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 info_level, SRV_SHARE_INFO_CTR *ctr,
+ int preferred_len, ENUM_HND *hnd)
+{
+ prs_struct qbuf, rbuf;
+ SRV_Q_NET_SHARE_ENUM q;
+ SRV_R_NET_SHARE_ENUM r;
+ WERROR result = W_ERROR(ERRgeneral);
+ int i;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ init_srv_q_net_share_enum(
+ &q, cli->srv_name_slash, info_level, preferred_len, hnd);
+
+ /* Marshall data and send request */
+
+ if (!srv_io_q_net_share_enum("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SRV_NET_SHARE_ENUM_ALL, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!srv_io_r_net_share_enum("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* Oh yuck yuck yuck - we have to copy all the info out of the
+ SRV_SHARE_INFO_CTR in the SRV_R_NET_SHARE_ENUM as when we do a
+ prs_mem_free() it will all be invalidated. The various share
+ info structures suck badly too. This really is gross. */
+
+ ZERO_STRUCTP(ctr);
+
+ ctr->info_level = info_level;
+ ctr->num_entries = r.ctr.num_entries;
+
+ switch(info_level) {
+ case 1:
+ ctr->share.info1 = (SRV_SHARE_INFO_1 *)talloc(
+ mem_ctx, sizeof(SRV_SHARE_INFO_1) * ctr->num_entries);
+
+ memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
+
+ for (i = 0; i < ctr->num_entries; i++) {
+ SRV_SHARE_INFO_1 *info1 = &ctr->share.info1[i];
+ char *s;
+
+ /* Copy pointer crap */
+
+ memcpy(&info1->info_1, &r.ctr.share.info1[i].info_1,
+ sizeof(SH_INFO_1));
+
+ /* Duplicate strings */
+
+ s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_netname);
+ if (s)
+ init_unistr2(&info1->info_1_str.uni_netname, s, strlen(s) + 1);
+
+ s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_remark);
+ if (s)
+ init_unistr2(&info1->info_1_str.uni_remark, s, strlen(s) + 1);
+
+ }
+
+ break;
+ case 2:
+ ctr->share.info2 = (SRV_SHARE_INFO_2 *)talloc(
+ mem_ctx, sizeof(SRV_SHARE_INFO_2) * ctr->num_entries);
+
+ memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
+
+ for (i = 0; i < ctr->num_entries; i++) {
+ SRV_SHARE_INFO_2 *info2 = &ctr->share.info2[i];
+ char *s;
+
+ /* Copy pointer crap */
+
+ memcpy(&info2->info_2, &r.ctr.share.info2[i].info_2,
+ sizeof(SH_INFO_2));
+
+ /* Duplicate strings */
+
+ s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_netname);
+ if (s)
+ init_unistr2(&info2->info_2_str.uni_netname, s, strlen(s) + 1);
+
+ s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_remark);
+ if (s)
+ init_unistr2(&info2->info_2_str.uni_remark, s, strlen(s) + 1);
+
+ s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_path);
+ if (s)
+ init_unistr2(&info2->info_2_str.uni_path, s, strlen(s) + 1);
+
+ s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_passwd);
+ if (s)
+ init_unistr2(&info2->info_2_str.uni_passwd, s, strlen(s) + 1);
+ }
+ break;
+ }
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+WERROR cli_srvsvc_net_share_del(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ const char *sharename)
+{
+ prs_struct qbuf, rbuf;
+ SRV_Q_NET_SHARE_DEL q;
+ SRV_R_NET_SHARE_DEL r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ init_srv_q_net_share_del(&q, cli->srv_name_slash, sharename);
+
+ /* Marshall data and send request */
+
+ if (!srv_io_q_net_share_del("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SRV_NET_SHARE_DEL, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!srv_io_r_net_share_del("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ char *netname, uint32 type, char *remark,
+ uint32 perms, uint32 max_uses, uint32 num_uses,
+ char *path, char *passwd)
+{
+ prs_struct qbuf, rbuf;
+ SRV_Q_NET_SHARE_ADD q;
+ SRV_R_NET_SHARE_ADD r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark,
+ perms, max_uses, num_uses, path, passwd);
+
+ /* Marshall data and send request */
+
+ if (!srv_io_q_net_share_add("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SRV_NET_SHARE_ADD, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!srv_io_r_net_share_add("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+WERROR cli_srvsvc_net_remote_tod(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ char *server, TIME_OF_DAY_INFO *tod)
+{
+ prs_struct qbuf, rbuf;
+ SRV_Q_NET_REMOTE_TOD q;
+ SRV_R_NET_REMOTE_TOD r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ init_srv_q_net_remote_tod(&q, cli->srv_name_slash);
+
+ /* Marshall data and send request */
+
+ if (!srv_io_q_net_remote_tod("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SRV_NET_REMOTE_TOD, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ r.tod = tod;
+
+ if (!srv_io_r_net_remote_tod("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 file_level, char *user_name,
+ SRV_FILE_INFO_CTR *ctr, int preferred_len,
+ ENUM_HND *hnd)
+{
+ prs_struct qbuf, rbuf;
+ SRV_Q_NET_FILE_ENUM q;
+ SRV_R_NET_FILE_ENUM r;
+ WERROR result = W_ERROR(ERRgeneral);
+ int i;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ init_srv_q_net_file_enum(&q, cli->srv_name_slash, NULL, user_name,
+ file_level, ctr, preferred_len, hnd);
+
+ /* Marshall data and send request */
+
+ if (!srv_io_q_net_file_enum("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SRV_NET_FILE_ENUM, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!srv_io_r_net_file_enum("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* copy the data over to the ctr */
+
+ ZERO_STRUCTP(ctr);
+
+ ctr->switch_value = file_level;
+
+ ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
+
+ switch(file_level) {
+ case 3:
+ ctr->file.info3 = (SRV_FILE_INFO_3 *)talloc(
+ mem_ctx, sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
+
+ memset(ctr->file.info3, 0,
+ sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
+
+ for (i = 0; i < r.ctr.num_entries; i++) {
+ SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i];
+ char *s;
+
+ /* Copy pointer crap */
+
+ memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3,
+ sizeof(FILE_INFO_3));
+
+ /* Duplicate strings */
+
+ s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name);
+ if (s)
+ init_unistr2(&info3->info_3_str.uni_path_name, s, strlen(s) + 1);
+
+ s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name);
+ if (s)
+ init_unistr2(&info3->info_3_str.uni_user_name, s, strlen(s) + 1);
+
+ }
+
+ break;
+ }
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
+WERROR cli_srvsvc_net_file_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 file_id)
+{
+ prs_struct qbuf, rbuf;
+ SRV_Q_NET_FILE_CLOSE q;
+ SRV_R_NET_FILE_CLOSE r;
+ WERROR result = W_ERROR(ERRgeneral);
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ init_srv_q_net_file_close(&q, cli->srv_name_slash, file_id);
+
+ /* Marshall data and send request */
+
+ if (!srv_io_q_net_file_close("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, SRV_NET_FILE_CLOSE, &qbuf, &rbuf))
+ goto done;
+
+ /* Unmarshall response */
+
+ if (!srv_io_r_net_file_close("", &r, &rbuf, 0))
+ goto done;
+
+ result = r.status;
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+ return result;
+}
diff --git a/source3/libsmb/cli_wkssvc.c b/source3/libsmb/cli_wkssvc.c
index 2a84e6b698..756ff61e5b 100644
--- a/source3/libsmb/cli_wkssvc.c
+++ b/source3/libsmb/cli_wkssvc.c
@@ -24,24 +24,6 @@
#include "includes.h"
/**
- * Opens a SMB connection to the wkssvc pipe
- *
- * @param cli client structure (not yet initialised)
- * @param system_name called rpc server name
- * @param creds user credentials
- *
- * @return client structure with opened pipe
- **/
-
-struct cli_state *cli_wkssvc_initialise(struct cli_state *cli,
- char *system_name,
- struct ntuser_creds *creds)
-{
- return cli_pipe_initialise(cli, system_name, PIPE_WKSSVC, creds);
-}
-
-
-/**
* WksQueryInfo rpc call (like query for server's capabilities)
*
* @param initialised client structure with \PIPE\wkssvc opened
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 4be63b8f2e..f0b02b97b0 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
client connect/disconnect routines
Copyright (C) Andrew Tridgell 1994-1998
+ Copyright (C) Andrew Barteltt 2001-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,28 +25,27 @@
static const struct {
- int prot;
- const char *name;
- }
-prots[] =
- {
- {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
- {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
- {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
- {PROTOCOL_LANMAN1,"LANMAN1.0"},
- {PROTOCOL_LANMAN2,"LM1.2X002"},
- {PROTOCOL_LANMAN2,"Samba"},
- {PROTOCOL_NT1,"NT LANMAN 1.0"},
- {PROTOCOL_NT1,"NT LM 0.12"},
- {-1,NULL}
- };
-
+ int prot;
+ const char *name;
+} prots[] = {
+ {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
+ {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
+ {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
+ {PROTOCOL_LANMAN1,"LANMAN1.0"},
+ {PROTOCOL_LANMAN2,"LM1.2X002"},
+ {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
+ {PROTOCOL_LANMAN2,"Samba"},
+ {PROTOCOL_NT1,"NT LANMAN 1.0"},
+ {PROTOCOL_NT1,"NT LM 0.12"},
+ {-1,NULL}
+};
/****************************************************************************
-do an old lanman2 style session setup
+ Do an old lanman2 style session setup.
****************************************************************************/
+
static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
- char *pass, int passlen)
+ char *pass, int passlen, const char *workgroup)
{
fstring pword;
char *p;
@@ -54,17 +54,19 @@ 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 & 1)) {
+ if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
passlen = 0;
}
- if (passlen > 0 && (cli->sec_mode & 2) && passlen != 24) {
+ if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
/* Encrypted mode needed, and non encrypted password supplied. */
passlen = 24;
- clistr_push(cli, pword, pass, -1, STR_TERMINATE);
- SMBencrypt((uchar *)pword,cli->secblob.data,(uchar *)pword);
- } else if ((cli->sec_mode & 2) && passlen == 24) {
+ SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
+ } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
/* Encrypted mode needed, and encrypted password supplied. */
memcpy(pword, pass, passlen);
} else if (passlen > 0) {
@@ -88,7 +90,10 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
p = smb_buf(cli->outbuf);
memcpy(p,pword,passlen);
p += passlen;
- p += clistr_push(cli, p, user, -1, STR_TERMINATE);
+ p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
+ p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
+ p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
+ p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
cli_send_smb(cli);
@@ -108,10 +113,10 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
return True;
}
-
/****************************************************************************
-work out suitable capabilities to offer the server
+ Work out suitable capabilities to offer the server.
****************************************************************************/
+
static uint32 cli_session_setup_capabilities(struct cli_state *cli)
{
uint32 capabilities = CAP_NT_SMBS;
@@ -131,10 +136,10 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli)
return capabilities;
}
-
/****************************************************************************
-do a NT1 guest session setup
+ Do a NT1 guest session setup.
****************************************************************************/
+
static BOOL cli_session_setup_guest(struct cli_state *cli)
{
char *p;
@@ -181,10 +186,10 @@ static BOOL cli_session_setup_guest(struct cli_state *cli)
return True;
}
-
/****************************************************************************
-do a NT1 plaintext session setup
+ Do a NT1 plaintext session setup.
****************************************************************************/
+
static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
char *pass, char *workgroup)
{
@@ -237,9 +242,15 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
}
-/****************************************************************************
-do a NT1 NTLM/LM encrypted session setup
-****************************************************************************/
+/**
+ do a NT1 NTLM/LM encrypted session setup
+ @param cli client state to create do session setup on
+ @param user username
+ @param pass *either* cleartext password (passlen !=24) or LM response.
+ @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
+ @param workgroup The user's domain.
+*/
+
static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
char *pass, int passlen,
char *ntpass, int ntpasslen,
@@ -248,6 +259,7 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
uint32 capabilities = cli_session_setup_capabilities(cli);
fstring pword, ntpword;
char *p;
+ BOOL tried_signing = False;
if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
return False;
@@ -257,12 +269,12 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
/* non encrypted password supplied. Ignore ntpass. */
passlen = 24;
ntpasslen = 24;
- clistr_push(cli, pword,
- pass?pass:"", sizeof(pword), STR_TERMINATE|STR_ASCII);
- clistr_push(cli, ntpword,
- pass?pass:"", sizeof(ntpword), STR_TERMINATE|STR_ASCII);
- SMBencrypt((uchar *)pword,cli->secblob.data,(uchar *)pword);
- SMBNTencrypt((uchar *)ntpword,cli->secblob.data,(uchar *)ntpword);
+ SMBencrypt((uchar *)pass,cli->secblob.data,(uchar *)pword);
+ SMBNTencrypt((uchar *)pass,cli->secblob.data,(uchar *)ntpword);
+ if (!cli->sign_info.use_smb_signing && cli->sign_info.negotiated_smb_signing) {
+ cli_calculate_mac_key(cli, (uchar *)pass, (uchar *)ntpword);
+ tried_signing = True;
+ }
} else {
memcpy(pword, pass, passlen);
memcpy(ntpword, ntpass, ntpasslen);
@@ -298,10 +310,15 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
show_msg(cli->inbuf);
+ if (tried_signing && (cli_is_error(cli) || SVAL(cli->inbuf,smb_vwv2) /* guest */)) {
+ /* We only use it if we have a successful non-guest connect */
+ cli->sign_info.use_smb_signing = False;
+ }
+
if (cli_is_error(cli)) {
return False;
}
-
+
/* use the returned vuid from now on */
cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -315,10 +332,10 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
return True;
}
-
/****************************************************************************
-send a extended security session setup blob, returning a reply blob
+ Send a extended security session setup blob, returning a reply blob.
****************************************************************************/
+
static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
{
uint32 capabilities = cli_session_setup_capabilities(cli);
@@ -382,8 +399,9 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
#ifdef HAVE_KRB5
/****************************************************************************
-do a spnego/kerberos encrypted session setup
+ Do a spnego/kerberos encrypted session setup.
****************************************************************************/
+
static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principal, char *workgroup)
{
DATA_BLOB blob2, negTokenTarg;
@@ -411,8 +429,9 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principal, c
#endif
/****************************************************************************
-do a spnego/NTLMSSP encrypted session setup
+ Do a spnego/NTLMSSP encrypted session setup.
****************************************************************************/
+
static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
char *pass, char *workgroup)
{
@@ -501,10 +520,10 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
return !cli_is_error(cli);
}
-
/****************************************************************************
-do a spnego encrypted session setup
+ Do a spnego encrypted session setup.
****************************************************************************/
+
static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user,
char *pass, char *workgroup)
{
@@ -514,6 +533,9 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user,
int i;
BOOL got_kerberos_mechanism = False;
+ /* spnego security cannot use SMB signing (for now). */
+ cli->sign_info.use_smb_signing = False;
+
DEBUG(2,("Doing spnego session setup (blob length=%d)\n", cli->secblob.length));
/* the server might not even do spnego */
@@ -558,12 +580,12 @@ ntlmssp:
return cli_session_setup_ntlmssp(cli, user, pass, workgroup);
}
-
/****************************************************************************
Send a session setup. The username and workgroup is in UNIX character
format and must be converted to DOS codepage format before sending. If the
password is in plaintext, the same should be done.
****************************************************************************/
+
BOOL cli_session_setup(struct cli_state *cli,
char *user,
char *pass, int passlen,
@@ -591,7 +613,7 @@ BOOL cli_session_setup(struct cli_state *cli,
/* if its an older server then we have to use the older request format */
if (cli->protocol < PROTOCOL_NT1) {
- return cli_session_setup_lanman2(cli, user, pass, passlen);
+ return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
}
/* if no user is supplied then we have to do an anonymous connection.
@@ -603,13 +625,13 @@ BOOL cli_session_setup(struct cli_state *cli,
/* if the server is share level then send a plaintext null
password at this point. The password is sent in the tree
connect */
- if ((cli->sec_mode & 1) == 0) {
+ if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
return cli_session_setup_plaintext(cli, user, "", workgroup);
}
- /* if the server doesn't support encryption then we have to use plaintext. The
- second password is ignored */
- if ((cli->sec_mode & 2) == 0) {
+ /* if the server doesn't support encryption then we have to use
+ plaintext. The second password is ignored */
+ if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
return cli_session_setup_plaintext(cli, user, pass, workgroup);
}
@@ -630,27 +652,28 @@ BOOL cli_session_setup(struct cli_state *cli,
BOOL cli_ulogoff(struct cli_state *cli)
{
- memset(cli->outbuf,'\0',smb_size);
- set_message(cli->outbuf,2,0,True);
- SCVAL(cli->outbuf,smb_com,SMBulogoffX);
- cli_setup_packet(cli);
+ memset(cli->outbuf,'\0',smb_size);
+ set_message(cli->outbuf,2,0,True);
+ SCVAL(cli->outbuf,smb_com,SMBulogoffX);
+ cli_setup_packet(cli);
SSVAL(cli->outbuf,smb_vwv0,0xFF);
SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
- cli_send_smb(cli);
- if (!cli_receive_smb(cli))
- return False;
+ cli_send_smb(cli);
+ if (!cli_receive_smb(cli))
+ return False;
- return !cli_is_error(cli);
+ return !cli_is_error(cli);
}
/****************************************************************************
-send a tconX
+ Send a tconX.
****************************************************************************/
+
BOOL cli_send_tconX(struct cli_state *cli,
const char *share, const char *dev, const char *pass, int passlen)
{
- fstring fullshare, pword, dos_pword;
+ fstring fullshare, pword;
char *p;
memset(cli->outbuf,'\0',smb_size);
memset(cli->inbuf,'\0',smb_size);
@@ -658,20 +681,19 @@ BOOL cli_send_tconX(struct cli_state *cli,
fstrcpy(cli->share, share);
/* in user level security don't send a password now */
- if (cli->sec_mode & 1) {
+ if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
passlen = 1;
pass = "";
}
- if ((cli->sec_mode & 2) && *pass && passlen != 24) {
+ if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
/*
* Non-encrypted passwords - convert to DOS codepage before encryption.
*/
passlen = 24;
- clistr_push(cli, dos_pword, pass, -1, STR_TERMINATE);
- SMBencrypt((uchar *)dos_pword,cli->secblob.data,(uchar *)pword);
+ SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
} else {
- if((cli->sec_mode & 3) == 0) {
+ if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
/*
* Non-encrypted passwords - convert to DOS codepage before using.
*/
@@ -728,10 +750,10 @@ BOOL cli_send_tconX(struct cli_state *cli,
return True;
}
-
/****************************************************************************
-send a tree disconnect
+ Send a tree disconnect.
****************************************************************************/
+
BOOL cli_tdis(struct cli_state *cli)
{
memset(cli->outbuf,'\0',smb_size);
@@ -747,15 +769,19 @@ BOOL cli_tdis(struct cli_state *cli)
return !cli_is_error(cli);
}
-
/****************************************************************************
-send a negprot command
+ Send a negprot command.
****************************************************************************/
+
void cli_negprot_send(struct cli_state *cli)
{
char *p;
int numprots;
+ if (cli->protocol < PROTOCOL_NT1) {
+ cli->use_spnego = False;
+ }
+
memset(cli->outbuf,'\0',smb_size);
/* setup the protocol strings */
@@ -778,16 +804,25 @@ void cli_negprot_send(struct cli_state *cli)
cli_send_smb(cli);
}
-
/****************************************************************************
-send a negprot command
+ Send a negprot command.
****************************************************************************/
+
BOOL cli_negprot(struct cli_state *cli)
{
char *p;
int numprots;
int plength;
+ if (cli->sign_info.use_smb_signing) {
+ DEBUG(0, ("Cannot send negprot again, particularly after setting up SMB Signing\n"));
+ return False;
+ }
+
+ if (cli->protocol < PROTOCOL_NT1) {
+ cli->use_spnego = False;
+ }
+
memset(cli->outbuf,'\0',smb_size);
/* setup the protocol strings */
@@ -822,7 +857,7 @@ BOOL cli_negprot(struct cli_state *cli)
return(False);
}
- cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
+ cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
if (cli->protocol >= PROTOCOL_NT1) {
/* NT protocol */
@@ -847,7 +882,16 @@ BOOL cli_negprot(struct cli_state *cli)
smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
}
+
+ /* A way to attempt to force SMB signing */
+ if (getenv("CLI_FORCE_SMB_SIGNING"))
+ cli->sign_info.negotiated_smb_signing = True;
+
+ if (cli->sign_info.negotiated_smb_signing && !(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
+ cli->sign_info.negotiated_smb_signing = False;
+
} else if (cli->protocol >= PROTOCOL_LANMAN1) {
+ cli->use_spnego = False;
cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
@@ -860,6 +904,7 @@ BOOL cli_negprot(struct cli_state *cli)
cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
} else {
/* the old core protocol */
+ cli->use_spnego = False;
cli->sec_mode = 0;
cli->serverzone = TimeDiff(time(NULL));
}
@@ -874,10 +919,10 @@ BOOL cli_negprot(struct cli_state *cli)
return True;
}
-
/****************************************************************************
- send a session request. see rfc1002.txt 4.3 and 4.3.2
+ Send a session request. See rfc1002.txt 4.3 and 4.3.2.
****************************************************************************/
+
BOOL cli_session_request(struct cli_state *cli,
struct nmb_name *calling, struct nmb_name *called)
{
@@ -888,6 +933,11 @@ BOOL cli_session_request(struct cli_state *cli,
/* 445 doesn't have session request */
if (cli->port == 445) return True;
+ if (cli->sign_info.use_smb_signing) {
+ DEBUG(0, ("Cannot send session resquest again, particularly after setting up SMB Signing\n"));
+ return False;
+ }
+
/* send a session request (RFC 1002) */
memcpy(&(cli->calling), calling, sizeof(*calling));
memcpy(&(cli->called ), called , sizeof(*called ));
@@ -902,7 +952,7 @@ BOOL cli_session_request(struct cli_state *cli,
name_mangle(cli->calling.name, p, cli->calling.name_type);
len += name_len(p);
- /* setup the packet length
+ /* setup the packet length
* Remove four bytes from the length count, since the length
* field in the NBT Session Service header counts the number
* of bytes which follow. The cli_send_smb() function knows
@@ -913,10 +963,6 @@ BOOL cli_session_request(struct cli_state *cli,
_smb_setlen(cli->outbuf,len);
SCVAL(cli->outbuf,0,0x81);
-#ifdef WITH_SSL
-retry:
-#endif /* WITH_SSL */
-
cli_send_smb(cli);
DEBUG(5,("Sent session request\n"));
@@ -962,15 +1008,6 @@ retry:
}
} /* C. Hoch 9/14/95 End */
-#ifdef WITH_SSL
- if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
- if (!sslutil_fd_is_ssl(cli->fd)){
- if (sslutil_connect(cli->fd) == 0)
- goto retry;
- }
- }
-#endif /* WITH_SSL */
-
if (CVAL(cli->inbuf,0) != 0x82) {
/* This is the wrong place to put the error... JRA. */
cli->rap_error = CVAL(cli->inbuf,4);
@@ -980,8 +1017,9 @@ retry:
}
/****************************************************************************
-open the client sockets
+ Open the client sockets.
****************************************************************************/
+
BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
{
extern pstring user_socket_options;
@@ -1034,155 +1072,11 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
}
/****************************************************************************
-establishes a connection right up to doing tconX, password in cache.
+ Initialise client credentials for authenticated pipe access.
****************************************************************************/
-BOOL cli_establish_connection(struct cli_state *cli,
- char *dest_host, struct in_addr *dest_ip,
- struct nmb_name *calling, struct nmb_name *called,
- char *service, char *service_type,
- BOOL do_shutdown, BOOL do_tcon)
-{
- DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
- nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
- cli->user_name, cli->domain));
-
- /* establish connection */
-
- if ((!cli->initialised))
- {
- return False;
- }
-
- /* cli_establish_connection() can't handle spnego yet. Once we get rid of
- pwd_cache and other horrors we can get rid of this */
- cli->use_spnego = False;
-
- if (cli->fd == -1)
- {
- if (!cli_connect(cli, dest_host, dest_ip))
- {
- DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
- nmb_namestr(called), inet_ntoa(*dest_ip)));
- return False;
- }
- }
-
- if (!cli_session_request(cli, calling, called))
- {
- DEBUG(1,("failed session request\n"));
- if (do_shutdown)
- cli_shutdown(cli);
- return False;
- }
-
- if (!cli_negprot(cli))
- {
- DEBUG(1,("failed negprot\n"));
- if (do_shutdown)
- cli_shutdown(cli);
- return False;
- }
-
- if (cli->pwd.cleartext || cli->pwd.null_pwd)
- {
- fstring passwd;
- int pass_len;
-
- if (cli->pwd.null_pwd)
- {
- /* attempt null session */
- passwd[0] = 0;
- pass_len = 1;
- }
- else
- {
- /* attempt clear-text session */
- pwd_get_cleartext(&(cli->pwd), passwd);
- pass_len = strlen(passwd);
- }
-
- /* attempt clear-text session */
- if (!cli_session_setup(cli, cli->user_name,
- passwd, pass_len,
- NULL, 0,
- cli->domain))
- {
- DEBUG(1,("failed session setup\n"));
- if (do_shutdown)
- {
- cli_shutdown(cli);
- }
- return False;
- }
- if (do_tcon)
- {
- if (!cli_send_tconX(cli, service, service_type,
- (char*)passwd, strlen(passwd)))
- {
- DEBUG(1,("failed tcon_X\n"));
- if (do_shutdown)
- {
- cli_shutdown(cli);
- }
- return False;
- }
- }
- }
- else
- {
- /* attempt encrypted session */
- unsigned char nt_sess_pwd[24];
- unsigned char lm_sess_pwd[24];
-
- /* creates (storing a copy of) and then obtains a 24 byte password OWF */
- pwd_make_lm_nt_owf(&(cli->pwd), cli->secblob.data);
- pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
-
- /* attempt encrypted session */
- if (!cli_session_setup(cli, cli->user_name,
- (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
- (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
- cli->domain))
- {
- DEBUG(1,("failed session setup\n"));
- if (do_shutdown)
- cli_shutdown(cli);
- return False;
- }
-
- DEBUG(1,("session setup ok\n"));
-
- if (*cli->server_domain || *cli->server_os || *cli->server_type)
- {
- DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
- cli->server_domain,
- cli->server_os,
- cli->server_type));
- }
-
- if (do_tcon)
- {
- if (!cli_send_tconX(cli, service, service_type,
- (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
- {
- DEBUG(1,("failed tcon_X\n"));
- if (do_shutdown)
- cli_shutdown(cli);
- return False;
- }
- }
- }
-
- if (do_shutdown)
- cli_shutdown(cli);
-
- return True;
-}
-
-/* Initialise client credentials for authenticated pipe access */
static void init_creds(struct ntuser_creds *creds, char* username,
- char* domain, char* password, int pass_len)
+ char* domain, char* password)
{
ZERO_STRUCTP(creds);
@@ -1196,15 +1090,26 @@ static void init_creds(struct ntuser_creds *creds, char* username,
}
}
-/****************************************************************************
-establishes a connection right up to doing tconX, password specified.
-****************************************************************************/
+/**
+ establishes a connection right up to doing tconX, password specified.
+ @param output_cli A fully initialised cli structure, non-null only on success
+ @param dest_host The netbios name of the remote host
+ @param dest_ip (optional) The the destination IP, NULL for name based lookup
+ @param port (optional) The destination port (0 for default)
+ @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
+ @param service_type The 'type' of serivice.
+ @param user Username, unix string
+ @param domain User's domain
+ @param password User's password, unencrypted unix string.
+*/
+
NTSTATUS cli_full_connection(struct cli_state **output_cli,
- const char *my_name, const char *dest_host,
+ const char *my_name,
+ const char *dest_host,
struct in_addr *dest_ip, int port,
char *service, char *service_type,
char *user, char *domain,
- char *password, int pass_len)
+ char *password, int flags)
{
struct ntuser_creds creds;
NTSTATUS nt_status;
@@ -1212,32 +1117,40 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
struct nmb_name called;
struct cli_state *cli;
struct in_addr ip;
-
- if (!output_cli)
+ extern pstring global_myname;
+
+ if (!output_cli) {
DEBUG(0, ("output_cli is NULL!?!"));
+ SMB_ASSERT("output_cli for cli_full_connection was NULL.\n");
+ }
- *output_cli = NULL;
+ if (!my_name)
+ my_name = global_myname;
- make_nmb_name(&calling, my_name, 0x0);
- make_nmb_name(&called , dest_host, 0x20);
-
-again:
-
if (!(cli = cli_initialise(NULL)))
return NT_STATUS_NO_MEMORY;
+ make_nmb_name(&calling, my_name, 0x0);
+ make_nmb_name(&called , dest_host, 0x20);
+
if (cli_set_port(cli, port) != port) {
cli_shutdown(cli);
return NT_STATUS_UNSUCCESSFUL;
}
- ip = *dest_ip;
-
+ if (dest_ip) {
+ ip = *dest_ip;
+ } else {
+ ZERO_STRUCT(ip);
+ }
+
+again:
+
DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service));
if (!cli_connect(cli, dest_host, &ip)) {
- DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
- nmb_namestr(&called), inet_ntoa(*dest_ip)));
+ DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n",
+ nmb_namestr(&called), inet_ntoa(ip)));
cli_shutdown(cli);
return NT_STATUS_UNSUCCESSFUL;
}
@@ -1258,6 +1171,12 @@ again:
return NT_STATUS_UNSUCCESSFUL;
}
+ if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) {
+ cli->use_spnego = False;
+ } else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
+ cli->use_kerberos = True;
+ }
+
if (!cli_negprot(cli)) {
DEBUG(1,("failed negprot\n"));
nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -1265,29 +1184,36 @@ again:
return nt_status;
}
- if (!cli_session_setup(cli, user, password, pass_len, password, pass_len,
+ if (!cli_session_setup(cli, user, password, strlen(password)+1,
+ password, strlen(password)+1,
domain)) {
- DEBUG(1,("failed session setup\n"));
- nt_status = cli_nt_error(cli);
- cli_shutdown(cli);
- if (NT_STATUS_IS_OK(nt_status))
- nt_status = NT_STATUS_UNSUCCESSFUL;
- return nt_status;
+ 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)));
+ cli_shutdown(cli);
+ if (NT_STATUS_IS_OK(nt_status))
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ return nt_status;
+ }
}
if (service) {
if (!cli_send_tconX(cli, service, service_type,
- (char*)password, pass_len)) {
- DEBUG(1,("failed tcon_X\n"));
+ (char*)password, strlen(password)+1)) {
+ DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
nt_status = cli_nt_error(cli);
cli_shutdown(cli);
- if (NT_STATUS_IS_OK(nt_status))
+ if (NT_STATUS_IS_OK(nt_status)) {
nt_status = NT_STATUS_UNSUCCESSFUL;
+ }
return nt_status;
}
}
- init_creds(&creds, user, domain, password, pass_len);
+ init_creds(&creds, user, domain, password);
cli_init_creds(cli, &creds);
*output_cli = cli;
@@ -1301,55 +1227,53 @@ again:
BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char *desthost,
struct in_addr *pdest_ip)
{
- struct nmb_name calling, called;
+ struct nmb_name calling, called;
- make_nmb_name(&calling, srchost, 0x0);
+ make_nmb_name(&calling, srchost, 0x0);
- /*
- * If the called name is an IP address
- * then use *SMBSERVER immediately.
- */
+ /*
+ * If the called name is an IP address
+ * then use *SMBSERVER immediately.
+ */
- if(is_ipaddress(desthost))
- make_nmb_name(&called, "*SMBSERVER", 0x20);
- else
- make_nmb_name(&called, desthost, 0x20);
+ if(is_ipaddress(desthost))
+ make_nmb_name(&called, "*SMBSERVER", 0x20);
+ else
+ make_nmb_name(&called, desthost, 0x20);
- if (!cli_session_request(cli, &calling, &called)) {
- struct nmb_name smbservername;
+ if (!cli_session_request(cli, &calling, &called)) {
+ struct nmb_name smbservername;
- make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
+ make_nmb_name(&smbservername , "*SMBSERVER", 0x20);
- /*
- * If the name wasn't *SMBSERVER then
- * try with *SMBSERVER if the first name fails.
- */
+ /*
+ * If the name wasn't *SMBSERVER then
+ * try with *SMBSERVER if the first name fails.
+ */
- if (nmb_name_equal(&called, &smbservername)) {
+ if (nmb_name_equal(&called, &smbservername)) {
- /*
- * The name used was *SMBSERVER, don't bother with another name.
- */
+ /*
+ * The name used was *SMBSERVER, don't bother with another name.
+ */
- DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
+ DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
with error %s.\n", desthost, cli_errstr(cli) ));
- cli_shutdown(cli);
- return False;
- }
+ cli_shutdown(cli);
+ return False;
+ }
- cli_shutdown(cli);
+ cli_shutdown(cli);
- if (!cli_initialise(cli) ||
- !cli_connect(cli, desthost, pdest_ip) ||
- !cli_session_request(cli, &calling, &smbservername)) {
- DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
+ if (!cli_initialise(cli) ||
+ !cli_connect(cli, desthost, pdest_ip) ||
+ !cli_session_request(cli, &calling, &smbservername)) {
+ DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
- cli_shutdown(cli);
- return False;
- }
- }
+ cli_shutdown(cli);
+ return False;
+ }
+ }
- return True;
+ return True;
}
-
-
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index ba7a327344..c9500ead5d 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -32,6 +32,41 @@ int cli_set_port(struct cli_state *cli, int port)
}
/****************************************************************************
+ read an smb from a fd ignoring all keepalive packets. Note that the buffer
+ *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
+ The timeout is in milliseconds
+
+ This is exactly the same as receive_smb except that it never returns
+ a session keepalive packet (just as receive_smb used to do).
+ receive_smb was changed to return keepalives as the oplock processing means this call
+ should never go into a blocking read.
+****************************************************************************/
+
+static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
+{
+ BOOL ret;
+
+ for(;;)
+ {
+ ret = receive_smb(fd, buffer, timeout);
+
+ if (!ret)
+ {
+ DEBUG(10,("client_receive_smb failed\n"));
+ show_msg(buffer);
+ return ret;
+ }
+
+ /* Ignore session keepalive packets. */
+ if(CVAL(buffer,0) != SMBkeepalive)
+ break;
+ }
+ show_msg(buffer);
+ return ret;
+}
+
+
+/****************************************************************************
recv an smb
****************************************************************************/
BOOL cli_receive_smb(struct cli_state *cli)
@@ -72,7 +107,7 @@ BOOL cli_receive_smb(struct cli_state *cli)
}
/****************************************************************************
- send an smb to a fd.
+ Send an smb to a fd.
****************************************************************************/
BOOL cli_send_smb(struct cli_state *cli)
@@ -82,31 +117,33 @@ BOOL cli_send_smb(struct cli_state *cli)
ssize_t ret;
/* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
- if (cli->fd == -1) return False;
+ if (cli->fd == -1)
+ return False;
+
+ cli_caclulate_sign_mac(cli);
len = smb_len(cli->outbuf) + 4;
while (nwritten < len) {
ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
if (ret <= 0) {
- close(cli->fd);
- cli->fd = -1;
- DEBUG(0,("Error writing %d bytes to client. %d\n",
- (int)len,(int)ret));
+ close(cli->fd);
+ cli->fd = -1;
+ DEBUG(0,("Error writing %d bytes to client. %d\n", (int)len,(int)ret));
return False;
}
nwritten += ret;
}
-
return True;
}
/****************************************************************************
-setup basics in a outgoing packet
+ Setup basics in a outgoing packet.
****************************************************************************/
+
void cli_setup_packet(struct cli_state *cli)
{
- cli->rap_error = 0;
+ cli->rap_error = 0;
SSVAL(cli->outbuf,smb_pid,cli->pid);
SSVAL(cli->outbuf,smb_uid,cli->vuid);
SSVAL(cli->outbuf,smb_mid,cli->mid);
@@ -123,6 +160,8 @@ void cli_setup_packet(struct cli_state *cli)
if (cli->use_spnego) {
flags2 |= FLAGS2_EXTENDED_SECURITY;
}
+ if (cli->sign_info.use_smb_signing)
+ flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
SSVAL(cli->outbuf,smb_flg2, flags2);
}
}
@@ -247,10 +286,6 @@ void cli_shutdown(struct cli_state *cli)
if (cli->mem_ctx)
talloc_destroy(cli->mem_ctx);
-#ifdef WITH_SSL
- if (cli->fd != -1)
- sslutil_disconnect(cli->fd);
-#endif /* WITH_SSL */
if (cli->fd != -1)
close(cli->fd);
allocated = cli->allocated;
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index 05843ac5de..a47c956a55 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -76,7 +76,7 @@ static BOOL cli_link_internal(struct cli_state *cli, const char *fname_src, cons
uint32 unix_perms_to_wire(mode_t perms)
{
- uint ret = 0;
+ unsigned int ret = 0;
ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0);
ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0);
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index 8b28e05a47..17a759f9e3 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -54,10 +54,14 @@ static int interpret_long_filename(struct cli_state *cli,
len = CVAL(p, 26);
p += 27;
p += clistr_align_in(cli, p, 0);
+ /* the len+2 below looks strange but it is
+ important to cope with the differences
+ between win2000 and win9x for this call
+ (tridge) */
p += clistr_pull(cli, finfo->name, p,
- sizeof(finfo->name),
- len,
- STR_TERMINATE);
+ sizeof(finfo->name),
+ len+2,
+ STR_TERMINATE);
return PTR_DIFF(p, base);
case 2: /* this is what OS/2 uses mostly */
diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c
index a2b6c8bb8b..2064e14954 100644
--- a/source3/libsmb/clirap.c
+++ b/source3/libsmb/clirap.c
@@ -117,7 +117,8 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
if (cli->rap_error == 0) {
DEBUG(4,("NetWkstaUserLogon success\n"));
cli->privileges = SVAL(p, 24);
- fstrcpy(cli->eff_name,p+2);
+ /* The cli->eff_name field used to be set here
+ but it wasn't used anywhere else. */
} else {
DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
}
@@ -283,8 +284,6 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char
char param[16+sizeof(fstring)];
char data[532];
char *p = param;
- fstring upper_case_old_pw;
- fstring upper_case_new_pw;
unsigned char old_pw_hash[16];
unsigned char new_pw_hash[16];
int data_len;
@@ -316,9 +315,7 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char
* Get the Lanman hash of the old password, we
* use this as the key to make_oem_passwd_hash().
*/
- memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
- clistr_push(cli, upper_case_old_pw, old_password, -1,STR_TERMINATE|STR_UPPER|STR_ASCII);
- E_P16((uchar *)upper_case_old_pw, old_pw_hash);
+ E_deshash(old_password, old_pw_hash);
clistr_push(cli, dos_new_password, new_password, -1, STR_TERMINATE|STR_ASCII);
@@ -328,10 +325,7 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char
/*
* Now place the old password hash in the data.
*/
- memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
- clistr_push(cli, upper_case_new_pw, new_password, -1, STR_TERMINATE|STR_UPPER|STR_ASCII);
-
- E_P16((uchar *)upper_case_new_pw, new_pw_hash);
+ E_deshash(new_password, new_pw_hash);
E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
diff --git a/source3/libsmb/clirap2.c b/source3/libsmb/clirap2.c
index 00cd4b15f3..9c3ec212d5 100644
--- a/source3/libsmb/clirap2.c
+++ b/source3/libsmb/clirap2.c
@@ -1493,7 +1493,7 @@ int cli_NetPrintQEnum(struct cli_state *cli,
for (j=0;j<jobcount;j++) {
uint16 jid, pos, fsstatus;
pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
- uint submitted, jsize;
+ unsigned int submitted, jsize;
GETWORD(p, jid);
GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
@@ -1594,7 +1594,7 @@ int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
uint16 jid, pos, fsstatus;
pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
- uint submitted, jsize;
+ unsigned int submitted, jsize;
GETWORD(p, jid);
GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
@@ -1740,7 +1740,7 @@ int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16,
for (i=0,p=rdata;i<count;i++) {
pstring wsname, username, clitype_name;
uint16 num_conns, num_opens, num_users;
- uint sess_time, idle_time, user_flags;
+ unsigned int sess_time, idle_time, user_flags;
GETSTRINGP(p, wsname, rdata, converter);
GETSTRINGP(p, username, rdata, converter);
@@ -1813,7 +1813,7 @@ int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (
int rsize, converter;
pstring wsname, username, clitype_name;
uint16 num_conns, num_opens, num_users;
- uint sess_time, idle_time, user_flags;
+ unsigned int sess_time, idle_time, user_flags;
p = rparam + WORDSIZE;
GETWORD(p, converter);
@@ -1935,7 +1935,7 @@ int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, void (*f
for (i=0,p=rdata;i<count;i++) {
pstring netname, username;
uint16 conn_id, conn_type, num_opens, num_users;
- uint conn_time;
+ unsigned int conn_time;
GETWORD(p,conn_id);
GETWORD(p,conn_type);
diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c
index 0a9569fc69..756a6cce2f 100644
--- a/source3/libsmb/clireadwrite.c
+++ b/source3/libsmb/clireadwrite.c
@@ -49,31 +49,6 @@ static BOOL cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
}
/****************************************************************************
-Issue a single SMBreadraw and don't wait for a reply.
-****************************************************************************/
-
-static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset,
- size_t size, int i)
-{
- memset(cli->outbuf,'\0',smb_size);
- memset(cli->inbuf,'\0',smb_size);
-
- set_message(cli->outbuf,10,0,True);
-
- SCVAL(cli->outbuf,smb_com,SMBreadbraw);
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- SSVAL(cli->outbuf,smb_vwv0,fnum);
- SIVAL(cli->outbuf,smb_vwv1,offset);
- SSVAL(cli->outbuf,smb_vwv2,size);
- SSVAL(cli->outbuf,smb_vwv3,size);
- SSVAL(cli->outbuf,smb_mid,cli->mid + i);
-
- return cli_send_smb(cli);
-}
-
-/****************************************************************************
Read size bytes at offset offset using SMBreadX.
****************************************************************************/
@@ -152,6 +127,43 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
return total;
}
+#if 0 /* relies on client_recieve_smb(), now a static in libsmb/clientgen.c */
+
+/* This call is INCOMPATIBLE with SMB signing. If you remove the #if 0
+ you must fix ensure you don't attempt to sign the packets - data
+ *will* be currupted */
+
+/****************************************************************************
+Issue a single SMBreadraw and don't wait for a reply.
+****************************************************************************/
+
+static BOOL cli_issue_readraw(struct cli_state *cli, int fnum, off_t offset,
+ size_t size, int i)
+{
+
+ if (!cli->sign_info.use_smb_signing) {
+ DEBUG(0, ("Cannot use readraw and SMB Signing\n"));
+ return False;
+ }
+
+ memset(cli->outbuf,'\0',smb_size);
+ memset(cli->inbuf,'\0',smb_size);
+
+ set_message(cli->outbuf,10,0,True);
+
+ SCVAL(cli->outbuf,smb_com,SMBreadbraw);
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ SSVAL(cli->outbuf,smb_vwv0,fnum);
+ SIVAL(cli->outbuf,smb_vwv1,offset);
+ SSVAL(cli->outbuf,smb_vwv2,size);
+ SSVAL(cli->outbuf,smb_vwv3,size);
+ SSVAL(cli->outbuf,smb_mid,cli->mid + i);
+
+ return cli_send_smb(cli);
+}
+
/****************************************************************************
Tester for the readraw call.
****************************************************************************/
@@ -213,7 +225,7 @@ ssize_t cli_readraw(struct cli_state *cli, int fnum, char *buf, off_t offset, si
return total;
}
-
+#endif
/****************************************************************************
issue a single SMBwrite and don't wait for a reply
****************************************************************************/
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index a4fcfa5d9a..469b946088 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -549,7 +549,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
format specifiers are:
- U = unicode string (input is unix string)
+ U = unicode string (output is unix string)
B = data blob
b = data blob in header
d = word (4 bytes)
@@ -620,3 +620,44 @@ BOOL msrpc_parse(DATA_BLOB *blob,
return True;
}
+
+/**
+ * Print out the NTLMSSP flags for debugging
+ */
+
+void debug_ntlmssp_flags(uint32 neg_flags)
+{
+ if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_UNICODE\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_OEM)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_OEM\n"));
+ if (neg_flags & NTLMSSP_REQUEST_TARGET)
+ DEBUG(4, (" NTLMSSP_REQUEST_TARGET\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_SIGN\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_SIGN)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_SEAL\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_NETWARE\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_NTLM)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_NTLM\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_NTLM2\n"));
+ if (neg_flags & NTLMSSP_CHAL_TARGET_INFO)
+ DEBUG(4, (" NTLMSSP_CHAL_TARGET_INFO\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_128)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_128\n"));
+ if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
+ DEBUG(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
+}
+
diff --git a/source3/libsmb/errormap.c b/source3/libsmb/errormap.c
index c30db3ad95..a35108c3de 100644
--- a/source3/libsmb/errormap.c
+++ b/source3/libsmb/errormap.c
@@ -2,6 +2,7 @@
* Unix SMB/CIFS implementation.
* error mapping functions
* Copyright (C) Andrew Tridgell 2001
+ * Copyright (C) Andrew Bartlett 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
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index 237701b968..0ffc1c1378 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -1,9 +1,10 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
SMB client library implementation
Copyright (C) Andrew Tridgell 1998
- Copyright (C) Richard Sharpe 2000
+ Copyright (C) Richard Sharpe 2000, 2002
Copyright (C) John Terpstra 2000
+ Copyright (C) Tom Jansen (Ninja ISD) 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
@@ -21,56 +22,36 @@
*/
#include "includes.h"
+
#include "libsmbclient.h"
-/* Structure for servers ... Held here so we don't need an include ...
- * May be better to put in an include file
+/*
+ * Functions exported by libsmb_cache.c that we need here
*/
+int smbc_default_cache_functions(SMBCCTX *context);
-struct smbc_server {
- struct smbc_server *next, *prev;
- struct cli_state cli;
- dev_t dev;
- char *server_name;
- char *share_name;
- char *workgroup;
- char *username;
- BOOL no_pathinfo2;
-};
-
-/* Keep directory entries in a list */
-struct smbc_dir_list {
- struct smbc_dir_list *next;
- struct smbc_dirent *dirent;
-};
-
-struct smbc_file {
- int cli_fd;
- int smbc_fd;
- char *fname;
- off_t offset;
- struct smbc_server *srv;
- BOOL file;
- struct smbc_dir_list *dir_list, *dir_end, *dir_next;
- int dir_type, dir_error;
-};
-
-int smbc_fstatdir(int fd, struct stat *st); /* Forward decl */
-BOOL smbc_getatr(struct smbc_server *srv, char *path,
- uint16 *mode, size_t *size,
- time_t *c_time, time_t *a_time, time_t *m_time,
- SMB_INO_T *ino);
+/*
+ * check if an element is part of the list.
+ * FIXME: Does not belong here !
+ * Can anyone put this in a macro in dlinklist.h ?
+ * -- Tom
+ */
+static int DLIST_CONTAINS(SMBCFILE * list, SMBCFILE *p) {
+ if (!p || !list) return False;
+ do {
+ if (p == list) return True;
+ list = list->next;
+ } while (list);
+ return False;
+}
extern BOOL in_client;
extern pstring global_myname;
+
+/*
+ * Is the logging working / configfile read ?
+ */
static int smbc_initialized = 0;
-static smbc_get_auth_data_fn smbc_auth_fn = NULL;
-/*static int smbc_debug;*/
-static int smbc_start_fd;
-static struct smbc_file **smbc_file_table;
-static struct smbc_server *smbc_srvs;
-static pstring my_netbios_name;
-static pstring smbc_user;
/*
* Function to parse a path and turn it into components
@@ -78,14 +59,14 @@ static pstring smbc_user;
* We accept smb://[[[domain;]user[:password@]]server[/share[/path[/file]]]]
*
* smb:// means show all the workgroups
- * smb://name/ means, if name<1D> exists, list servers in workgroup,
+ * smb://name/ means, if name<1D> or name<1B> exists, list servers in workgroup,
* else, if name<20> exists, list all shares for server ...
*/
static const char *smbc_prefix = "smb:";
static int
-smbc_parse_path(const char *fname, char *server, char *share, char *path,
+smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share, char *path,
char *user, char *password) /* FIXME, lengths of strings */
{
static pstring s;
@@ -121,7 +102,8 @@ smbc_parse_path(const char *fname, char *server, char *share, char *path,
if (*p == '/') {
- strncpy(server, (char *)lp_workgroup(), 16); /* FIXME: Danger here */
+ strncpy(server, context->workgroup,
+ (strlen(context->workgroup) < 16)?strlen(context->workgroup):16);
return 0;
}
@@ -147,7 +129,7 @@ smbc_parse_path(const char *fname, char *server, char *share, char *path,
if (strchr_m(u, ';')) {
next_token(&u, domain, ";", sizeof(fstring));
-
+
}
if (strchr_m(u, ':')) {
@@ -172,9 +154,9 @@ smbc_parse_path(const char *fname, char *server, char *share, char *path,
}
if (!next_token(&p, server, "/", sizeof(fstring))) {
-
+
return -1;
-
+
}
if (*p == (char)0) return 0; /* That's it ... */
@@ -196,7 +178,7 @@ smbc_parse_path(const char *fname, char *server, char *share, char *path,
* Convert an SMB error into a UNIX error ...
*/
-int smbc_errno(struct cli_state *c)
+static int smbc_errno(SMBCCTX *context, struct cli_state *c)
{
int ret;
@@ -216,12 +198,65 @@ int smbc_errno(struct cli_state *c)
ret = cli_errno_from_nt(status);
DEBUG(3,("smbc errno %s -> %d\n",
- nt_errstr(status), ret));
+ get_nt_error_msg(status), ret));
}
return ret;
}
+/*
+ * Check a server_fd.
+ * returns 0 if the server is in shape. Returns 1 on error
+ *
+ * Also useable outside libsmbclient to enable external cache
+ * to do some checks too.
+ */
+int smbc_check_server(SMBCCTX * context, SMBCSRV * server)
+{
+ if ( cli_send_keepalive(&server->cli) == False )
+ return 1;
+
+ /* connection is ok */
+ return 0;
+}
+
+/*
+ * Remove a server from the list server_table if it's unused.
+ * On success, 0 is returned. 1 is returned if the server could not be removed.
+ *
+ * Also useable outside libsmbclient
+ */
+int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv)
+{
+ SMBCFILE * file;
+
+ /* are we being fooled ? */
+ if (!context || !context->_initialized || !srv) return 1;
+
+
+ /* Check all open files/directories for a relation with this server */
+ for (file = context->_files; file; file=file->next) {
+ if (file->srv == srv) {
+ /* Still used */
+ DEBUG(3, ("smbc_remove_usused_server: %p still used by %p.\n",
+ srv, file));
+ return 1;
+ }
+ }
+
+ DLIST_REMOVE(context->_servers, srv);
+
+ cli_shutdown(&srv->cli);
+
+ DEBUG(3, ("smbc_remove_usused_server: %p removed.\n", srv));
+
+ context->callbacks.remove_cached_srv_fn(context, srv);
+
+ SAFE_FREE(srv);
+
+ return 0;
+}
+
/*
* Connect to a server, possibly on an existing connection
*
@@ -233,58 +268,70 @@ int smbc_errno(struct cli_state *c)
* info we need, unless the username and password were passed in.
*/
-struct smbc_server *smbc_server(char *server, char *share,
- char *workgroup, char *username,
- char *password)
+SMBCSRV *smbc_server(SMBCCTX *context,
+ char *server, char *share,
+ char *workgroup, char *username,
+ char *password)
{
- struct smbc_server *srv=NULL;
+ SMBCSRV *srv=NULL;
+ int auth_called = 0;
struct cli_state c;
struct nmb_name called, calling;
char *p, *server_n = server;
fstring group;
pstring ipenv;
struct in_addr ip;
+ int tried_reverse = 0;
- zero_ip(&ip);
+ zero_ip(&ip);
ZERO_STRUCT(c);
- /* try to use an existing connection */
- for (srv=smbc_srvs;srv;srv=srv->next) {
- if (strcmp(server,srv->server_name)==0 &&
- strcmp(share,srv->share_name)==0 &&
- strcmp(workgroup,srv->workgroup)==0 &&
- strcmp(username, srv->username) == 0)
- return srv;
- }
-
if (server[0] == 0) {
errno = EPERM;
return NULL;
}
- /*
- * Pick up the auth info here, once we know we need to connect
- * But only if we do not have a username and password ...
- */
+ check_server_cache:
- if (!username[0] || !password[0])
- smbc_auth_fn(server, share, workgroup, sizeof(fstring),
- username, sizeof(fstring), password, sizeof(fstring));
-
- /*
- * However, smbc_auth_fn may have picked up info relating to an
- * existing connection, so try for an existing connection again ...
- */
-
- for (srv=smbc_srvs;srv;srv=srv->next) {
- if (strcmp(server,srv->server_name)==0 &&
- strcmp(share,srv->share_name)==0 &&
- strcmp(workgroup,srv->workgroup)==0 &&
- strcmp(username, srv->username) == 0)
- return srv;
+ srv = context->callbacks.get_cached_srv_fn(context, server, share,
+ workgroup, username);
+
+ if (!auth_called && !srv && (!username[0] || !password[0])) {
+ context->callbacks.auth_fn(server, share, workgroup, sizeof(fstring),
+ username, sizeof(fstring), password, sizeof(fstring));
+ /*
+ * However, smbc_auth_fn may have picked up info relating to an
+ * existing connection, so try for an existing connection again ...
+ */
+ auth_called = 1;
+ goto check_server_cache;
+
}
+
+ if (srv) {
+ if (context->callbacks.check_server_fn(context, srv)) {
+ /*
+ * This server is no good anymore
+ * Try to remove it and check for more possible servers in the cache
+ */
+ if (context->callbacks.remove_unused_server_fn(context, srv)) {
+ /*
+ * We could not remove the server completely, remove it from the cache
+ * so we will not get it again. It will be removed when the last file/dir
+ * is closed.
+ */
+ context->callbacks.remove_cached_srv_fn(context, srv);
+ }
+
+ /*
+ * Maybe there are more cached connections to this server
+ */
+ goto check_server_cache;
+ }
+ return srv;
+ }
- make_nmb_name(&calling, my_netbios_name, 0x0);
+ make_nmb_name(&calling, context->netbios_name, 0x0);
make_nmb_name(&called , server, 0x20);
DEBUG(4,("smbc_server: server_n=[%s] server=[%s]\n", server_n, server));
@@ -303,21 +350,52 @@ struct smbc_server *smbc_server(char *server, char *share,
again:
slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);
- zero_ip(&ip);
+ zero_ip(&ip);
/* have to open a new connection */
- if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {
- if (c.initialised) cli_shutdown(&c);
+ if (!cli_initialise(&c)) {
errno = ENOENT;
return NULL;
}
+ c.timeout = context->timeout;
+
+ if (!cli_connect(&c, server_n, &ip)) {
+ cli_shutdown(&c);
+ errno = ENOENT;
+ return NULL;
+ }
+
if (!cli_session_request(&c, &calling, &called)) {
cli_shutdown(&c);
if (strcmp(called.name, "*SMBSERVER")) {
make_nmb_name(&called , "*SMBSERVER", 0x20);
goto again;
}
+ else { /* Try one more time, but ensure we don't loop */
+
+ /* Only try this if server is an IP address ... */
+
+ if (is_ipaddress(server) && !tried_reverse) {
+ fstring remote_name;
+ struct in_addr rem_ip;
+
+ if (!inet_aton(server, &rem_ip)) {
+ DEBUG(4, ("Could not convert IP address %s to struct in_addr\n", server));
+ errno = ENOENT;
+ return NULL;
+ }
+
+ tried_reverse++; /* Yuck */
+
+ if (name_status_find("*", 0, 0, rem_ip, remote_name)) {
+ make_nmb_name(&called, remote_name, 0x20);
+ goto again;
+ }
+
+
+ }
+ }
errno = ENOENT;
return NULL;
}
@@ -345,50 +423,37 @@ struct smbc_server *smbc_server(char *server, char *share,
if (!cli_send_tconX(&c, share, "?????",
password, strlen(password)+1)) {
- errno = smbc_errno(&c);
+ errno = smbc_errno(context, &c);
cli_shutdown(&c);
return NULL;
}
DEBUG(4,(" tconx ok\n"));
- srv = (struct smbc_server *)malloc(sizeof(*srv));
+ /*
+ * Ok, we have got a nice connection
+ * Let's find a free server_fd
+ */
+
+ srv = (SMBCSRV *)malloc(sizeof(*srv));
if (!srv) {
errno = ENOMEM;
goto failed;
}
ZERO_STRUCTP(srv);
-
srv->cli = c;
-
srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
- srv->server_name = strdup(server);
- if (!srv->server_name) {
- errno = ENOMEM;
- goto failed;
- }
-
- srv->share_name = strdup(share);
- if (!srv->share_name) {
- errno = ENOMEM;
+ /* now add it to the cache (internal or external) */
+ if (context->callbacks.add_cached_srv_fn(context, srv, server, share, workgroup, username)) {
+ DEBUG(3, (" Failed to add server to cache\n"));
goto failed;
}
- srv->workgroup = strdup(workgroup);
- if (!srv->workgroup) {
- errno = ENOMEM;
- goto failed;
- }
-
- srv->username = strdup(username);
- if (!srv->username) {
- errno = ENOMEM;
- goto failed;
- }
-
- DLIST_ADD(smbc_srvs, srv);
+
+ DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
+ server, share, srv));
return srv;
@@ -396,214 +461,49 @@ struct smbc_server *smbc_server(char *server, char *share,
cli_shutdown(&c);
if (!srv) return NULL;
- SAFE_FREE(srv->server_name);
- SAFE_FREE(srv->share_name);
- SAFE_FREE(srv->workgroup);
- SAFE_FREE(srv->username);
SAFE_FREE(srv);
return NULL;
}
-/*
- *Remove a server from the list smbc_srvs if it's unused -- Tom (tom@ninja.nl)
- *
- * We accept a *srv
- */
-BOOL smbc_remove_unused_server(struct smbc_server * s)
-{
- int p;
-
- /* are we being fooled ? */
- if (!s) return False;
-
- /* close all open files/directories on this server */
- for (p = 0; p < SMBC_MAX_FD; p++) {
- if (smbc_file_table[p] &&
- smbc_file_table[p]->srv == s) {
- /* Still used .. DARN */
- DEBUG(3, ("smbc_remove_usused_server: %x still used by %s (%d).\n", (int) s,
- smbc_file_table[p]->fname, smbc_file_table[p]->smbc_fd));
- return False;
- }
- }
-
- cli_shutdown(&s->cli);
-
- SAFE_FREE(s->username);
- SAFE_FREE(s->workgroup);
- SAFE_FREE(s->server_name);
- SAFE_FREE(s->share_name);
- DLIST_REMOVE(smbc_srvs, s);
- DEBUG(3, ("smbc_remove_usused_server: %x removed.\n", (int) s));
- SAFE_FREE(s);
- return True;
-}
-
-/*
- *Initialise the library etc
- *
- * We accept valid values for debug from 0 to 100,
- * and insist that fn must be non-null.
- */
-
-int smbc_init(smbc_get_auth_data_fn fn, int debug)
-{
- pstring conf;
- int p, pid;
- char *user = NULL, *home = NULL, *pname="libsmbclient";
-
- if (!fn || debug < 0 || debug > 100) {
-
- errno = EINVAL;
- return -1;
-
- }
-
- if (smbc_initialized) { /* Don't go through this if we have already done it */
-
- return 0;
-
- }
-
- smbc_initialized = 1;
- smbc_auth_fn = fn;
- /* smbc_debug = debug; */
-
- DEBUGLEVEL = -1;
-
- setup_logging(pname, False);
-
- /* Here we would open the smb.conf file if needed ... */
-
- home = getenv("HOME");
-
- slprintf(conf, sizeof(conf), "%s/.smb/smb.conf", home);
-
- load_interfaces(); /* Load the list of interfaces ... */
-
- in_client = True; /* FIXME, make a param */
-
- if (!lp_load(conf, True, False, False)) {
-
- /*
- * Hmmm, what the hell do we do here ... we could not parse the
- * config file ... We must return an error ... and keep info around
- * about why we failed
- */
-
- errno = ENOENT; /* FIXME: Figure out the correct error response */
- return -1;
-
- }
-
- reopen_logs(); /* Get logging working ... */
-
- /*
- * FIXME: Is this the best way to get the user info?
- */
-
- user = getenv("USER");
- /* walk around as "guest" if no username can be found */
- if (!user) user = strdup("guest");
- pstrcpy(smbc_user, user); /* Save for use elsewhere */
-
- /*
- * We try to get our netbios name from the config. If that fails we fall
- * back on constructing our netbios name from our hostname etc
- */
- if (global_myname) {
- pstrcpy(my_netbios_name, global_myname);
- }
- else {
- /*
- * Hmmm, I want to get hostname as well, but I am too lazy for the moment
- */
- pid = sys_getpid();
- slprintf(my_netbios_name, 16, "smbc%s%d", user, pid);
- }
- DEBUG(0,("Using netbios name %s.\n", my_netbios_name));
-
- name_register_wins(my_netbios_name, 0);
-
- /*
- * Now initialize the file descriptor array and figure out what the
- * max open files is, so we can return FD's that are above the max
- * open file, and separated by a guard band
- */
-
-#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
- do {
- struct rlimit rlp;
-
- if (getrlimit(RLIMIT_NOFILE, &rlp)) {
-
- DEBUG(0, ("smbc_init: getrlimit(1) for RLIMIT_NOFILE failed with error %s\n", strerror(errno)));
-
- smbc_start_fd = 1000000;
-
- }
- else {
-
- smbc_start_fd = rlp.rlim_max + 10000; /* Leave a guard space of 10,000 */
-
- }
- } while ( 0 );
-#else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
-
- smbc_start_fd = 1000000;
-
-#endif
-
- smbc_file_table = malloc(SMBC_MAX_FD * sizeof(struct smbc_file *));
-
- for (p = 0; p < SMBC_MAX_FD; p++)
- smbc_file_table[p] = NULL;
-
- if (!smbc_file_table)
- return ENOMEM;
-
- return 0; /* Success */
-
-}
-
/*
* Routine to open() a file ...
*/
-int smbc_open(const char *fname, int flags, mode_t mode)
+static SMBCFILE *smbc_open_ctx(SMBCCTX *context, const char *fname, int flags, mode_t mode)
{
fstring server, share, user, password, workgroup;
pstring path;
- struct smbc_server *srv = NULL;
+ SMBCSRV *srv = NULL;
+ SMBCFILE *file = NULL;
int fd;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL; /* Best I can think of ... */
- return -1;
+ return NULL;
}
if (!fname) {
errno = EINVAL;
- return -1;
+ return NULL;
}
- smbc_parse_path(fname, server, share, path, user, password); /* FIXME, check errors */
+ smbc_parse_path(context, fname, server, share, path, user, password); /* FIXME, check errors */
- if (user[0] == (char)0) pstrcpy(user, smbc_user);
+ if (user[0] == (char)0) pstrcpy(user, context->user);
- pstrcpy(workgroup, lp_workgroup());
+ pstrcpy(workgroup, context->workgroup);
- srv = smbc_server(server, share, workgroup, user, password);
+ srv = smbc_server(context, server, share, workgroup, user, password);
if (!srv) {
if (errno == EPERM) errno = EACCES;
- return -1; /* smbc_server sets errno */
-
+ return NULL; /* smbc_server sets errno */
+
}
/* Hmmm, the test for a directory is suspect here ... FIXME */
@@ -614,50 +514,38 @@ int smbc_open(const char *fname, int flags, mode_t mode)
}
else {
+
+ file = malloc(sizeof(SMBCFILE));
- int slot = 0;
-
- /* Find a free slot first */
-
- while (smbc_file_table[slot])
- slot++;
-
- if (slot > SMBC_MAX_FD) {
-
- errno = ENOMEM; /* FIXME, is this best? */
- return -1;
-
- }
-
- smbc_file_table[slot] = malloc(sizeof(struct smbc_file));
-
- if (!smbc_file_table[slot]) {
+ if (!file) {
errno = ENOMEM;
- return -1;
+ return NULL;
}
+ ZERO_STRUCTP(file);
+
if ((fd = cli_open(&srv->cli, path, flags, DENY_NONE)) < 0) {
/* Handle the error ... */
- SAFE_FREE(smbc_file_table[slot]);
- errno = smbc_errno(&srv->cli);
- return -1;
+ SAFE_FREE(file);
+ errno = smbc_errno(context, &srv->cli);
+ return NULL;
}
/* Fill in file struct */
- smbc_file_table[slot]->cli_fd = fd;
- smbc_file_table[slot]->smbc_fd = slot + smbc_start_fd;
- smbc_file_table[slot]->fname = strdup(fname);
- smbc_file_table[slot]->srv = srv;
- smbc_file_table[slot]->offset = 0;
- smbc_file_table[slot]->file = True;
+ file->cli_fd = fd;
+ file->fname = strdup(fname);
+ file->srv = srv;
+ file->offset = 0;
+ file->file = True;
- return smbc_file_table[slot]->smbc_fd;
+ DLIST_ADD(context->_files, file);
+ return file;
}
@@ -666,14 +554,15 @@ int smbc_open(const char *fname, int flags, mode_t mode)
if (fd == -1) {
int eno = 0;
- eno = smbc_errno(&srv->cli);
- fd = smbc_opendir(fname);
- if (fd < 0) errno = eno;
- return fd;
+ eno = smbc_errno(context, &srv->cli);
+ file = context->opendir(context, fname);
+ if (!file) errno = eno;
+ return file;
}
- return 1; /* Success, with fd ... */
+ errno = EINVAL; /* FIXME, correct errno ? */
+ return NULL;
}
@@ -683,38 +572,37 @@ int smbc_open(const char *fname, int flags, mode_t mode)
static int creat_bits = O_WRONLY | O_CREAT | O_TRUNC; /* FIXME: Do we need this */
-int smbc_creat(const char *path, mode_t mode)
+static SMBCFILE *smbc_creat_ctx(SMBCCTX *context, const char *path, mode_t mode)
{
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
- return -1;
+ return NULL;
}
- return smbc_open(path, creat_bits, mode);
+ return smbc_open_ctx(context, path, creat_bits, mode);
}
/*
* Routine to read() a file ...
*/
-ssize_t smbc_read(int fd, void *buf, size_t count)
+static ssize_t smbc_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t count)
{
- struct smbc_file *fe;
int ret;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- DEBUG(4, ("smbc_read(%d, %d)\n", fd, (int)count));
+ DEBUG(4, ("smbc_read(%p, %d)\n", file, (int)count));
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
@@ -730,25 +618,16 @@ ssize_t smbc_read(int fd, void *buf, size_t count)
}
- fe = smbc_file_table[fd - smbc_start_fd];
-
- if (!fe || !fe->file) {
-
- errno = EBADF;
- return -1;
-
- }
-
- ret = cli_read(&fe->srv->cli, fe->cli_fd, buf, fe->offset, count);
+ ret = cli_read(&file->srv->cli, file->cli_fd, buf, file->offset, count);
if (ret < 0) {
- errno = smbc_errno(&fe->srv->cli);
+ errno = smbc_errno(context, &file->srv->cli);
return -1;
}
- fe->offset += ret;
+ file->offset += ret;
DEBUG(4, (" --> %d\n", ret));
@@ -760,19 +639,18 @@ ssize_t smbc_read(int fd, void *buf, size_t count)
* Routine to write() a file ...
*/
-ssize_t smbc_write(int fd, void *buf, size_t count)
+static ssize_t smbc_write_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t count)
{
int ret;
- struct smbc_file *fe;
- if (!smbc_initialized) {
+ if (!context || context->_initialized) {
errno = EINVAL;
return -1;
}
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
@@ -788,25 +666,16 @@ ssize_t smbc_write(int fd, void *buf, size_t count)
}
- fe = smbc_file_table[fd - smbc_start_fd];
-
- if (!fe || !fe->file) {
-
- errno = EBADF;
- return -1;
-
- }
-
- ret = cli_write(&fe->srv->cli, fe->cli_fd, 0, buf, fe->offset, count);
+ ret = cli_write(&file->srv->cli, file->cli_fd, 0, buf, file->offset, count);
if (ret <= 0) {
- errno = smbc_errno(&fe->srv->cli);
+ errno = smbc_errno(context, &file->srv->cli);
return -1;
}
- fe->offset += ret;
+ file->offset += ret;
return ret; /* Success, 0 bytes of data ... */
}
@@ -815,75 +684,123 @@ ssize_t smbc_write(int fd, void *buf, size_t count)
* Routine to close() a file ...
*/
-int smbc_close(int fd)
+static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file)
{
- struct smbc_file *fe;
- struct smbc_server *srv;
+ SMBCSRV *srv;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
}
- fe = smbc_file_table[fd - smbc_start_fd];
+ /* IS a dir ... */
+ if (!file->file) {
+
+ return context->closedir(context, file);
- if (!fe) {
+ }
+
+ if (!cli_close(&file->srv->cli, file->cli_fd)) {
+
+ DEBUG(3, ("cli_close failed on %s. purging server.\n",
+ file->fname));
+ /* Deallocate slot and remove the server
+ * from the server cache if unused */
+ errno = smbc_errno(context, &file->srv->cli);
+ srv = file->srv;
+ DLIST_REMOVE(context->_files, file);
+ SAFE_FREE(file->fname);
+ SAFE_FREE(file);
+ context->callbacks.remove_unused_server_fn(context, srv);
- errno = EBADF;
return -1;
}
- if (!fe->file) {
+ if (!file->file) {
- return smbc_closedir(fd);
+ return context->closedir(context, file);
}
- if (!cli_close(&fe->srv->cli, fe->cli_fd)) {
-
- DEBUG(3, ("cli_close failed on %s (%d). purging server.\n",
- fe->fname, fe->smbc_fd));
+ if (!cli_close(&file->srv->cli, file->cli_fd)) {
+ DEBUG(3, ("cli_close failed on %s. purging server.\n",
+ file->fname));
/* Deallocate slot and remove the server
* from the server cache if unused */
- errno = smbc_errno(&fe->srv->cli);
- srv = fe->srv;
- SAFE_FREE(fe->fname);
- SAFE_FREE(fe);
- smbc_file_table[fd - smbc_start_fd] = NULL;
- smbc_remove_unused_server(srv);
+ errno = smbc_errno(context, &file->srv->cli);
+ srv = file->srv;
+ DLIST_REMOVE(context->_files, file);
+ SAFE_FREE(file->fname);
+ SAFE_FREE(file);
+ context->callbacks.remove_unused_server_fn(context, srv);
return -1;
-
}
- SAFE_FREE(fe->fname);
- SAFE_FREE(fe);
- smbc_file_table[fd - smbc_start_fd] = NULL;
+ DLIST_REMOVE(context->_files, file);
+ SAFE_FREE(file->fname);
+ SAFE_FREE(file);
return 0;
}
/*
+ * Get info from an SMB server on a file. Use a qpathinfo call first
+ * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo
+ */
+static BOOL smbc_getatr(SMBCCTX * context, SMBCSRV *srv, char *path,
+ uint16 *mode, size_t *size,
+ time_t *c_time, time_t *a_time, time_t *m_time,
+ SMB_INO_T *ino)
+{
+
+ if (!context || !context->_initialized) {
+
+ errno = EINVAL;
+ return -1;
+
+ }
+
+ DEBUG(4,("smbc_getatr: sending qpathinfo\n"));
+
+ if (!srv->no_pathinfo2 &&
+ cli_qpathinfo2(&srv->cli, path, c_time, a_time, m_time, NULL,
+ size, mode, ino)) return True;
+
+ /* if this is NT then don't bother with the getatr */
+ if (srv->cli.capabilities & CAP_NT_SMBS) return False;
+
+ if (cli_getatr(&srv->cli, path, mode, size, m_time)) {
+ a_time = c_time = m_time;
+ srv->no_pathinfo2 = True;
+ return True;
+ }
+
+ return False;
+
+}
+
+/*
* Routine to unlink() a file
*/
-int smbc_unlink(const char *fname)
+static int smbc_unlink_ctx(SMBCCTX *context, const char *fname)
{
fstring server, share, user, password, workgroup;
pstring path;
- struct smbc_server *srv = NULL;
+ SMBCSRV *srv = NULL;
- if (!smbc_initialized) {
+ if (!context || context->_initialized) {
errno = EINVAL; /* Best I can think of ... */
return -1;
@@ -897,13 +814,13 @@ int smbc_unlink(const char *fname)
}
- smbc_parse_path(fname, server, share, path, user, password); /* FIXME, check errors */
+ smbc_parse_path(context, fname, server, share, path, user, password); /* FIXME, check errors */
- if (user[0] == (char)0) pstrcpy(user, smbc_user);
+ if (user[0] == (char)0) pstrcpy(user, context->user);
- pstrcpy(workgroup, lp_workgroup());
+ pstrcpy(workgroup, context->workgroup);
- srv = smbc_server(server, share, workgroup, user, password);
+ srv = smbc_server(context, server, share, workgroup, user, password);
if (!srv) {
@@ -913,23 +830,23 @@ int smbc_unlink(const char *fname)
/* if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
- int job = smbc_stat_printjob(srv, path, NULL, NULL);
- if (job == -1) {
+ int job = smbc_stat_printjob(srv, path, NULL, NULL);
+ if (job == -1) {
- return -1;
+ return -1;
- }
- if ((err = cli_printjob_del(&srv->cli, job)) != 0) {
+ }
+ if ((err = cli_printjob_del(&srv->cli, job)) != 0) {
- return -1;
+ return -1;
- }
- } else */
+ }
+ } else */
if (!cli_unlink(&srv->cli, path)) {
- errno = smbc_errno(&srv->cli);
+ errno = smbc_errno(context, &srv->cli);
if (errno == EACCES) { /* Check if the file is a directory */
@@ -939,12 +856,12 @@ int smbc_unlink(const char *fname)
time_t m_time = 0, a_time = 0, c_time = 0;
SMB_INO_T ino = 0;
- if (!smbc_getatr(srv, path, &mode, &size,
+ if (!smbc_getatr(context, srv, path, &mode, &size,
&c_time, &a_time, &m_time, &ino)) {
/* Hmmm, bad error ... What? */
- errno = smbc_errno(&srv->cli);
+ errno = smbc_errno(context, &srv->cli);
return -1;
}
@@ -970,35 +887,37 @@ int smbc_unlink(const char *fname)
* Routine to rename() a file
*/
-int smbc_rename(const char *oname, const char *nname)
+static int smbc_rename_ctx(SMBCCTX *ocontext, const char *oname,
+ SMBCCTX *ncontext, const char *nname)
{
fstring server1, share1, server2, share2, user1, user2, password1, password2, workgroup;
pstring path1, path2;
- struct smbc_server *srv = NULL;
+ SMBCSRV *srv = NULL;
- if (!smbc_initialized) {
+ if (!ocontext || !ncontext ||
+ !ocontext->_initialized || !ncontext->_initialized) {
errno = EINVAL; /* Best I can think of ... */
return -1;
}
-
+
if (!oname || !nname) {
errno = EINVAL;
return -1;
}
-
+
DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname));
- smbc_parse_path(oname, server1, share1, path1, user1, password1);
+ smbc_parse_path(ocontext, oname, server1, share1, path1, user1, password1);
- if (user1[0] == (char)0) pstrcpy(user1, smbc_user);
+ if (user1[0] == (char)0) pstrcpy(user1, ocontext->user);
- smbc_parse_path(nname, server2, share2, path2, user2, password2);
+ smbc_parse_path(ncontext, nname, server2, share2, path2, user2, password2);
- if (user2[0] == (char)0) pstrcpy(user2, smbc_user);
+ if (user2[0] == (char)0) pstrcpy(user2, ncontext->user);
if (strcmp(server1, server2) || strcmp(share1, share2) ||
strcmp(user1, user2)) {
@@ -1010,9 +929,9 @@ int smbc_rename(const char *oname, const char *nname)
}
- pstrcpy(workgroup, lp_workgroup());
-
- srv = smbc_server(server1, share1, workgroup, user1, password1);
+ pstrcpy(workgroup, ocontext->workgroup);
+ /* HELP !!! Which workgroup should I use ? Or are they always the same -- Tom */
+ srv = smbc_server(ocontext, server1, share1, workgroup, user1, password1);
if (!srv) {
return -1;
@@ -1020,7 +939,7 @@ int smbc_rename(const char *oname, const char *nname)
}
if (!cli_rename(&srv->cli, path1, path2)) {
- int eno = smbc_errno(&srv->cli);
+ int eno = smbc_errno(ocontext, &srv->cli);
if (eno != EEXIST ||
!cli_unlink(&srv->cli, path2) ||
@@ -1040,35 +959,25 @@ int smbc_rename(const char *oname, const char *nname)
* A routine to lseek() a file
*/
-off_t smbc_lseek(int fd, off_t offset, int whence)
+static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int whence)
{
- struct smbc_file *fe;
size_t size;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
-
- }
-
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
-
- errno = EBADF;
- return -1;
-
+
}
- fe = smbc_file_table[fd - smbc_start_fd];
-
- if (!fe) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
}
- if (!fe->file) {
+ if (!file->file) {
errno = EINVAL;
return -1; /* Can't lseek a dir ... */
@@ -1077,23 +986,23 @@ off_t smbc_lseek(int fd, off_t offset, int whence)
switch (whence) {
case SEEK_SET:
- fe->offset = offset;
+ file->offset = offset;
break;
case SEEK_CUR:
- fe->offset += offset;
+ file->offset += offset;
break;
case SEEK_END:
- if (!cli_qfileinfo(&fe->srv->cli, fe->cli_fd, NULL, &size, NULL, NULL,
+ if (!cli_qfileinfo(&file->srv->cli, file->cli_fd, NULL, &size, NULL, NULL,
NULL, NULL, NULL) &&
- !cli_getattrE(&fe->srv->cli, fe->cli_fd, NULL, &size, NULL, NULL,
+ !cli_getattrE(&file->srv->cli, file->cli_fd, NULL, &size, NULL, NULL,
NULL)) {
errno = EINVAL;
return -1;
}
- fe->offset = size + offset;
+ file->offset = size + offset;
break;
default:
@@ -1102,7 +1011,7 @@ off_t smbc_lseek(int fd, off_t offset, int whence)
}
- return fe->offset;
+ return file->offset;
}
@@ -1111,9 +1020,16 @@ off_t smbc_lseek(int fd, off_t offset, int whence)
*/
static
-ino_t smbc_inode(const char *name)
+ino_t smbc_inode(SMBCCTX *context, const char *name)
{
+ if (!context || !context->_initialized) {
+
+ errno = EINVAL;
+ return -1;
+
+ }
+
if (!*name) return 2; /* FIXME, why 2 ??? */
return (ino_t)str_checksum(name);
@@ -1125,9 +1041,9 @@ ino_t smbc_inode(const char *name)
*/
static
-int smbc_setup_stat(struct stat *st, char *fname, size_t size, int mode)
+int smbc_setup_stat(SMBCCTX *context, struct stat *st, char *fname, size_t size, int mode)
{
-
+
st->st_mode = 0;
if (IS_DOS_DIR(mode)) {
@@ -1154,55 +1070,20 @@ int smbc_setup_stat(struct stat *st, char *fname, size_t size, int mode)
}
if (st->st_ino == 0) {
- st->st_ino = smbc_inode(fname);
+ st->st_ino = smbc_inode(context, fname);
}
-
+
return True; /* FIXME: Is this needed ? */
}
/*
- * Get info from an SMB server on a file. Use a qpathinfo call first
- * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo
- */
-
-BOOL smbc_getatr(struct smbc_server *srv, char *path,
- uint16 *mode, size_t *size,
- time_t *c_time, time_t *a_time, time_t *m_time,
- SMB_INO_T *ino)
-{
-
- if (!smbc_initialized) {
-
- errno = EINVAL;
- return -1;
-
- }
-
- DEBUG(4,("smbc_getatr: sending qpathinfo\n"));
-
- if (!srv->no_pathinfo2 &&
- cli_qpathinfo2(&srv->cli, path, c_time, a_time, m_time, NULL,
- size, mode, ino)) return True;
-
- /* if this is NT then don't bother with the getatr */
- if (srv->cli.capabilities & CAP_NT_SMBS) return False;
-
- if (cli_getatr(&srv->cli, path, mode, size, m_time)) {
- a_time = c_time = m_time;
- srv->no_pathinfo2 = True;
- return True;
- }
- return False;
-}
-
-/*
* Routine to stat a file given a name
*/
-int smbc_stat(const char *fname, struct stat *st)
+static int smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st)
{
- struct smbc_server *srv;
+ SMBCSRV *srv;
fstring server, share, user, password, workgroup;
pstring path;
time_t m_time = 0, a_time = 0, c_time = 0;
@@ -1210,11 +1091,11 @@ int smbc_stat(const char *fname, struct stat *st)
uint16 mode = 0;
SMB_INO_T ino = 0;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL; /* Best I can think of ... */
return -1;
-
+
}
if (!fname) {
@@ -1226,13 +1107,13 @@ int smbc_stat(const char *fname, struct stat *st)
DEBUG(4, ("smbc_stat(%s)\n", fname));
- smbc_parse_path(fname, server, share, path, user, password); /*FIXME, errors*/
+ smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
- if (user[0] == (char)0) pstrcpy(user, smbc_user);
+ if (user[0] == (char)0) pstrcpy(user, context->user);
- pstrcpy(workgroup, lp_workgroup());
+ pstrcpy(workgroup, context->workgroup);
- srv = smbc_server(server, share, workgroup, user, password);
+ srv = smbc_server(context, server, share, workgroup, user, password);
if (!srv) {
@@ -1246,9 +1127,9 @@ int smbc_stat(const char *fname, struct stat *st)
}
else if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
-
+
if (strcmp(path, "\\") == 0) {
-
+
mode = aDIR | aRONLY;
}
@@ -1261,19 +1142,17 @@ int smbc_stat(const char *fname, struct stat *st)
}
else { */
- if (!smbc_getatr(srv, path, &mode, &size,
+ if (!smbc_getatr(context, srv, path, &mode, &size,
&c_time, &a_time, &m_time, &ino)) {
- errno = smbc_errno(&srv->cli);
+ errno = smbc_errno(context, &srv->cli);
return -1;
-
+
}
- /* } */
-
st->st_ino = ino;
- smbc_setup_stat(st, path, size, mode);
+ smbc_setup_stat(context, st, path, size, mode);
st->st_atime = a_time;
st->st_ctime = c_time;
@@ -1288,46 +1167,36 @@ int smbc_stat(const char *fname, struct stat *st)
* Routine to stat a file given an fd
*/
-int smbc_fstat(int fd, struct stat *st)
+static int smbc_fstat_ctx(SMBCCTX *context, SMBCFILE *file, struct stat *st)
{
- struct smbc_file *fe;
time_t c_time, a_time, m_time;
size_t size;
uint16 mode;
SMB_INO_T ino = 0;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
+ if (!file || !DLIST_CONTAINS(context->_files, file)) {
errno = EBADF;
return -1;
}
- fe = smbc_file_table[fd - smbc_start_fd];
+ if (!file->file) {
- if (!fe) {
-
- errno = EBADF;
- return -1;
+ return context->fstatdir(context, file, st);
}
- if (!fe->file) {
-
- return smbc_fstatdir(fd, st);
-
- }
-
- if (!cli_qfileinfo(&fe->srv->cli, fe->cli_fd,
+ if (!cli_qfileinfo(&file->srv->cli, file->cli_fd,
&mode, &size, &c_time, &a_time, &m_time, NULL, &ino) &&
- !cli_getattrE(&fe->srv->cli, fe->cli_fd,
+ !cli_getattrE(&file->srv->cli, file->cli_fd,
&mode, &size, &c_time, &a_time, &m_time)) {
errno = EINVAL;
@@ -1337,12 +1206,12 @@ int smbc_fstat(int fd, struct stat *st)
st->st_ino = ino;
- smbc_setup_stat(st, fe->fname, size, mode);
+ smbc_setup_stat(context, st, file->fname, size, mode);
st->st_atime = a_time;
st->st_ctime = c_time;
st->st_mtime = m_time;
- st->st_dev = fe->srv->dev;
+ st->st_dev = file->srv->dev;
return 0;
@@ -1362,7 +1231,7 @@ int smbc_fstat(int fd, struct stat *st)
* smb://<IP-addr>/share which should list files on share
*/
-static void smbc_remove_dir(struct smbc_file *dir)
+static void smbc_remove_dir(SMBCFILE *dir)
{
struct smbc_dir_list *d,*f;
@@ -1380,7 +1249,7 @@ static void smbc_remove_dir(struct smbc_file *dir)
}
-static int add_dirent(struct smbc_file *dir, const char *name, const char *comment, uint32 type)
+static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint32 type)
{
struct smbc_dirent *dirent;
int size;
@@ -1403,6 +1272,11 @@ static int add_dirent(struct smbc_file *dir, const char *name, const char *comme
}
+ ZERO_STRUCTP(dirent);
+
+ ZERO_STRUCTP(dirent);
+
+
if (dir->dir_list == NULL) {
dir->dir_list = malloc(sizeof(struct smbc_dir_list));
@@ -1413,6 +1287,7 @@ static int add_dirent(struct smbc_file *dir, const char *name, const char *comme
return -1;
}
+ ZERO_STRUCTP(dir->dir_list);
dir->dir_end = dir->dir_next = dir->dir_list;
@@ -1420,14 +1295,15 @@ static int add_dirent(struct smbc_file *dir, const char *name, const char *comme
else {
dir->dir_end->next = malloc(sizeof(struct smbc_dir_list));
-
- if (!dir->dir_end) {
-
+
+ if (!dir->dir_end->next) {
+
SAFE_FREE(dirent);
dir->dir_error = ENOMEM;
return -1;
}
+ ZERO_STRUCTP(dir->dir_end->next);
dir->dir_end = dir->dir_end->next;
@@ -1435,7 +1311,7 @@ static int add_dirent(struct smbc_file *dir, const char *name, const char *comme
dir->dir_end->next = NULL;
dir->dir_end->dirent = dirent;
-
+
dirent->smbc_type = type;
dirent->namelen = (name?strlen(name):0);
dirent->commentlen = (comment?strlen(comment):0);
@@ -1453,13 +1329,13 @@ static int add_dirent(struct smbc_file *dir, const char *name, const char *comme
static void
list_fn(const char *name, uint32 type, const char *comment, void *state)
{
- struct smbc_file *dir = (struct smbc_file *)state;
+ SMBCFILE *dir = (SMBCFILE *)state;
int dirent_type;
/* We need to process the type a little ... */
if (dir->dir_type == SMBC_FILE_SHARE) {
-
+
switch (type) {
case 0: /* Directory tree */
dirent_type = SMBC_FILE_SHARE;
@@ -1481,6 +1357,7 @@ list_fn(const char *name, uint32 type, const char *comment, void *state)
dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */
break;
}
+ ZERO_STRUCTP(dir->dir_list);
}
else dirent_type = dir->dir_type;
@@ -1498,113 +1375,103 @@ static void
dir_list_fn(file_info *finfo, const char *mask, void *state)
{
- if (add_dirent((struct smbc_file *)state, finfo->name, "",
+ if (add_dirent((SMBCFILE *)state, finfo->name, "",
(finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) {
/* Handle an error ... */
+
/* FIXME: Add some code ... */
}
}
-int smbc_opendir(const char *fname)
+static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
{
fstring server, share, user, password, workgroup;
pstring path;
- struct smbc_server *srv = NULL;
+ SMBCSRV *srv = NULL;
+ SMBCFILE *dir = NULL;
struct in_addr rem_ip;
int slot = 0;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
- return -1;
+ return NULL;
}
if (!fname) {
errno = EINVAL;
- return -1;
+ return NULL;
}
- if (smbc_parse_path(fname, server, share, path, user, password)) {
+ if (smbc_parse_path(context, fname, server, share, path, user, password)) {
errno = EINVAL;
- return -1;
+ return NULL;
}
- if (user[0] == (char)0) pstrcpy(user, smbc_user);
-
- pstrcpy(workgroup, lp_workgroup());
+ if (user[0] == (char)0) pstrcpy(user, context->user);
- /* Get a file entry ... */
+ pstrcpy(workgroup, context->workgroup);
- slot = 0;
+ dir = malloc(sizeof(*dir));
- while (smbc_file_table[slot])
- slot++;
-
- if (slot > SMBC_MAX_FD) {
+ if (!dir) {
errno = ENOMEM;
- return -1; /* FIXME, ... move into a func */
-
- }
-
- smbc_file_table[slot] = malloc(sizeof(struct smbc_file));
-
- if (!smbc_file_table[slot]) {
-
- errno = ENOMEM;
- return -1;
+ return NULL;
}
- smbc_file_table[slot]->cli_fd = 0;
- smbc_file_table[slot]->smbc_fd = slot + smbc_start_fd;
- smbc_file_table[slot]->fname = strdup(fname);
- smbc_file_table[slot]->srv = NULL;
- smbc_file_table[slot]->offset = 0;
- smbc_file_table[slot]->file = False;
- smbc_file_table[slot]->dir_list =
- smbc_file_table[slot]->dir_next =
- smbc_file_table[slot]->dir_end = NULL;
+ ZERO_STRUCTP(dir);
+
+ dir->cli_fd = 0;
+ dir->fname = strdup(fname);
+ dir->srv = NULL;
+ dir->offset = 0;
+ dir->file = False;
+ dir->dir_list = dir->dir_next = dir->dir_end = NULL;
if (server[0] == (char)0) {
if (share[0] != (char)0 || path[0] != (char)0) {
errno = EINVAL;
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- return -1;
+ return NULL;
}
/* We have server and share and path empty ... so list the workgroups */
+ /* first try to get the LMB for our workgroup, and if that fails, */
+ /* try the DMB */
- if (!resolve_name(lp_workgroup(), &rem_ip, 0x1d)) {
+ if (!(resolve_name(context->workgroup, &rem_ip, 0x1d) ||
+ resolve_name(context->workgroup, &rem_ip, 0x1b))) {
errno = EINVAL; /* Something wrong with smb.conf? */
- return -1;
+ return NULL;
}
- smbc_file_table[slot]->dir_type = SMBC_WORKGROUP;
+ dir->dir_type = SMBC_WORKGROUP;
/* find the name of the server ... */
if (!name_status_find("*", 0, 0, rem_ip, server)) {
- DEBUG(0, ("Could not get the name of local master browser for server %s\n", server));
+ DEBUG(0,("Could not get the name of local/domain master browser for server %s\n", server));
errno = EINVAL;
- return -1;
+ return NULL;
}
@@ -1612,31 +1479,34 @@ int smbc_opendir(const char *fname)
* Get a connection to IPC$ on the server if we do not already have one
*/
- srv = smbc_server(server, "IPC$", workgroup, user, password);
+ srv = smbc_server(context, server, "IPC$", workgroup, user, password);
if (!srv) {
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- return -1;
+
+ return NULL;
}
+ ZERO_STRUCTP(dir->dir_end);
- smbc_file_table[slot]->srv = srv;
+ dir->srv = srv;
/* Now, list the stuff ... */
if (!cli_NetServerEnum(&srv->cli, workgroup, 0x80000000, list_fn,
- (void *)smbc_file_table[slot])) {
+ (void *)dir)) {
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
errno = cli_errno(&srv->cli);
- return -1;
+
+ return NULL;
}
}
@@ -1647,22 +1517,23 @@ int smbc_opendir(const char *fname)
if (path[0] != (char)0) { /* Should not have empty share with path */
errno = EINVAL;
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- return -1;
+ return NULL;
}
- /* Check to see if <server><1D> translates, or <server><20> translates */
+ /* Check to see if <server><1D>, <server><1B>, or <server><20> translates */
/* However, we check to see if <server> is an IP address first */
if (!is_ipaddress(server) && /* Not an IP addr so check next */
- resolve_name(server, &rem_ip, 0x1d)) { /* Found LMB */
+ (resolve_name(server, &rem_ip, 0x1d) || /* Found LMB */
+ resolve_name(server, &rem_ip, 0x1b) )) { /* Found DMB */
pstring buserver;
- smbc_file_table[slot]->dir_type = SMBC_SERVER;
+ dir->dir_type = SMBC_SERVER;
/*
* Get the backup list ...
@@ -1671,9 +1542,9 @@ int smbc_opendir(const char *fname)
if (!name_status_find("*", 0, 0, rem_ip, buserver)) {
- DEBUG(0, ("Could not get name of local master browser %s\n", server));
+ DEBUG(0, ("Could not get name of local/domain master browser for server %s\n", server));
errno = EPERM; /* FIXME, is this correct */
- return -1;
+ return NULL;
}
@@ -1681,32 +1552,32 @@ int smbc_opendir(const char *fname)
* Get a connection to IPC$ on the server if we do not already have one
*/
- srv = smbc_server(buserver, "IPC$", workgroup, user, password);
+ srv = smbc_server(context, buserver, "IPC$", workgroup, user, password);
if (!srv) {
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- return -1;
+ return NULL;
}
- smbc_file_table[slot]->srv = srv;
+ dir->srv = srv;
/* Now, list the servers ... */
if (!cli_NetServerEnum(&srv->cli, server, 0x0000FFFE, list_fn,
- (void *)smbc_file_table[slot])) {
+ (void *)dir)) {
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
errno = cli_errno(&srv->cli);
- return -1;
-
+ return NULL;
+
}
}
@@ -1716,33 +1587,33 @@ int smbc_opendir(const char *fname)
/* Now, list the shares ... */
- smbc_file_table[slot]->dir_type = SMBC_FILE_SHARE;
+ dir->dir_type = SMBC_FILE_SHARE;
- srv = smbc_server(server, "IPC$", workgroup, user, password);
+ srv = smbc_server(context, server, "IPC$", workgroup, user, password);
if (!srv) {
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- return -1;
+ return NULL;
}
- smbc_file_table[slot]->srv = srv;
+ dir->srv = srv;
/* Now, list the servers ... */
if (cli_RNetShareEnum(&srv->cli, list_fn,
- (void *)smbc_file_table[slot]) < 0) {
+ (void *)dir) < 0) {
errno = cli_errno(&srv->cli);
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- return -1;
+ return NULL;
}
@@ -1750,11 +1621,11 @@ int smbc_opendir(const char *fname)
else {
errno = ENODEV; /* Neither the workgroup nor server exists */
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- return -1;
+ return NULL;
}
@@ -1765,42 +1636,43 @@ int smbc_opendir(const char *fname)
/* Well, we connect to the server and list the directory */
- smbc_file_table[slot]->dir_type = SMBC_FILE_SHARE;
+ dir->dir_type = SMBC_FILE_SHARE;
- srv = smbc_server(server, share, workgroup, user, password);
+ srv = smbc_server(context, server, share, workgroup, user, password);
if (!srv) {
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- return -1;
+ return NULL;
}
- smbc_file_table[slot]->srv = srv;
+ dir->srv = srv;
/* Now, list the files ... */
pstrcat(path, "\\*");
if (cli_list(&srv->cli, path, aDIR | aSYSTEM | aHIDDEN, dir_list_fn,
- (void *)smbc_file_table[slot]) < 0) {
+ (void *)dir) < 0) {
- if (smbc_file_table[slot]) {
- SAFE_FREE(smbc_file_table[slot]->fname);
- SAFE_FREE(smbc_file_table[slot]);
+ if (dir) {
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir);
}
- errno = smbc_errno(&srv->cli);
- return -1;
+ errno = smbc_errno(context, &srv->cli);
+ return NULL;
}
}
}
- return smbc_file_table[slot]->smbc_fd;
+ DLIST_ADD(context->_files, dir);
+ return dir;
}
@@ -1808,44 +1680,34 @@ int smbc_opendir(const char *fname)
* Routine to close a directory
*/
-int smbc_closedir(int fd)
+static int smbc_closedir_ctx(SMBCCTX *context, SMBCFILE *dir)
{
- struct smbc_file *fe;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
+ if (!dir || !DLIST_CONTAINS(context->_files, dir)) {
errno = EBADF;
return -1;
-
+
}
- fe = smbc_file_table[fd - smbc_start_fd];
-
- if (!fe) {
+ smbc_remove_dir(dir); /* Clean it up */
- errno = EBADF;
- return -1;
-
- }
+ DLIST_REMOVE(context->_files, dir);
- smbc_remove_dir(fe); /* Clean it up */
+ if (dir) {
- if (fe) {
-
- SAFE_FREE(fe->fname);
- SAFE_FREE(fe); /* Free the space too */
+ SAFE_FREE(dir->fname);
+ SAFE_FREE(dir); /* Free the space too */
}
- smbc_file_table[fd - smbc_start_fd] = NULL;
-
return 0;
}
@@ -1854,50 +1716,38 @@ int smbc_closedir(int fd)
* Routine to get a directory entry
*/
-static char smbc_local_dirent[512]; /* Make big enough */
-
-struct smbc_dirent *smbc_readdir(unsigned int fd)
+struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir)
{
- struct smbc_file *fe;
struct smbc_dirent *dirp, *dirent;
/* Check that all is ok first ... */
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return NULL;
}
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
+ if (!dir || !DLIST_CONTAINS(context->_files, dir)) {
errno = EBADF;
return NULL;
}
- fe = smbc_file_table[fd - smbc_start_fd];
-
- if (!fe) {
-
- errno = EBADF;
- return NULL;
-
- }
-
- if (fe->file != False) { /* FIXME, should be dir, perhaps */
+ if (dir->file != False) { /* FIXME, should be dir, perhaps */
errno = ENOTDIR;
return NULL;
}
- if (!fe->dir_next)
+ if (!dir->dir_next)
return NULL;
else {
- dirent = fe->dir_next->dirent;
+ dirent = dir->dir_next->dirent;
if (!dirent) {
@@ -1908,15 +1758,12 @@ struct smbc_dirent *smbc_readdir(unsigned int fd)
/* Hmmm, do I even need to copy it? */
- memcpy(smbc_local_dirent, dirent, dirent->dirlen); /* Copy the dirent */
-
- dirp = (struct smbc_dirent *)smbc_local_dirent;
-
+ memcpy(context->_dirent, dirent, dirent->dirlen); /* Copy the dirent */
+ dirp = (struct smbc_dirent *)context->_dirent;
dirp->comment = (char *)(&dirp->name + dirent->namelen + 1);
-
- fe->dir_next = fe->dir_next->next;
+ dir->dir_next = dir->dir_next->next;
- return (struct smbc_dirent *)smbc_local_dirent;
+ return (struct smbc_dirent *)context->_dirent;
}
}
@@ -1925,39 +1772,29 @@ struct smbc_dirent *smbc_readdir(unsigned int fd)
* Routine to get directory entries
*/
-int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count)
+static int smbc_getdents_ctx(SMBCCTX *context, SMBCFILE *dir, struct smbc_dirent *dirp, int count)
{
- struct smbc_file *fe;
- struct smbc_dir_list *dir;
+ struct smbc_dir_list *dirlist;
int rem = count, reqd;
char *ndir = (char *)dirp;
/* Check that all is ok first ... */
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
-
- errno = EBADF;
- return -1;
-
- }
-
- fe = smbc_file_table[fd - smbc_start_fd];
-
- if (!fe) {
+ if (!dir || !DLIST_CONTAINS(context->_files, dir)) {
errno = EBADF;
return -1;
-
+
}
- if (fe->file != False) { /* FIXME, should be dir, perhaps */
+ if (dir->file != False) { /* FIXME, should be dir, perhaps */
errno = ENOTDIR;
return -1;
@@ -1970,18 +1807,18 @@ int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count)
* send a request to the server to get the info.
*/
- while ((dir = fe->dir_next)) {
+ while ((dirlist = dir->dir_next)) {
struct smbc_dirent *dirent;
- if (!dir->dirent) {
+ if (!dirlist->dirent) {
errno = ENOENT; /* Bad error */
return -1;
}
- if (rem < (reqd = (sizeof(struct smbc_dirent) + dir->dirent->namelen +
- dir->dirent->commentlen + 1))) {
+ if (rem < (reqd = (sizeof(struct smbc_dirent) + dirlist->dirent->namelen +
+ dirlist->dirent->commentlen + 1))) {
if (rem < count) { /* We managed to copy something */
@@ -1998,7 +1835,7 @@ int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count)
}
- dirent = dir->dirent;
+ dirent = dirlist->dirent;
memcpy(ndir, dirent, reqd); /* Copy the data in ... */
@@ -2009,7 +1846,7 @@ int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count)
rem -= reqd;
- fe->dir_next = dir = dir -> next;
+ dir->dir_next = dirlist = dirlist -> next;
}
if (rem == count)
@@ -2023,13 +1860,13 @@ int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count)
* Routine to create a directory ...
*/
-int smbc_mkdir(const char *fname, mode_t mode)
+static int smbc_mkdir_ctx(SMBCCTX *context, const char *fname, mode_t mode)
{
- struct smbc_server *srv;
+ SMBCSRV *srv;
fstring server, share, user, password, workgroup;
pstring path;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2045,13 +1882,13 @@ int smbc_mkdir(const char *fname, mode_t mode)
DEBUG(4, ("smbc_mkdir(%s)\n", fname));
- smbc_parse_path(fname, server, share, path, user, password); /*FIXME, errors*/
+ smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
- if (user[0] == (char)0) pstrcpy(user, smbc_user);
+ if (user[0] == (char)0) pstrcpy(user, context->user);
- pstrcpy(workgroup, lp_workgroup());
+ pstrcpy(workgroup, context->workgroup);
- srv = smbc_server(server, share, workgroup, user, password);
+ srv = smbc_server(context, server, share, workgroup, user, password);
if (!srv) {
@@ -2082,7 +1919,7 @@ int smbc_mkdir(const char *fname, mode_t mode)
if (!cli_mkdir(&srv->cli, path)) {
- errno = smbc_errno(&srv->cli);
+ errno = smbc_errno(context, &srv->cli);
return -1;
}
@@ -2109,13 +1946,13 @@ static void rmdir_list_fn(file_info *finfo, const char *mask, void *state)
* Routine to remove a directory
*/
-int smbc_rmdir(const char *fname)
+static int smbc_rmdir_ctx(SMBCCTX *context, const char *fname)
{
- struct smbc_server *srv;
+ SMBCSRV *srv;
fstring server, share, user, password, workgroup;
pstring path;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2131,13 +1968,13 @@ int smbc_rmdir(const char *fname)
DEBUG(4, ("smbc_rmdir(%s)\n", fname));
- smbc_parse_path(fname, server, share, path, user, password); /*FIXME, errors*/
+ smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
- if (user[0] == (char)0) pstrcpy(user, smbc_user);
+ if (user[0] == (char)0) pstrcpy(user, context->user);
- pstrcpy(workgroup, lp_workgroup());
+ pstrcpy(workgroup, context->workgroup);
- srv = smbc_server(server, share, workgroup, user, password);
+ srv = smbc_server(context, server, share, workgroup, user, password);
if (!srv) {
@@ -2162,13 +1999,13 @@ int smbc_rmdir(const char *fname)
mode = aRONLY;
smbc_stat_printjob(srv, path, &size, &m_time);
c_time = a_time = m_time;
-
+
}
else { */
if (!cli_rmdir(&srv->cli, path)) {
- errno = smbc_errno(&srv->cli);
+ errno = smbc_errno(context, &srv->cli);
if (errno == EACCES) { /* Check if the dir empty or not */
@@ -2185,7 +2022,7 @@ int smbc_rmdir(const char *fname)
/* Fix errno to ignore latest error ... */
DEBUG(5, ("smbc_rmdir: cli_list returned an error: %d\n",
- smbc_errno(&srv->cli)));
+ smbc_errno(context, &srv->cli)));
errno = EACCES;
}
@@ -2209,41 +2046,31 @@ int smbc_rmdir(const char *fname)
* Routine to return the current directory position
*/
-off_t smbc_telldir(int fd)
+static off_t smbc_telldir_ctx(SMBCCTX *context, SMBCFILE *dir)
{
- struct smbc_file *fe;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
+ if (!dir || !DLIST_CONTAINS(context->_files, dir)) {
errno = EBADF;
return -1;
}
- fe = smbc_file_table[fd - smbc_start_fd];
-
- if (!fe) {
-
- errno = EBADF;
- return -1;
-
- }
-
- if (fe->file != False) { /* FIXME, should be dir, perhaps */
+ if (dir->file != False) { /* FIXME, should be dir, perhaps */
errno = ENOTDIR;
return -1;
}
- return (off_t) fe->dir_next;
+ return (off_t) dir->dir_next;
}
@@ -2281,36 +2108,19 @@ struct smbc_dir_list *smbc_check_dir_ent(struct smbc_dir_list *list,
* Routine to seek on a directory
*/
-int smbc_lseekdir(int fd, off_t offset)
+static int smbc_lseekdir_ctx(SMBCCTX *context, SMBCFILE *dir, off_t offset)
{
- struct smbc_file *fe;
struct smbc_dirent *dirent = (struct smbc_dirent *)offset;
struct smbc_dir_list *list_ent = NULL;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
}
- if (fd < smbc_start_fd || fd >= (smbc_start_fd + SMBC_MAX_FD)) {
-
- errno = EBADF;
- return -1;
-
- }
-
- fe = smbc_file_table[fd - smbc_start_fd];
-
- if (!fe) {
-
- errno = EBADF;
- return -1;
-
- }
-
- if (fe->file != False) { /* FIXME, should be dir, perhaps */
+ if (dir->file != False) { /* FIXME, should be dir, perhaps */
errno = ENOTDIR;
return -1;
@@ -2321,7 +2131,7 @@ int smbc_lseekdir(int fd, off_t offset)
if (dirent == NULL) { /* Seek to the begining of the list */
- fe->dir_next = fe->dir_list;
+ dir->dir_next = dir->dir_list;
return 0;
}
@@ -2329,14 +2139,14 @@ int smbc_lseekdir(int fd, off_t offset)
/* Now, run down the list and make sure that the entry is OK */
/* This may need to be changed if we change the format of the list */
- if ((list_ent = smbc_check_dir_ent(fe->dir_list, dirent)) == NULL) {
+ if ((list_ent = smbc_check_dir_ent(dir->dir_list, dirent)) == NULL) {
errno = EINVAL; /* Bad entry */
return -1;
}
- fe->dir_next = list_ent;
+ dir->dir_next = list_ent;
return 0;
@@ -2346,10 +2156,10 @@ int smbc_lseekdir(int fd, off_t offset)
* Routine to fstat a dir
*/
-int smbc_fstatdir(int fd, struct stat *st)
+static int smbc_fstatdir_ctx(SMBCCTX *context, SMBCFILE *dir, struct stat *st)
{
- if (!smbc_initialized) {
+ if (context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2363,18 +2173,53 @@ int smbc_fstatdir(int fd, struct stat *st)
}
/*
+ * Open a print file to be written to by other calls
+ */
+
+static SMBCFILE *smbc_open_print_job_ctx(SMBCCTX *context, const char *fname)
+{
+ fstring server, share, user, password;
+ pstring path;
+
+ if (!context || context->_initialized) {
+
+ errno = EINVAL;
+ return NULL;
+
+ }
+
+ if (!fname) {
+
+ errno = EINVAL;
+ return NULL;
+
+ }
+
+ DEBUG(4, ("smbc_open_print_job_ctx(%s)\n", fname));
+
+ smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
+
+ /* What if the path is empty, or the file exists? */
+
+ return context->open(context, fname, O_WRONLY, 666);
+
+}
+
+/*
* Routine to print a file on a remote server ...
*
* We open the file, which we assume to be on a remote server, and then
* copy it to a print file on the share specified by printq.
*/
-int smbc_print_file(const char *fname, const char *printq)
+static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_print, const char *printq)
{
- int fid1, fid2, bytes, saverr, tot_bytes = 0;
+ SMBCFILE *fid1, *fid2;
+ int bytes, saverr, tot_bytes = 0;
char buf[4096];
- if (!smbc_initialized) {
+ if (!c_file || !c_file->_initialized || !c_print ||
+ !c_print->_initialized) {
errno = EINVAL;
return -1;
@@ -2390,33 +2235,33 @@ int smbc_print_file(const char *fname, const char *printq)
/* Try to open the file for reading ... */
- if ((fid1 = smbc_open(fname, O_RDONLY, 0666)) < 0) {
-
+ if ((fid1 = c_file->open(c_file, fname, O_RDONLY, 0666)) < 0) {
+
DEBUG(3, ("Error, fname=%s, errno=%i\n", fname, errno));
return -1; /* smbc_open sets errno */
-
+
}
/* Now, try to open the printer file for writing */
- if ((fid2 = smbc_open_print_job(printq)) < 0) {
+ if ((fid2 = c_print->open_print_job(c_print, printq)) < 0) {
saverr = errno; /* Save errno */
- smbc_close(fid1);
+ c_file->close(c_file, fid1);
errno = saverr;
return -1;
}
- while ((bytes = smbc_read(fid1, buf, sizeof(buf))) > 0) {
+ while ((bytes = c_file->read(c_file, fid1, buf, sizeof(buf))) > 0) {
tot_bytes += bytes;
- if ((smbc_write(fid2, buf, bytes)) < 0) {
+ if ((c_print->write(c_print, fid2, buf, bytes)) < 0) {
saverr = errno;
- smbc_close(fid1);
- smbc_close(fid2);
+ c_file->close(c_file, fid1);
+ c_print->close(c_print, fid2);
errno = saverr;
}
@@ -2425,8 +2270,8 @@ int smbc_print_file(const char *fname, const char *printq)
saverr = errno;
- smbc_close(fid1); /* We have to close these anyway */
- smbc_close(fid2);
+ c_file->close(c_file, fid1); /* We have to close these anyway */
+ c_print->close(c_print, fid2);
if (bytes < 0) {
@@ -2440,15 +2285,16 @@ int smbc_print_file(const char *fname, const char *printq)
}
/*
- * Open a print file to be written to by other calls
+ * Routine to list print jobs on a printer share ...
*/
-int smbc_open_print_job(const char *fname)
+static int smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, void (*fn)(struct print_job_info *))
{
- fstring server, share, user, password;
+ SMBCSRV *srv;
+ fstring server, share, user, password, workgroup;
pstring path;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2456,33 +2302,51 @@ int smbc_open_print_job(const char *fname)
}
if (!fname) {
-
+
errno = EINVAL;
return -1;
}
- DEBUG(4, ("smbc_open_print_job(%s)\n", fname));
+ DEBUG(4, ("smbc_list_print_jobs(%s)\n", fname));
- smbc_parse_path(fname, server, share, path, user, password); /*FIXME, errors*/
+ smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
- /* What if the path is empty, or the file exists? */
+ if (user[0] == (char)0) pstrcpy(user, context->user);
+
+ pstrcpy(workgroup, context->workgroup);
- return smbc_open(fname, O_WRONLY, 666);
+ srv = smbc_server(context, server, share, workgroup, user, password);
+
+ if (!srv) {
+
+ return -1; /* errno set by smbc_server */
+
+ }
+
+ if (cli_print_queue(&srv->cli, fn) < 0) {
+
+ errno = smbc_errno(context, &srv->cli);
+ return -1;
+
+ }
+
+ return 0;
}
/*
- * Routine to list print jobs on a printer share ...
+ * Delete a print job from a remote printer share
*/
-int smbc_list_print_jobs(const char *fname, void (*fn)(struct print_job_info *))
+static int smbc_unlink_print_job_ctx(SMBCCTX *context, const char *fname, int id)
{
- struct smbc_server *srv;
+ SMBCSRV *srv;
fstring server, share, user, password, workgroup;
pstring path;
+ int err;
- if (!smbc_initialized) {
+ if (!context || !context->_initialized) {
errno = EINVAL;
return -1;
@@ -2496,15 +2360,15 @@ int smbc_list_print_jobs(const char *fname, void (*fn)(struct print_job_info *))
}
- DEBUG(4, ("smbc_list_print_jobs(%s)\n", fname));
+ DEBUG(4, ("smbc_unlink_print_job(%s)\n", fname));
- smbc_parse_path(fname, server, share, path, user, password); /*FIXME, errors*/
+ smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
- if (user[0] == (char)0) pstrcpy(user, smbc_user);
+ if (user[0] == (char)0) pstrcpy(user, context->user);
- pstrcpy(workgroup, lp_workgroup());
+ pstrcpy(workgroup, context->workgroup);
- srv = smbc_server(server, share, workgroup, user, password);
+ srv = smbc_server(context, server, share, workgroup, user, password);
if (!srv) {
@@ -2512,9 +2376,12 @@ int smbc_list_print_jobs(const char *fname, void (*fn)(struct print_job_info *))
}
- if (cli_print_queue(&srv->cli, fn) < 0) {
+ if ((err = cli_printjob_del(&srv->cli, id)) != 0) {
- errno = smbc_errno(&srv->cli);
+ if (err < 0)
+ errno = smbc_errno(context, &srv->cli);
+ else if (err == ERRnosuchprintjob)
+ errno = EINVAL;
return -1;
}
@@ -2524,58 +2391,252 @@ int smbc_list_print_jobs(const char *fname, void (*fn)(struct print_job_info *))
}
/*
- * Delete a print job from a remote printer share
+ * Get a new empty handle to fill in with your own info
*/
+SMBCCTX * smbc_new_context(void)
+{
+ SMBCCTX * context;
+
+ context = malloc(sizeof(*context));
+ if (!context) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ ZERO_STRUCTP(context);
+
+ /* ADD REASONABLE DEFAULTS */
+ context->debug = 0;
+ context->timeout = 20000; /* 20 seconds */
+
+ context->open = smbc_open_ctx;
+ context->creat = smbc_creat_ctx;
+ context->read = smbc_read_ctx;
+ context->write = smbc_write_ctx;
+ context->close = smbc_close_ctx;
+ context->unlink = smbc_unlink_ctx;
+ context->rename = smbc_rename_ctx;
+ context->lseek = smbc_lseek_ctx;
+ context->stat = smbc_stat_ctx;
+ context->fstat = smbc_fstat_ctx;
+ context->opendir = smbc_opendir_ctx;
+ context->closedir = smbc_closedir_ctx;
+ context->readdir = smbc_readdir_ctx;
+ context->getdents = smbc_getdents_ctx;
+ context->mkdir = smbc_mkdir_ctx;
+ context->rmdir = smbc_rmdir_ctx;
+ context->telldir = smbc_telldir_ctx;
+ context->lseekdir = smbc_lseekdir_ctx;
+ context->fstatdir = smbc_fstatdir_ctx;
+ context->open_print_job = smbc_open_print_job_ctx;
+ context->print_file = smbc_print_file_ctx;
+ context->list_print_jobs = smbc_list_print_jobs_ctx;
+ context->unlink_print_job = smbc_unlink_print_job_ctx;
+
+ context->callbacks.check_server_fn = smbc_check_server;
+ context->callbacks.remove_unused_server_fn = smbc_remove_unused_server;
+
+ smbc_default_cache_functions(context);
+
+ return context;
+}
-int smbc_unlink_print_job(const char *fname, int id)
+/*
+ * Free a context
+ *
+ * Returns 0 on success. Otherwise returns 1, the SMBCCTX is _not_ freed
+ * and thus you'll be leaking memory if not handled properly.
+ *
+ */
+int smbc_free_context(SMBCCTX * context, int shutdown_ctx)
{
- struct smbc_server *srv;
- fstring server, share, user, password, workgroup;
- pstring path;
- int err;
+ if (!context) {
+ errno = EBADF;
+ return 1;
+ }
+
+ if (shutdown_ctx) {
+ SMBCFILE * f;
+ DEBUG(1,("Performing aggressive shutdown.\n"));
+
+ f = context->_files;
+ while (f) {
+ context->close(context, f);
+ f = f->next;
+ }
+ context->_files = NULL;
+
+ /* First try to remove the servers the nice way. */
+ if (context->callbacks.purge_cached_fn(context)) {
+ SMBCSRV * s;
+ DEBUG(1, ("Could not purge all servers, Nice way shutdown failed.\n"));
+ s = context->_servers;
+ while (s) {
+ cli_shutdown(&s->cli);
+ context->callbacks.remove_cached_srv_fn(context, s);
+ SAFE_FREE(s);
+ s = s->next;
+ }
+ context->_servers = NULL;
+ }
+ }
+ else {
+ /* This is the polite way */
+ if (context->callbacks.purge_cached_fn(context)) {
+ DEBUG(1, ("Could not purge all servers, free_context failed.\n"));
+ errno = EBUSY;
+ return 1;
+ }
+ if (context->_servers) {
+ DEBUG(1, ("Active servers in context, free_context failed.\n"));
+ errno = EBUSY;
+ return 1;
+ }
+ if (context->_files) {
+ DEBUG(1, ("Active files in context, free_context failed.\n"));
+ errno = EBUSY;
+ return 1;
+ }
+ }
- if (!smbc_initialized) {
+ /* Things we have to clean up */
+ SAFE_FREE(context->workgroup);
+ SAFE_FREE(context->netbios_name);
+ SAFE_FREE(context->user);
+
+ DEBUG(3, ("Context %p succesfully freed\n", context));
+ SAFE_FREE(context);
+ return 0;
+}
- errno = EINVAL;
- return -1;
+/*
+ * Initialise the library etc
+ *
+ * We accept a struct containing handle information.
+ * valid values for info->debug from 0 to 100,
+ * and insist that info->fn must be non-null.
+ */
+SMBCCTX * smbc_init_context(SMBCCTX * context)
+{
+ pstring conf;
+ int pid;
+ char *user = NULL, *home = NULL;
+
+ if (!context) {
+ errno = EBADF;
+ return NULL;
}
- if (!fname) {
+ /* Do not initialise the same client twice */
+ if (context->_initialized) {
+ return 0;
+ }
+
+ if (!context->callbacks.auth_fn || context->debug < 0 || context->debug > 100) {
errno = EINVAL;
- return -1;
+ return NULL;
}
-
- DEBUG(4, ("smbc_unlink_print_job(%s)\n", fname));
- smbc_parse_path(fname, server, share, path, user, password); /*FIXME, errors*/
-
- if (user[0] == (char)0) pstrcpy(user, smbc_user);
+ if (!smbc_initialized) {
+ /* Do some library wide intialisations the first time we get called */
- pstrcpy(workgroup, lp_workgroup());
+ /* Do we still need this ? */
+ DEBUGLEVEL = 10;
+
+ setup_logging( "libsmbclient", False);
- srv = smbc_server(server, share, workgroup, user, password);
+ /* Here we would open the smb.conf file if needed ... */
+
+ home = getenv("HOME");
- if (!srv) {
+ slprintf(conf, sizeof(conf), "%s/.smb/smb.conf", home);
+
+ load_interfaces(); /* Load the list of interfaces ... */
+
+ in_client = True; /* FIXME, make a param */
- return -1; /* errno set by smbc_server */
+ if (!lp_load(conf, True, False, False)) {
- }
+ /*
+ * Hmmm, what the hell do we do here ... we could not parse the
+ * config file ... We must return an error ... and keep info around
+ * about why we failed
+ */
+
+ errno = ENOENT; /* FIXME: Figure out the correct error response */
+ return NULL;
+ }
- if ((err = cli_printjob_del(&srv->cli, id)) != 0) {
+ reopen_logs(); /* Get logging working ... */
+
+ /*
+ * Block SIGPIPE (from lib/util_sock.c: write())
+ * It is not needed and should not stop execution
+ */
+ BlockSignals(True, SIGPIPE);
+
+ /* Done with one-time initialisation */
+ smbc_initialized = 1;
- if (err < 0)
- errno = smbc_errno(&srv->cli);
- else if (err == ERRnosuchprintjob)
- errno = EINVAL;
- return -1;
+ }
+
+ if (!context->user) {
+ /*
+ * FIXME: Is this the best way to get the user info?
+ */
+ user = getenv("USER");
+ /* walk around as "guest" if no username can be found */
+ if (!user) context->user = strdup("guest");
+ else context->user = strdup(user);
+ }
+ if (!context->netbios_name) {
+ /*
+ * We try to get our netbios name from the config. If that fails we fall
+ * back on constructing our netbios name from our hostname etc
+ */
+ if (global_myname) {
+ context->netbios_name = strdup(global_myname);
+ }
+ else {
+ /*
+ * Hmmm, I want to get hostname as well, but I am too lazy for the moment
+ */
+ pid = sys_getpid();
+ context->netbios_name = malloc(17);
+ if (!context->netbios_name) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ slprintf(context->netbios_name, 16, "smbc%s%d", context->user, pid);
+ }
+ }
+ DEBUG(0,("Using netbios name %s.\n", context->netbios_name));
+
+ if (!context->workgroup) {
+ if (lp_workgroup()) {
+ context->workgroup = strdup(lp_workgroup());
+ }
+ else {
+ /* TODO: Think about a decent default workgroup */
+ context->workgroup = strdup("samba");
+ }
}
+ DEBUG(0,("Using workgroup %s.\n", context->workgroup));
+
+ /* shortest timeout is 1 second */
+ if (context->timeout > 0 && context->timeout < 1000)
+ context->timeout = 1000;
- return 0;
+ /*
+ * FIXME: Should we check the function pointers here?
+ */
+ context->_initialized = 1;
+
+ return context;
}
-
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 7928d44652..18564bccf4 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -191,7 +191,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, 0, STR_TERMINATE);
+ pull_ascii(name, status[i].name, 15, -1, STR_TERMINATE);
result = True;
done:
@@ -207,257 +207,233 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t
return result;
}
-/****************************************************************************
- Do a NetBIOS name registation to try to claim a name ...
-***************************************************************************/
-BOOL name_register(int fd, const char *name, int name_type,
- struct in_addr name_ip, int opcode,
- BOOL bcast,
- struct in_addr to_ip, int *count)
-{
- int retries = 3;
- struct timeval tval;
- struct packet_struct p;
- struct packet_struct *p2;
- struct nmb_packet *nmb = &p.packet.nmb;
- struct in_addr register_ip;
-
- DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
-
- register_ip.s_addr = name_ip.s_addr; /* Fix this ... */
-
- memset((char *)&p, '\0', sizeof(p));
-
- *count = 0;
-
- nmb->header.name_trn_id = generate_trn_id();
- nmb->header.opcode = opcode;
- nmb->header.response = False;
- nmb->header.nm_flags.bcast = False;
- nmb->header.nm_flags.recursion_available = False;
- nmb->header.nm_flags.recursion_desired = True; /* ? */
- nmb->header.nm_flags.trunc = False;
- nmb->header.nm_flags.authoritative = True;
-
- nmb->header.qdcount = 1;
- nmb->header.ancount = 0;
- nmb->header.nscount = 0;
- nmb->header.arcount = 1;
-
- make_nmb_name(&nmb->question.question_name, name, name_type);
-
- nmb->question.question_type = 0x20;
- nmb->question.question_class = 0x1;
-
- /* Now, create the additional stuff for a registration request */
-
- if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
-
- DEBUG(0, ("name_register: malloc fail for additional record.\n"));
- return False;
- }
-
- memset((char *)nmb->additional, '\0', sizeof(struct res_rec));
-
- nmb->additional->rr_name = nmb->question.question_name;
- nmb->additional->rr_type = RR_TYPE_NB;
- nmb->additional->rr_class = RR_CLASS_IN;
-
- /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
- if (nmb->header.nm_flags.bcast)
- nmb->additional->ttl = PERMANENT_TTL;
- else
- nmb->additional->ttl = lp_max_ttl();
-
- nmb->additional->rdlength = 6;
-
- nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
-
- /* Set the address for the name we are registering. */
- putip(&nmb->additional->rdata[2], &register_ip);
-
- p.ip = to_ip;
- p.port = NMB_PORT;
- p.fd = fd;
- p.timestamp = time(NULL);
- p.packet_type = NMB_PACKET;
-
- GetTimeOfDay(&tval);
+/*
+ comparison function used by sort_ip_list
+*/
+static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
+{
+ int max_bits1=0, max_bits2=0;
+ int num_interfaces = iface_count();
+ int i;
- if (!send_packet(&p))
- return False;
+ for (i=0;i<num_interfaces;i++) {
+ struct in_addr ip;
+ int bits1, bits2;
+ ip = *iface_n_bcast(i);
+ bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);
+ bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);
+ max_bits1 = MAX(bits1, max_bits1);
+ max_bits2 = MAX(bits2, max_bits2);
+ }
+
+ /* bias towards directly reachable IPs */
+ if (iface_local(*ip1)) {
+ max_bits1 += 32;
+ }
+ if (iface_local(*ip2)) {
+ max_bits2 += 32;
+ }
- retries--;
+ return max_bits2 - max_bits1;
+}
- if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
- debug_nmb_packet(p2);
- SAFE_FREE(p2); /* No memory leaks ... */
- }
+/*
+ sort an IP list so that names that are close to one of our interfaces
+ are at the top. This prevents the problem where a WINS server returns an IP that
+ is not reachable from our subnet as the first match
+*/
+static void sort_ip_list(struct in_addr *iplist, int count)
+{
+ if (count <= 1) {
+ return;
+ }
- return True;
+ qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);
}
+
/****************************************************************************
Do a netbios name query to find someones IP.
Returns an array of IP addresses or NULL if none.
*count will be set to the number of addresses returned.
+ *timed_out is set if we failed by timing out
****************************************************************************/
struct in_addr *name_query(int fd,const char *name,int name_type,
BOOL bcast,BOOL recurse,
- struct in_addr to_ip, int *count)
+ struct in_addr to_ip, int *count, int *flags,
+ BOOL *timed_out)
{
- BOOL found=False;
- int i, retries = 3;
- int retry_time = bcast?250:2000;
- struct timeval tval;
- struct packet_struct p;
- struct packet_struct *p2;
- struct nmb_packet *nmb = &p.packet.nmb;
- struct in_addr *ip_list = NULL;
-
- memset((char *)&p,'\0',sizeof(p));
- (*count) = 0;
-
- nmb->header.name_trn_id = generate_trn_id();
- nmb->header.opcode = 0;
- nmb->header.response = False;
- nmb->header.nm_flags.bcast = bcast;
- nmb->header.nm_flags.recursion_available = False;
- nmb->header.nm_flags.recursion_desired = recurse;
- nmb->header.nm_flags.trunc = False;
- nmb->header.nm_flags.authoritative = False;
- nmb->header.rcode = 0;
- nmb->header.qdcount = 1;
- nmb->header.ancount = 0;
- nmb->header.nscount = 0;
- nmb->header.arcount = 0;
-
- make_nmb_name(&nmb->question.question_name,name,name_type);
-
- nmb->question.question_type = 0x20;
- nmb->question.question_class = 0x1;
-
- p.ip = to_ip;
- p.port = NMB_PORT;
- p.fd = fd;
- p.timestamp = time(NULL);
- p.packet_type = NMB_PACKET;
-
- GetTimeOfDay(&tval);
-
- if (!send_packet(&p))
- return NULL;
-
- retries--;
+ BOOL found=False;
+ int i, retries = 3;
+ int retry_time = bcast?250:2000;
+ struct timeval tval;
+ struct packet_struct p;
+ struct packet_struct *p2;
+ struct nmb_packet *nmb = &p.packet.nmb;
+ struct in_addr *ip_list = NULL;
+ if (timed_out) {
+ *timed_out = False;
+ }
+
+ memset((char *)&p,'\0',sizeof(p));
+ (*count) = 0;
+ (*flags) = 0;
+
+ nmb->header.name_trn_id = generate_trn_id();
+ nmb->header.opcode = 0;
+ nmb->header.response = False;
+ nmb->header.nm_flags.bcast = bcast;
+ nmb->header.nm_flags.recursion_available = False;
+ nmb->header.nm_flags.recursion_desired = recurse;
+ nmb->header.nm_flags.trunc = False;
+ nmb->header.nm_flags.authoritative = False;
+ nmb->header.rcode = 0;
+ nmb->header.qdcount = 1;
+ nmb->header.ancount = 0;
+ nmb->header.nscount = 0;
+ nmb->header.arcount = 0;
+
+ make_nmb_name(&nmb->question.question_name,name,name_type);
+
+ nmb->question.question_type = 0x20;
+ nmb->question.question_class = 0x1;
+
+ p.ip = to_ip;
+ p.port = NMB_PORT;
+ p.fd = fd;
+ p.timestamp = time(NULL);
+ p.packet_type = NMB_PACKET;
+
+ GetTimeOfDay(&tval);
+
+ if (!send_packet(&p))
+ return NULL;
+
+ retries--;
+
while (1) {
- struct timeval tval2;
- struct in_addr *tmp_ip_list;
-
- GetTimeOfDay(&tval2);
- if (TvalDiff(&tval,&tval2) > retry_time) {
- if (!retries)
- break;
- if (!found && !send_packet(&p))
- return NULL;
- GetTimeOfDay(&tval);
- retries--;
- }
-
- if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
- struct nmb_packet *nmb2 = &p2->packet.nmb;
- debug_nmb_packet(p2);
-
- /* If we get a Negative Name Query Response from a WINS
- * server, we should report it and give up.
- */
- if( 0 == nmb2->header.opcode /* A query response */
- && !(bcast) /* from a WINS server */
- && nmb2->header.rcode /* Error returned */
- ) {
-
- if( DEBUGLVL( 3 ) ) {
- /* Only executed if DEBUGLEVEL >= 3 */
+ struct timeval tval2;
+ struct in_addr *tmp_ip_list;
+
+ GetTimeOfDay(&tval2);
+ if (TvalDiff(&tval,&tval2) > retry_time) {
+ if (!retries)
+ break;
+ if (!found && !send_packet(&p))
+ return NULL;
+ GetTimeOfDay(&tval);
+ retries--;
+ }
+
+ if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
+ struct nmb_packet *nmb2 = &p2->packet.nmb;
+ debug_nmb_packet(p2);
+
+ /* If we get a Negative Name Query Response from a WINS
+ * server, we should report it and give up.
+ */
+ if( 0 == nmb2->header.opcode /* A query response */
+ && !(bcast) /* from a WINS server */
+ && nmb2->header.rcode /* Error returned */
+ ) {
+
+ if( DEBUGLVL( 3 ) ) {
+ /* Only executed if DEBUGLEVEL >= 3 */
dbgtext( "Negative name query response, rcode 0x%02x: ", nmb2->header.rcode );
- switch( nmb2->header.rcode ) {
- case 0x01:
- dbgtext( "Request was invalidly formatted.\n" );
- break;
- case 0x02:
- dbgtext( "Problem with NBNS, cannot process name.\n");
- break;
- case 0x03:
- dbgtext( "The name requested does not exist.\n" );
- break;
- case 0x04:
- dbgtext( "Unsupported request error.\n" );
- break;
- case 0x05:
- dbgtext( "Query refused error.\n" );
- break;
- default:
- dbgtext( "Unrecognized error code.\n" );
- break;
- }
- }
- free_packet(p2);
- return( NULL );
- }
-
- if (nmb2->header.opcode != 0 ||
- nmb2->header.nm_flags.bcast ||
- nmb2->header.rcode ||
- !nmb2->header.ancount) {
- /*
- * XXXX what do we do with this? Could be a
- * redirect, but we'll discard it for the
+ switch( nmb2->header.rcode ) {
+ case 0x01:
+ dbgtext( "Request was invalidly formatted.\n" );
+ break;
+ case 0x02:
+ dbgtext( "Problem with NBNS, cannot process name.\n");
+ break;
+ case 0x03:
+ dbgtext( "The name requested does not exist.\n" );
+ break;
+ case 0x04:
+ dbgtext( "Unsupported request error.\n" );
+ break;
+ case 0x05:
+ dbgtext( "Query refused error.\n" );
+ break;
+ default:
+ dbgtext( "Unrecognized error code.\n" );
+ break;
+ }
+ }
+ free_packet(p2);
+ return( NULL );
+ }
+
+ if (nmb2->header.opcode != 0 ||
+ nmb2->header.nm_flags.bcast ||
+ nmb2->header.rcode ||
+ !nmb2->header.ancount) {
+ /*
+ * XXXX what do we do with this? Could be a
+ * redirect, but we'll discard it for the
* moment.
*/
- free_packet(p2);
- continue;
- }
-
- tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
- * ( (*count) + nmb2->answers->rdlength/6 ) );
-
- if (!tmp_ip_list) {
- DEBUG(0,("name_query: Realloc failed.\n"));
- SAFE_FREE(ip_list);
- }
-
- ip_list = tmp_ip_list;
-
- if (ip_list) {
+ free_packet(p2);
+ continue;
+ }
+
+ tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
+ * ( (*count) + nmb2->answers->rdlength/6 ) );
+
+ if (!tmp_ip_list) {
+ DEBUG(0,("name_query: Realloc failed.\n"));
+ SAFE_FREE(ip_list);
+ }
+
+ ip_list = tmp_ip_list;
+
+ if (ip_list) {
DEBUG(2,("Got a positive name query response from %s ( ", inet_ntoa(p2->ip)));
- for (i=0;i<nmb2->answers->rdlength/6;i++) {
- putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
- DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
- (*count)++;
- }
- DEBUGADD(2,(")\n"));
- }
+ for (i=0;i<nmb2->answers->rdlength/6;i++) {
+ putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
+ DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
+ (*count)++;
+ }
+ DEBUGADD(2,(")\n"));
+ }
+
+ found=True;
+ retries=0;
+ /* We add the flags back ... */
+ if (nmb2->header.response)
+ (*flags) |= NM_FLAGS_RS;
+ if (nmb2->header.nm_flags.authoritative)
+ (*flags) |= NM_FLAGS_AA;
+ if (nmb2->header.nm_flags.trunc)
+ (*flags) |= NM_FLAGS_TC;
+ if (nmb2->header.nm_flags.recursion_desired)
+ (*flags) |= NM_FLAGS_RD;
+ if (nmb2->header.nm_flags.recursion_available)
+ (*flags) |= NM_FLAGS_RA;
+ if (nmb2->header.nm_flags.bcast)
+ (*flags) |= NM_FLAGS_B;
+ free_packet(p2);
+ /*
+ * If we're doing a unicast lookup we only
+ * expect one reply. Don't wait the full 2
+ * seconds if we got one. JRA.
+ */
+ if(!bcast && found)
+ break;
+ }
+ }
- found=True;
- retries=0;
- free_packet(p2);
- /*
- * If we're doing a unicast lookup we only
- * expect one reply. Don't wait the full 2
- * seconds if we got one. JRA.
- */
- if(!bcast && found)
- break;
- }
- }
+ if (timed_out) {
+ *timed_out = True;
+ }
- /* Reach here if we've timed out waiting for replies.. */
- if( !bcast && !found ) {
- /* Timed out wating for WINS server to respond. Mark it dead. */
- wins_srv_died( to_ip );
- }
+ /* sort the ip list so we choose close servers first if possible */
+ sort_ip_list(ip_list, *count);
- return ip_list;
+ return ip_list;
}
/********************************************************
@@ -569,75 +545,6 @@ void endlmhosts(XFILE *fp)
x_fclose(fp);
}
-BOOL name_register_wins(const char *name, int name_type)
-{
- int sock, i, return_count;
- int num_interfaces = iface_count();
- struct in_addr sendto_ip;
-
- /*
- * Check if we have any interfaces, prevents a segfault later
- */
-
- if (num_interfaces <= 0)
- return False; /* Should return some indication of the problem */
-
- /*
- * Do a broadcast register ...
- */
-
- if (0 == wins_srv_count())
- return False;
-
- if( DEBUGLVL( 4 ) )
- {
- dbgtext( "name_register_wins: Registering my name %s ", name );
- dbgtext( "with WINS server %s.\n", wins_srv_name() );
- }
-
- sock = open_socket_in( SOCK_DGRAM, 0, 3,
- interpret_addr("0.0.0.0"), True );
-
- if (sock == -1) return False;
-
- set_socket_options(sock, "SO_BROADCAST"); /* ????! crh */
-
- sendto_ip = wins_srv_ip();
-
- if (num_interfaces > 1) {
-
- for (i = 0; i < num_interfaces; i++) {
-
- if (!name_register(sock, name, name_type, *iface_n_ip(i),
- NMB_NAME_MULTIHOMED_REG_OPCODE,
- True, sendto_ip, &return_count)) {
-
- close(sock);
- return False;
-
- }
-
- }
-
- }
- else {
-
- if (!name_register(sock, name, name_type, *iface_n_ip(0),
- NMB_NAME_REG_OPCODE,
- True, sendto_ip, &return_count)) {
-
- close(sock);
- return False;
-
- }
-
- }
-
- close(sock);
-
- return True;
-
-}
/********************************************************
Resolve via "bcast" method.
@@ -670,10 +577,11 @@ BOOL name_resolve_bcast(const char *name, int name_type,
*/
for( i = num_interfaces-1; i >= 0; i--) {
struct in_addr sendto_ip;
+ int flags;
/* Done this way to fix compiler error on IRIX 5.x */
sendto_ip = *iface_n_bcast(i);
*return_ip_list = name_query(sock, name, name_type, True,
- True, sendto_ip, return_count);
+ True, sendto_ip, return_count, &flags, NULL);
if(*return_ip_list != NULL) {
close(sock);
return True;
@@ -687,62 +595,88 @@ BOOL name_resolve_bcast(const char *name, int name_type,
/********************************************************
Resolve via "wins" method.
*********************************************************/
-
-static BOOL resolve_wins(const char *name, int name_type,
- struct in_addr **return_iplist, int *return_count)
+BOOL resolve_wins(const char *name, int name_type,
+ struct in_addr **return_iplist, int *return_count)
{
- int sock;
- struct in_addr wins_ip;
- BOOL wins_ismyip;
+ int sock, t, i;
+ char **wins_tags;
+ struct in_addr src_ip;
*return_iplist = NULL;
*return_count = 0;
- /*
- * "wins" means do a unicast lookup to the WINS server.
- * Ignore if there is no WINS server specified or if the
- * WINS server is one of our interfaces (if we're being
- * called from within nmbd - we can't do this call as we
- * would then block).
- */
-
DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
- if (lp_wins_support()) {
- /*
- * We're providing WINS support. Call ourselves so
- * long as we're not nmbd.
- */
- extern struct in_addr loopback_ip;
- wins_ip = loopback_ip;
- wins_ismyip = True;
- } else if( wins_srv_count() < 1 ) {
+ if (wins_srv_count() < 1) {
DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
return False;
- } else {
- wins_ip = wins_srv_ip();
- wins_ismyip = ismyip(wins_ip);
}
- DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
- if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
- sock = open_socket_in( SOCK_DGRAM, 0, 3,
- interpret_addr(lp_socket_address()),
- True );
- if (sock != -1) {
- *return_iplist = name_query( sock, name,
- name_type, False,
- True, wins_ip,
- return_count);
- if(*return_iplist != NULL) {
- close(sock);
- return True;
+ /* we try a lookup on each of the WINS tags in turn */
+ wins_tags = wins_srv_tags();
+
+ if (!wins_tags) {
+ /* huh? no tags?? give up in disgust */
+ return False;
+ }
+
+ /* the address we will be sending from */
+ src_ip = *interpret_addr2(lp_socket_address());
+
+ /* in the worst case we will try every wins server with every
+ tag! */
+ for (t=0; wins_tags && wins_tags[t]; t++) {
+ int srv_count = wins_srv_count_tag(wins_tags[t]);
+ for (i=0; i<srv_count; i++) {
+ struct in_addr wins_ip;
+ int flags;
+ BOOL timed_out;
+
+ wins_ip = wins_srv_ip_tag(wins_tags[t], src_ip);
+
+ if (global_in_nmbd && ismyip(wins_ip)) {
+ /* yikes! we'll loop forever */
+ continue;
+ }
+
+ /* skip any that have been unresponsive lately */
+ if (wins_srv_is_dead(wins_ip, src_ip)) {
+ continue;
+ }
+
+ DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
+
+ sock = open_socket_in(SOCK_DGRAM, 0, 3, src_ip.s_addr, True);
+ if (sock == -1) {
+ continue;
+ }
+
+ *return_iplist = name_query(sock,name,name_type, False,
+ True, wins_ip, return_count, &flags,
+ &timed_out);
+ if (*return_iplist != NULL) {
+ goto success;
}
close(sock);
+
+ if (timed_out) {
+ /* Timed out wating for WINS server to respond. Mark it dead. */
+ wins_srv_died(wins_ip, src_ip);
+ } else {
+ /* The name definately isn't in this
+ group of WINS servers. goto the next group */
+ break;
+ }
}
}
+ wins_srv_tags_free(wins_tags);
return False;
+
+success:
+ wins_srv_tags_free(wins_tags);
+ close(sock);
+ return True;
}
/********************************************************
@@ -992,52 +926,6 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
return False;
}
-
-/********************************************************
- resolve a name of format \\server_name or \\ipaddress
- into a name. also, cut the \\ from the front for us.
-*********************************************************/
-
-BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
- struct in_addr *ip)
-{
- BOOL ret;
- const char *sv_name = srv_name;
-
- DEBUG(10,("resolve_srv_name: %s\n", srv_name));
-
- if (srv_name == NULL || strequal("\\\\.", srv_name))
- {
- extern pstring global_myname;
- fstrcpy(dest_host, global_myname);
- ip = interpret_addr2("127.0.0.1");
- return True;
- }
-
- if (strnequal("\\\\", srv_name, 2))
- {
- sv_name = &srv_name[2];
- }
-
- fstrcpy(dest_host, sv_name);
- /* treat the '*' name specially - it is a magic name for the PDC */
- if (strcmp(dest_host,"*") == 0) {
- extern pstring global_myname;
- ret = resolve_name(lp_workgroup(), ip, 0x1B);
- lookup_dc_name(global_myname, lp_workgroup(), ip, dest_host);
- } else {
- ret = resolve_name(dest_host, ip, 0x20);
- }
-
- if (is_ipaddress(dest_host))
- {
- fstrcpy(dest_host, "*SMBSERVER");
- }
-
- return ret;
-}
-
-
/********************************************************
Find the IP address of the master browser or DMB for a workgroup.
*********************************************************/
@@ -1269,14 +1157,6 @@ NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
#endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
}
-/********************************************************
- Get the IP address list of the Local Master Browsers
- ********************************************************/
-
-BOOL get_lmb_list(struct in_addr **ip_list, int *count)
-{
- return internal_resolve_name( MSBROWSE, 0x1, ip_list, count);
-}
/********************************************************
Get the IP address list of the PDC/BDC's of a Domain.
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index 9a37b4252a..ba0d8cee5d 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -1045,7 +1045,7 @@ BOOL match_mailslot_name(struct packet_struct *p, char *mailslot_name)
/****************************************************************************
return the number of bits that match between two 4 character buffers
***************************************************************************/
-static int matching_bits(uchar *p1, uchar *p2)
+int matching_quad_bits(uchar *p1, uchar *p2)
{
int i, j, ret = 0;
for (i=0; i<4; i++) {
@@ -1071,7 +1071,7 @@ compare two query reply records
***************************************************************************/
static int name_query_comp(uchar *p1, uchar *p2)
{
- return matching_bits(p2+2, sort_ip) - matching_bits(p1+2, sort_ip);
+ return matching_quad_bits(p2+2, sort_ip) - matching_quad_bits(p1+2, sort_ip);
}
/****************************************************************************
diff --git a/source3/libsmb/nterr.c b/source3/libsmb/nterr.c
index faf5147fe2..e2da6318e1 100644
--- a/source3/libsmb/nterr.c
+++ b/source3/libsmb/nterr.c
@@ -534,6 +534,7 @@ nt_err_code_struct nt_errs[] =
{ "NT_STATUS_QUOTA_LIST_INCONSISTENT", NT_STATUS_QUOTA_LIST_INCONSISTENT },
{ "NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE },
{ "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES },
+ { "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES },
{ "STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED },
{ NULL, NT_STATUS(0) }
};
diff --git a/source3/libsmb/pwd_cache.c b/source3/libsmb/pwd_cache.c
index 7d1185d9a7..fc0602507a 100644
--- a/source3/libsmb/pwd_cache.c
+++ b/source3/libsmb/pwd_cache.c
@@ -24,7 +24,7 @@
Initialises a password structure.
****************************************************************************/
-void pwd_init(struct pwd_info *pwd)
+static void pwd_init(struct pwd_info *pwd)
{
memset((char *)pwd->password , '\0', sizeof(pwd->password ));
memset((char *)pwd->smb_lm_pwd, '\0', sizeof(pwd->smb_lm_pwd));
@@ -38,89 +38,21 @@ void pwd_init(struct pwd_info *pwd)
}
/****************************************************************************
- Returns NULL password flag.
-****************************************************************************/
-
-BOOL pwd_is_nullpwd(const struct pwd_info *pwd)
-{
- return pwd->null_pwd;
-}
-
-/****************************************************************************
- Compares two passwords. hmm, not as trivial as expected. hmm.
-****************************************************************************/
-
-BOOL pwd_compare(const struct pwd_info *pwd1, const struct pwd_info *pwd2)
-{
- if (pwd1->cleartext && pwd2->cleartext) {
- if (strequal(pwd1->password, pwd2->password))
- return True;
- }
- if (pwd1->null_pwd && pwd2->null_pwd)
- return True;
-
- if (!pwd1->null_pwd && !pwd2->null_pwd &&
- !pwd1->cleartext && !pwd2->cleartext) {
-#ifdef DEBUG_PASSWORD
- DEBUG(100,("pwd compare: nt#\n"));
- dump_data(100, pwd1->smb_nt_pwd, 16);
- dump_data(100, pwd2->smb_nt_pwd, 16);
-#endif
- if (memcmp(pwd1->smb_nt_pwd, pwd2->smb_nt_pwd, 16) == 0)
- return True;
-#ifdef DEBUG_PASSWORD
- DEBUG(100,("pwd compare: lm#\n"));
- dump_data(100, pwd1->smb_lm_pwd, 16);
- dump_data(100, pwd2->smb_lm_pwd, 16);
-#endif
- if (memcmp(pwd1->smb_lm_pwd, pwd2->smb_lm_pwd, 16) == 0)
- return True;
- }
- return False;
-}
-
-/****************************************************************************
- Reads a password.
+ Makes lm and nt hashed passwords.
****************************************************************************/
-void pwd_read(struct pwd_info *pwd, char *passwd_report, BOOL do_encrypt)
+static void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr)
{
- /* grab a password */
- char *user_pass;
+ pstring dos_passwd;
pwd_init(pwd);
- user_pass = (char*)getpass(passwd_report);
-
- /*
- * Do not assume that an empty string is a NULL password.
- * If you do this will break the session key generation for
- * and account with an emtpy password. If you wish to use
- * a NULL password, use the -N option to smbclient and rpcclient
- * --jerry
- */
-#if 0
- if (user_pass == NULL || user_pass[0] == 0)
- pwd_set_nullpwd(pwd);
- else if (do_encrypt)
-#endif
- if (do_encrypt)
- pwd_make_lm_nt_16(pwd, user_pass);
- else
- pwd_set_cleartext(pwd, user_pass);
-}
-
-/****************************************************************************
- Stores a cleartext password.
-****************************************************************************/
-
-void pwd_set_nullpwd(struct pwd_info *pwd)
-{
- pwd_init(pwd);
+ push_ascii_pstring(dos_passwd, clr);
+ nt_lm_owf_gen(dos_passwd, pwd->smb_nt_pwd, pwd->smb_lm_pwd);
+ pwd->null_pwd = False;
pwd->cleartext = False;
- pwd->null_pwd = True;
- pwd->crypted = False;
+ pwd->crypted = False;
}
/****************************************************************************
@@ -141,7 +73,7 @@ void pwd_set_cleartext(struct pwd_info *pwd, char *clr)
Gets a cleartext password.
****************************************************************************/
-void pwd_get_cleartext(struct pwd_info *pwd, char *clr)
+void pwd_get_cleartext(struct pwd_info *pwd, fstring clr)
{
if (pwd->cleartext)
fstrcpy(clr, pwd->password);
@@ -151,29 +83,6 @@ void pwd_get_cleartext(struct pwd_info *pwd, char *clr)
}
/****************************************************************************
- Stores lm and nt hashed passwords.
-****************************************************************************/
-
-void pwd_set_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16])
-{
- pwd_init(pwd);
-
- if (lm_pwd)
- memcpy(pwd->smb_lm_pwd, lm_pwd, 16);
- else
- memset((char *)pwd->smb_lm_pwd, '\0', 16);
-
- if (nt_pwd)
- memcpy(pwd->smb_nt_pwd, nt_pwd, 16);
- else
- memset((char *)pwd->smb_nt_pwd, '\0', 16);
-
- pwd->null_pwd = False;
- pwd->cleartext = False;
- pwd->crypted = False;
-}
-
-/****************************************************************************
Gets lm and nt hashed passwords.
****************************************************************************/
@@ -186,24 +95,6 @@ void pwd_get_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16])
}
/****************************************************************************
- Makes lm and nt hashed passwords.
-****************************************************************************/
-
-void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr)
-{
- pstring dos_passwd;
-
- pwd_init(pwd);
-
- push_ascii_pstring(dos_passwd, clr);
-
- nt_lm_owf_gen(dos_passwd, pwd->smb_nt_pwd, pwd->smb_lm_pwd);
- pwd->null_pwd = False;
- pwd->cleartext = False;
- pwd->crypted = False;
-}
-
-/****************************************************************************
Makes lm and nt OWF crypts.
****************************************************************************/
@@ -247,3 +138,13 @@ void pwd_get_lm_nt_owf(struct pwd_info *pwd, uchar lm_owf[24], uchar nt_owf[24])
if (nt_owf != NULL)
memcpy(nt_owf, pwd->smb_nt_owf, 24);
}
+
+
+
+
+
+
+
+
+
+
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index 6fa8de418a..95434d0ae4 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/libsmb/smbencrypt.c
@@ -26,18 +26,14 @@
/*
This implements the X/Open SMB password encryption
- It takes a password, a 8 byte "crypt key" and puts 24 bytes of
- encrypted password into p24 */
-void SMBencrypt(const uchar *passwd, const uchar *c8, uchar *p24)
+ 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)
{
- uchar p14[15], p21[21];
+ uchar p21[21];
memset(p21,'\0',21);
- memset(p14,'\0',14);
- StrnCpy((char *)p14,(const char *)passwd,14);
-
- strupper((char *)p14);
- E_P16(p14, p21);
+ E_deshash(passwd, p21);
SMBOWFencrypt(p21, c8, p24);
@@ -49,61 +45,74 @@ void SMBencrypt(const uchar *passwd, const uchar *c8, uchar *p24)
#endif
}
-/*
+/**
* Creates the MD4 Hash of the users password in NT UNICODE.
+ * @param passwd password in 'unix' charset.
+ * @param p16 return password hashed with md4, caller allocated 16 byte buffer
*/
-void E_md4hash(const uchar *passwd, uchar *p16)
+void E_md4hash(const char *passwd, uchar p16[16])
{
int len;
smb_ucs2_t wpwd[129];
- /* Password cannot be longer than 128 characters */
- len = strlen((const char *)passwd);
- if(len > 128)
- len = 128;
/* Password must be converted to NT unicode - null terminated. */
push_ucs2(NULL, wpwd, (const char *)passwd, 256, STR_UNICODE|STR_NOALIGN|STR_TERMINATE);
/* Calculate length in bytes */
len = strlen_w(wpwd) * sizeof(int16);
mdfour(p16, (unsigned char *)wpwd, len);
+ ZERO_STRUCT(wpwd);
}
-/* Does both the NT and LM owfs of a user's password */
-void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16])
+/**
+ * Creates the MD4 Hash of the users password in NT UNICODE.
+ * @param passwd password in 'unix' charset.
+ * @param p16 return password hashed with md4, caller allocated 16 byte buffer
+ */
+
+void E_deshash(const char *passwd, uchar p16[16])
{
- char passwd[514];
+ uchar dospwd[15]; /* Password must not be > 14 chars long. */
+ ZERO_STRUCT(dospwd);
+ ZERO_STRUCTP(p16);
+
+ /* Password must be converted to DOS charset - null terminated. */
+ push_ascii(dospwd, (const char *)passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE);
- memset(passwd,'\0',514);
- safe_strcpy( passwd, pwd, sizeof(passwd)-1);
+ E_P16(dospwd, p16);
+
+ ZERO_STRUCT(dospwd);
+}
+/**
+ * Creates the MD4 and DES (LM) Hash of the users password.
+ * MD4 is of the NT Unicode, DES is of the DOS UPPERCASE password.
+ * @param passwd password in 'unix' charset.
+ * @param nt_p16 return password hashed with md4, caller allocated 16 byte buffer
+ * @param p16 return password hashed with des, caller allocated 16 byte buffer
+ */
+
+/* Does both the NT and LM owfs of a user's password */
+void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16])
+{
/* Calculate the MD4 hash (NT compatible) of the password */
memset(nt_p16, '\0', 16);
- E_md4hash((uchar *)passwd, nt_p16);
+ E_md4hash(pwd, nt_p16);
#ifdef DEBUG_PASSWORD
DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n"));
- dump_data(120, passwd, strlen(passwd));
+ dump_data(120, pwd, strlen(pwd));
dump_data(100, (char *)nt_p16, 16);
#endif
- /* Mangle the passwords into Lanman format */
- passwd[14] = '\0';
- strupper(passwd);
-
- /* Calculate the SMB (lanman) hash functions of the password */
-
- memset(p16, '\0', 16);
- E_P16((uchar *) passwd, (uchar *)p16);
+ E_deshash(pwd, (uchar *)p16);
#ifdef DEBUG_PASSWORD
DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n"));
- dump_data(120, passwd, strlen(passwd));
+ dump_data(120, pwd, strlen(pwd));
dump_data(100, (char *)p16, 16);
#endif
- /* clear out local copy of user's password (just being paranoid). */
- memset(passwd, '\0', sizeof(passwd));
}
/* Does both the NTLMv2 owfs of a user's password */
@@ -322,22 +331,56 @@ BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
#endif
return True;
+}
+/***********************************************************
+ SMB signing - setup the MAC key.
+************************************************************/
+
+void cli_calculate_mac_key(struct cli_state *cli, const unsigned char *ntpasswd, const uchar resp[24])
+{
+ /* Get first 16 bytes. */
+ E_md4hash(ntpasswd,&cli->sign_info.mac_key[0]);
+ memcpy(&cli->sign_info.mac_key[16],resp,24);
+ cli->sign_info.mac_key_len = 40;
+ cli->sign_info.use_smb_signing = True;
+
+ /* These calls are INCONPATIBLE with SMB signing */
+ cli->readbraw_supported = False;
+ cli->writebraw_supported = False;
+
+ /* Reset the sequence number in case we had a previous (aborted) attempt */
+ cli->sign_info.send_seq_num = 0;
}
-/* Calculate the NT owfs of a user's password */
-void nt_owf_genW(const UNISTR2 *pwd, uchar nt_p16[16])
+/***********************************************************
+ SMB signing - calculate a MAC to send.
+************************************************************/
+
+void cli_caclulate_sign_mac(struct cli_state *cli)
{
- char buf[512];
- int i;
+ unsigned char calc_md5_mac[16];
+ struct MD5Context md5_ctx;
- for (i = 0; i < MIN(pwd->uni_str_len, sizeof(buf) / 2); i++)
- {
- SIVAL(buf, i * 2, pwd->buffer[i]);
+ if (!cli->sign_info.use_smb_signing) {
+ return;
}
- /* Calculate the MD4 hash (NT compatible) of the password */
- mdfour(nt_p16, (const unsigned char *)buf, pwd->uni_str_len * 2);
- /* clear out local copy of user's password (just being paranoid). */
- ZERO_STRUCT(buf);
+ /*
+ * Firstly put the sequence number into the first 4 bytes.
+ * and zero out the next 4 bytes.
+ */
+ SIVAL(cli->outbuf, smb_ss_field, cli->sign_info.send_seq_num);
+ SIVAL(cli->outbuf, smb_ss_field + 4, 0);
+
+ /* Calculate the 16 byte MAC and place first 8 bytes into the field. */
+ MD5Init(&md5_ctx);
+ MD5Update(&md5_ctx, cli->sign_info.mac_key, cli->sign_info.mac_key_len);
+ MD5Update(&md5_ctx, cli->outbuf + 4, smb_len(cli->outbuf));
+ MD5Final(calc_md5_mac, &md5_ctx);
+
+ memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
+ cli->sign_info.send_seq_num++;
+ cli->sign_info.reply_seq_num = cli->sign_info.send_seq_num;
+ cli->sign_info.send_seq_num++;
}
diff --git a/source3/libsmb/trust_passwd.c b/source3/libsmb/trust_passwd.c
index 51ffa1dd95..3b77f7330e 100644
--- a/source3/libsmb/trust_passwd.c
+++ b/source3/libsmb/trust_passwd.c
@@ -39,7 +39,7 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
SEC_CHAN_WKSTA : SEC_CHAN_BDC, orig_trust_passwd_hash);
if (!NT_STATUS_IS_OK(result)) {
- DEBUG(0,("just_change_the_password: unable to setup creds (%s)!\n",
+ DEBUG(1,("just_change_the_password: unable to setup creds (%s)!\n",
nt_errstr(result)));
return result;
}
@@ -71,13 +71,14 @@ NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx
str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
new_trust_passwd = talloc_strdup(mem_ctx, str);
- E_md4hash((uchar *)new_trust_passwd, new_trust_passwd_hash);
+ E_md4hash(new_trust_passwd, new_trust_passwd_hash);
nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
new_trust_passwd_hash);
if (NT_STATUS_IS_OK(nt_status)) {
- DEBUG(3,("%s : change_trust_account_password: Changed password.\n", timestring(False)));
+ DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
+ timestring(False)));
/*
* Return the result of trying to write the new password
* back into the trust account file.
@@ -96,7 +97,8 @@ NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx
already setup the connection to the NETLOGON pipe
**********************************************************/
-NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx, char *domain)
+NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ char *domain)
{
unsigned char old_trust_passwd_hash[16];
char *up_domain;
diff --git a/source3/libsmb/unexpected.c b/source3/libsmb/unexpected.c
index f74a05f75f..4fc3914481 100644
--- a/source3/libsmb/unexpected.c
+++ b/source3/libsmb/unexpected.c
@@ -46,7 +46,7 @@ void unexpected_packet(struct packet_struct *p)
int len=0;
if (!tdbd) {
- tdbd = tdb_open_log(lock_path("unexpected.tdb"), 1,
+ tdbd = tdb_open_log(lock_path("unexpected.tdb"), 0,
TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
O_RDWR | O_CREAT, 0644);
if (!tdbd) {