summaryrefslogtreecommitdiff
path: root/source3/client
diff options
context:
space:
mode:
Diffstat (limited to 'source3/client')
-rw-r--r--source3/client/cifs.spnego.c63
-rw-r--r--source3/client/client.c356
-rw-r--r--source3/client/clitar.c71
-rw-r--r--source3/client/dnsbrowse.c237
-rw-r--r--source3/client/mount.cifs.c98
-rw-r--r--source3/client/smbmnt.c5
-rw-r--r--source3/client/smbmount.c4
-rw-r--r--source3/client/smbspool.c21
8 files changed, 724 insertions, 131 deletions
diff --git a/source3/client/cifs.spnego.c b/source3/client/cifs.spnego.c
index caa22276c4..d10d19da96 100644
--- a/source3/client/cifs.spnego.c
+++ b/source3/client/cifs.spnego.c
@@ -3,11 +3,13 @@
* Copyright (C) Igor Mammedov (niallain@gmail.com) 2007
*
* Used by /sbin/request-key for handling
-* cifs upcall for kerberos authorization of access to share.
+* cifs upcall for kerberos authorization of access to share and
+* cifs upcall for DFS srver name resolving (IPv4/IPv6 aware).
* You should have keyutils installed and add following line to
* /etc/request-key.conf file
create cifs.spnego * * /usr/local/sbin/cifs.spnego [-v][-c] %k
+create cifs.resolver * * /usr/local/sbin/cifs.spnego [-v] %k
* 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
@@ -27,7 +29,7 @@ create cifs.spnego * * /usr/local/sbin/cifs.spnego [-v][-c] %k
#include "cifs_spnego.h"
-const char* CIFSSPNEGO_VERSION="1.0";
+const char *CIFSSPNEGO_VERSION = "1.1";
static const char *prog = "cifs.spnego";
typedef enum _secType {
KRB5,
@@ -146,6 +148,58 @@ int decode_key_description(const char *desc, int *ver, secType_t * sec,
return retval;
}
+int cifs_resolver(const key_serial_t key, const char *key_descr)
+{
+ int c;
+ struct addrinfo *addr;
+ char ip[INET6_ADDRSTRLEN];
+ void *p;
+ const char *keyend = key_descr;
+ /* skip next 4 ';' delimiters to get to description */
+ for (c = 1; c <= 4; c++) {
+ keyend = index(keyend+1, ';');
+ if (!keyend) {
+ syslog(LOG_WARNING, "invalid key description: %s",
+ key_descr);
+ return 1;
+ }
+ }
+ keyend++;
+
+ /* resolve name to ip */
+ c = getaddrinfo(keyend, NULL, NULL, &addr);
+ if (c) {
+ syslog(LOG_WARNING, "unable to resolve hostname: %s [%s]",
+ keyend, gai_strerror(c));
+ return 1;
+ }
+
+ /* conver ip to string form */
+ if (addr->ai_family == AF_INET) {
+ p = &(((struct sockaddr_in *)addr->ai_addr)->sin_addr);
+ } else {
+ p = &(((struct sockaddr_in6 *)addr->ai_addr)->sin6_addr);
+ }
+ if (!inet_ntop(addr->ai_family, p, ip, sizeof(ip))) {
+ syslog(LOG_WARNING, "%s: inet_ntop: %s",
+ __FUNCTION__, strerror(errno));
+ freeaddrinfo(addr);
+ return 1;
+ }
+
+ /* setup key */
+ c = keyctl_instantiate(key, ip, strlen(ip)+1, 0);
+ if (c == -1) {
+ syslog(LOG_WARNING, "%s: keyctl_instantiate: %s",
+ __FUNCTION__, strerror(errno));
+ freeaddrinfo(addr);
+ return 1;
+ }
+
+ freeaddrinfo(addr);
+ return 0;
+}
+
int main(const int argc, char *const argv[])
{
struct cifs_spnego_msg *keydata = NULL;
@@ -199,6 +253,11 @@ int main(const int argc, char *const argv[])
goto out;
}
+ if (strncmp(buf, "cifs.resolver", sizeof("cifs.resolver")-1) == 0) {
+ rc = cifs_resolver(key, buf);
+ goto out;
+ }
+
rc = decode_key_description(buf, &kernel_upcall_version, &sectype,
&hostname, &uid);
if ((rc & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
diff --git a/source3/client/client.c b/source3/client/client.c
index d59af9e6cf..c934310491 100644
--- a/source3/client/client.c
+++ b/source3/client/client.c
@@ -28,16 +28,20 @@
#define REGISTER 0
#endif
+extern int do_smb_browse(void); /* mDNS browsing */
+
extern bool AllowDebugChange;
extern bool override_logfile;
extern char tar_type;
extern bool in_client;
+
static int port = 0;
static char *service;
static char *desthost;
static char *calling_name;
static bool grepable = false;
static char *cmdstr = NULL;
+static const char *cmd_ptr = NULL;
static int io_bufsize = 64512;
@@ -89,6 +93,9 @@ static unsigned int put_total_time_ms = 0;
/* totals globals */
static double dir_total;
+/* encrypted state. */
+static bool smb_encrypt;
+
/* root cli_state connection */
struct cli_state *cli;
@@ -422,7 +429,7 @@ static int cmd_cd(void)
char *buf = NULL;
int rc = 0;
- if (next_token_nr_talloc(talloc_tos(), NULL, &buf,NULL)) {
+ if (next_token_talloc(talloc_tos(), &cmd_ptr, &buf,NULL)) {
rc = do_cd(buf);
} else {
d_printf("Current directory is %s\n",client_get_cur_dir());
@@ -860,7 +867,7 @@ static int cmd_dir(void)
return 1;
}
- if (next_token_nr_talloc(ctx, NULL,&buf,NULL)) {
+ if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
string_replace(buf,'/','\\');
if (*buf == CLI_DIRSEP_CHAR) {
mask = talloc_strdup(ctx, buf + 1);
@@ -912,7 +919,7 @@ static int cmd_du(void)
}
}
- if (next_token_nr_talloc(ctx, NULL,&buf,NULL)) {
+ if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
string_replace(buf,'/','\\');
if (*buf == CLI_DIRSEP_CHAR) {
mask = talloc_strdup(ctx, buf);
@@ -938,8 +945,8 @@ static int cmd_echo(void)
char *num;
char *data;
- if (!next_token_nr_talloc(ctx, NULL, &num, NULL)
- || !next_token_nr_talloc(ctx, NULL, &data, NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL)
+ || !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) {
d_printf("echo <num> <data>\n");
return 1;
}
@@ -1113,7 +1120,7 @@ static int cmd_get(void)
return 1;
}
- if (!next_token_nr_talloc(ctx, NULL,&fname,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
d_printf("get <filename> [localname]\n");
return 1;
}
@@ -1126,7 +1133,7 @@ static int cmd_get(void)
return 1;
}
- next_token_nr_talloc(ctx, NULL,&lname,NULL);
+ next_token_talloc(ctx, &cmd_ptr,&lname,NULL);
if (!lname) {
lname = fname;
}
@@ -1274,7 +1281,7 @@ static int cmd_more(void)
}
close(fd);
- if (!next_token_nr_talloc(ctx,NULL,&fname,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
d_printf("more <filename>\n");
unlink(lname);
return 1;
@@ -1322,7 +1329,7 @@ static int cmd_mget(void)
abort_mget = false;
- while (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
mget_mask = talloc_strdup(ctx, client_get_cur_dir());
if (!mget_mask) {
return 1;
@@ -1439,7 +1446,7 @@ static int cmd_mkdir(void)
return 1;
}
- if (!next_token_nr_talloc(ctx, NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
if (!recurse) {
d_printf("mkdir <dirname>\n");
}
@@ -1456,6 +1463,7 @@ static int cmd_mkdir(void)
struct cli_state *targetcli;
char *targetname = NULL;
char *p = NULL;
+ char *saveptr;
ddir2 = talloc_strdup(ctx, "");
if (!ddir2) {
@@ -1471,7 +1479,7 @@ static int cmd_mkdir(void)
return 1;
}
trim_char(ddir,'.','\0');
- p = strtok(ddir,"/\\");
+ p = strtok_r(ddir, "/\\", &saveptr);
while (p) {
ddir2 = talloc_asprintf_append(ddir2, p);
if (!ddir2) {
@@ -1484,7 +1492,7 @@ static int cmd_mkdir(void)
if (!ddir2) {
return 1;
}
- p = strtok(NULL,"/\\");
+ p = strtok_r(NULL, "/\\", &saveptr);
}
} else {
do_mkdir(mask);
@@ -1508,7 +1516,7 @@ static int cmd_altname(void)
return 1;
}
- if (!next_token_nr_talloc(ctx, NULL, &buf, NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
d_printf("altname <file>\n");
return 1;
}
@@ -1521,6 +1529,92 @@ static int cmd_altname(void)
}
/****************************************************************************
+ Show all info we can get
+****************************************************************************/
+
+static int do_allinfo(const char *name)
+{
+ fstring altname;
+ struct timespec b_time, a_time, m_time, c_time;
+ SMB_OFF_T size;
+ uint16_t mode;
+ SMB_INO_T ino;
+ NTTIME tmp;
+ unsigned int num_streams;
+ struct stream_struct *streams;
+ unsigned int i;
+
+ if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
+ d_printf("%s getting alt name for %s\n",
+ cli_errstr(cli),name);
+ return false;
+ }
+ d_printf("altname: %s\n", altname);
+
+ if (!cli_qpathinfo2(cli, name, &b_time, &a_time, &m_time, &c_time,
+ &size, &mode, &ino)) {
+ d_printf("%s getting pathinfo for %s\n",
+ cli_errstr(cli),name);
+ return false;
+ }
+
+ unix_timespec_to_nt_time(&tmp, b_time);
+ d_printf("create_time: %s\n", nt_time_string(talloc_tos(), tmp));
+
+ unix_timespec_to_nt_time(&tmp, a_time);
+ d_printf("access_time: %s\n", nt_time_string(talloc_tos(), tmp));
+
+ unix_timespec_to_nt_time(&tmp, m_time);
+ d_printf("write_time: %s\n", nt_time_string(talloc_tos(), tmp));
+
+ unix_timespec_to_nt_time(&tmp, c_time);
+ d_printf("change_time: %s\n", nt_time_string(talloc_tos(), tmp));
+
+ if (!cli_qpathinfo_streams(cli, name, talloc_tos(), &num_streams,
+ &streams)) {
+ d_printf("%s getting streams for %s\n",
+ cli_errstr(cli),name);
+ return false;
+ }
+
+ for (i=0; i<num_streams; i++) {
+ d_printf("stream: [%s], %lld bytes\n", streams[i].name,
+ (unsigned long long)streams[i].size);
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ Show all info we can get
+****************************************************************************/
+
+static int cmd_allinfo(void)
+{
+ TALLOC_CTX *ctx = talloc_tos();
+ char *name;
+ char *buf;
+
+ name = talloc_strdup(ctx, client_get_cur_dir());
+ if (!name) {
+ return 1;
+ }
+
+ if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
+ d_printf("allinfo <file>\n");
+ return 1;
+ }
+ name = talloc_asprintf_append(name, buf);
+ if (!name) {
+ return 1;
+ }
+
+ do_allinfo(name);
+
+ return 0;
+}
+
+/****************************************************************************
Put a single file.
****************************************************************************/
@@ -1674,12 +1768,12 @@ static int cmd_put(void)
return 1;
}
- if (!next_token_nr_talloc(ctx,NULL,&lname,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&lname,NULL)) {
d_printf("put <filename>\n");
return 1;
}
- if (next_token_nr_talloc(ctx, NULL,&buf,NULL)) {
+ if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
rname = talloc_asprintf_append(rname, buf);
} else {
rname = talloc_asprintf_append(rname, lname);
@@ -1759,7 +1853,7 @@ static int cmd_select(void)
{
TALLOC_CTX *ctx = talloc_tos();
char *new_fs = NULL;
- next_token_nr_talloc(ctx, NULL,&new_fs,NULL)
+ next_token_talloc(ctx, &cmd_ptr,&new_fs,NULL)
;
if (new_fs) {
client_set_fileselection(new_fs);
@@ -1845,7 +1939,7 @@ static int cmd_mput(void)
TALLOC_CTX *ctx = talloc_tos();
char *p = NULL;
- while (next_token_nr_talloc(ctx, NULL,&p,NULL)) {
+ while (next_token_talloc(ctx, &cmd_ptr,&p,NULL)) {
int ret;
struct file_list *temp_list;
char *quest, *lname, *rname;
@@ -1956,14 +2050,14 @@ static int cmd_cancel(void)
char *buf = NULL;
int job;
- if (!next_token_nr_talloc(ctx, NULL, &buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr, &buf,NULL)) {
d_printf("cancel <jobid> ...\n");
return 1;
}
do {
job = atoi(buf);
do_cancel(job);
- } while (next_token_nr_talloc(ctx,NULL,&buf,NULL));
+ } while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL));
return 0;
}
@@ -1979,7 +2073,7 @@ static int cmd_print(void)
char *rname = NULL;
char *p = NULL;
- if (!next_token_nr_talloc(ctx, NULL, &lname,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr, &lname,NULL)) {
d_printf("print <filename>\n");
return 1;
}
@@ -2075,7 +2169,7 @@ static int cmd_del(void)
if (!mask) {
return 1;
}
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("del <filename>\n");
return 1;
}
@@ -2101,14 +2195,14 @@ static int cmd_wdel(void)
struct cli_state *targetcli;
char *targetname = NULL;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("wdel 0x<attrib> <wcard>\n");
return 1;
}
attribute = (uint16)strtol(buf, (char **)NULL, 16);
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("wdel 0x<attrib> <wcard>\n");
return 1;
}
@@ -2143,7 +2237,7 @@ static int cmd_open(void)
struct cli_state *targetcli;
int fnum;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("open <filename>\n");
return 1;
}
@@ -2174,6 +2268,49 @@ static int cmd_open(void)
return 0;
}
+static int cmd_posix_encrypt(void)
+{
+ TALLOC_CTX *ctx = talloc_tos();
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+
+ if (cli->use_kerberos) {
+ status = cli_gss_smb_encryption_start(cli);
+ } else {
+ char *domain = NULL;
+ char *user = NULL;
+ char *password = NULL;
+
+ if (!next_token_talloc(ctx, &cmd_ptr,&domain,NULL)) {
+ d_printf("posix_encrypt domain user password\n");
+ return 1;
+ }
+
+ if (!next_token_talloc(ctx, &cmd_ptr,&user,NULL)) {
+ d_printf("posix_encrypt domain user password\n");
+ return 1;
+ }
+
+ if (!next_token_talloc(ctx, &cmd_ptr,&password,NULL)) {
+ d_printf("posix_encrypt domain user password\n");
+ return 1;
+ }
+
+ status = cli_raw_ntlm_smb_encryption_start(cli,
+ user,
+ password,
+ domain);
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("posix_encrypt failed with error %s\n", nt_errstr(status));
+ } else {
+ d_printf("encryption on\n");
+ smb_encrypt = true;
+ }
+
+ return 0;
+}
+
/****************************************************************************
****************************************************************************/
@@ -2187,7 +2324,7 @@ static int cmd_posix_open(void)
mode_t mode;
int fnum;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("posix_open <filename> 0<mode>\n");
return 1;
}
@@ -2199,7 +2336,7 @@ static int cmd_posix_open(void)
return 1;
}
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("posix_open <filename> 0<mode>\n");
return 1;
}
@@ -2235,7 +2372,7 @@ static int cmd_posix_mkdir(void)
mode_t mode;
int fnum;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("posix_mkdir <filename> 0<mode>\n");
return 1;
}
@@ -2247,7 +2384,7 @@ static int cmd_posix_mkdir(void)
return 1;
}
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("posix_mkdir <filename> 0<mode>\n");
return 1;
}
@@ -2275,7 +2412,7 @@ static int cmd_posix_unlink(void)
char *targetname = NULL;
struct cli_state *targetcli;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("posix_unlink <filename>\n");
return 1;
}
@@ -2309,7 +2446,7 @@ static int cmd_posix_rmdir(void)
char *targetname = NULL;
struct cli_state *targetcli;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("posix_rmdir <filename>\n");
return 1;
}
@@ -2341,7 +2478,7 @@ static int cmd_close(void)
char *buf = NULL;
int fnum;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("close <fnum>\n");
return 1;
}
@@ -2420,17 +2557,30 @@ static int cmd_posix(void)
return 1;
}
}
+ if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) {
+ caps = talloc_asprintf_append(caps, "posix_encrypt ");
+ if (!caps) {
+ return 1;
+ }
+ }
+ if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) {
+ caps = talloc_asprintf_append(caps, "mandatory_posix_encrypt ");
+ if (!caps) {
+ return 1;
+ }
+ }
if (*caps && caps[strlen(caps)-1] == ' ') {
caps[strlen(caps)-1] = '\0';
}
+
+ d_printf("Server supports CIFS capabilities %s\n", caps);
+
if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) {
d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli));
return 1;
}
- d_printf("Selecting server supported CIFS capabilities %s\n", caps);
-
if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
CLI_DIRSEP_CHAR = '/';
*CLI_DIRSEP_STR = '/';
@@ -2448,13 +2598,13 @@ static int cmd_lock(void)
enum brl_type lock_type;
int fnum;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
return 1;
}
fnum = atoi(buf);
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
return 1;
}
@@ -2468,14 +2618,14 @@ static int cmd_lock(void)
return 1;
}
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
return 1;
}
start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
return 1;
}
@@ -2496,20 +2646,20 @@ static int cmd_unlock(void)
SMB_BIG_UINT start, len;
int fnum;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("unlock <fnum> <hex-start> <hex-len>\n");
return 1;
}
fnum = atoi(buf);
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("unlock <fnum> <hex-start> <hex-len>\n");
return 1;
}
start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("unlock <fnum> <hex-start> <hex-len>\n");
return 1;
}
@@ -2536,7 +2686,7 @@ static int cmd_rmdir(void)
char *targetname = NULL;
struct cli_state *targetcli;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("rmdir <dirname>\n");
return 1;
}
@@ -2575,8 +2725,8 @@ static int cmd_link(void)
char *targetname = NULL;
struct cli_state *targetcli;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
- !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+ !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
d_printf("link <oldname> <newname>\n");
return 1;
}
@@ -2626,8 +2776,8 @@ static int cmd_symlink(void)
char *targetname = NULL;
struct cli_state *targetcli;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
- !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+ !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
d_printf("symlink <oldname> <newname>\n");
return 1;
}
@@ -2679,8 +2829,8 @@ static int cmd_chmod(void)
struct cli_state *targetcli;
mode_t mode;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
- !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+ !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
d_printf("chmod mode file\n");
return 1;
}
@@ -2835,7 +2985,7 @@ static int cmd_getfacl(void)
uint16 num_dir_acls = 0;
uint16 i;
- if (!next_token_nr_talloc(ctx,NULL,&name,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
d_printf("getfacl filename\n");
return 1;
}
@@ -3001,7 +3151,7 @@ static int cmd_stat(void)
SMB_STRUCT_STAT sbuf;
struct tm *lt;
- if (!next_token_nr_talloc(ctx,NULL,&name,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
d_printf("stat file\n");
return 1;
}
@@ -3097,9 +3247,9 @@ static int cmd_chown(void)
struct cli_state *targetcli;
char *targetname = NULL;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
- !next_token_nr_talloc(ctx,NULL,&buf2,NULL) ||
- !next_token_nr_talloc(ctx,NULL,&buf3,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+ !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL) ||
+ !next_token_talloc(ctx, &cmd_ptr,&buf3,NULL)) {
d_printf("chown uid gid file\n");
return 1;
}
@@ -3146,8 +3296,8 @@ static int cmd_rename(void)
char *targetsrc;
char *targetdest;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
- !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+ !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
d_printf("rename <src> <dest>\n");
return 1;
}
@@ -3221,8 +3371,8 @@ static int cmd_hardlink(void)
struct cli_state *targetcli;
char *targetname;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
- !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+ !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
d_printf("hardlink <src> <dest>\n");
return 1;
}
@@ -3278,7 +3428,7 @@ static int cmd_newer(void)
bool ok;
SMB_STRUCT_STAT sbuf;
- ok = next_token_nr_talloc(ctx,NULL,&buf,NULL);
+ ok = next_token_talloc(ctx, &cmd_ptr,&buf,NULL);
if (ok && (sys_stat(buf,&sbuf) == 0)) {
newer_than = sbuf.st_mtime;
DEBUG(1,("Getting files newer than %s",
@@ -3304,7 +3454,7 @@ static int cmd_archive(void)
TALLOC_CTX *ctx = talloc_tos();
char *buf;
- if (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
archive_level = atoi(buf);
} else {
d_printf("Archive level is %d\n",archive_level);
@@ -3383,7 +3533,7 @@ static int cmd_lcd(void)
char *buf;
char *d;
- if (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
chdir(buf);
}
d = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
@@ -3414,7 +3564,7 @@ static int cmd_reget(void)
return 1;
}
- if (!next_token_nr_talloc(ctx, NULL, &fname, NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr, &fname, NULL)) {
d_printf("reget <filename>\n");
return 1;
}
@@ -3428,7 +3578,7 @@ static int cmd_reget(void)
}
local_name = fname;
- next_token_nr_talloc(ctx, NULL, &p, NULL);
+ next_token_talloc(ctx, &cmd_ptr, &p, NULL);
if (p) {
local_name = p;
}
@@ -3456,7 +3606,7 @@ static int cmd_reput(void)
return 1;
}
- if (!next_token_nr_talloc(ctx, NULL, &local_name, NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr, &local_name, NULL)) {
d_printf("reput <filename>\n");
return 1;
}
@@ -3466,7 +3616,7 @@ static int cmd_reput(void)
return 1;
}
- if (next_token_nr_talloc(ctx, NULL, &buf, NULL)) {
+ if (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
remote_name = talloc_asprintf_append(remote_name,
buf);
} else {
@@ -3640,7 +3790,7 @@ static int cmd_vuid(void)
TALLOC_CTX *ctx = talloc_tos();
char *buf;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("Current VUID is %d\n", cli->vuid);
return 0;
}
@@ -3658,12 +3808,12 @@ static int cmd_logon(void)
TALLOC_CTX *ctx = talloc_tos();
char *l_username, *l_password;
- if (!next_token_nr_talloc(ctx,NULL,&l_username,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&l_username,NULL)) {
d_printf("logon <username> [<password>]\n");
return 0;
}
- if (!next_token_nr_talloc(ctx,NULL,&l_password,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&l_password,NULL)) {
char *pass = getpass("Password: ");
if (pass) {
l_password = talloc_strdup(ctx,pass);
@@ -3726,17 +3876,29 @@ int cmd_iosize(void)
char *buf;
int iosize;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
- d_printf("iosize <n> or iosize 0x<n>. "
- "Minimum is 16384 (0x4000), "
- "max is 16776960 (0xFFFF00)\n");
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
+ if (!smb_encrypt) {
+ d_printf("iosize <n> or iosize 0x<n>. "
+ "Minimum is 16384 (0x4000), "
+ "max is 16776960 (0xFFFF00)\n");
+ } else {
+ d_printf("iosize <n> or iosize 0x<n>. "
+ "(Encrypted connection) ,"
+ "Minimum is 16384 (0x4000), "
+ "max is 130048 (0x1FC00)\n");
+ }
return 1;
}
iosize = strtol(buf,NULL,0);
- if (iosize < 0 || iosize > 0xFFFF00) {
+ if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) {
+ d_printf("iosize out of range for encrypted "
+ "connection (min = 16384 (0x4000), "
+ "max = 130048 (0x1FC00)");
+ return 1;
+ } else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) {
d_printf("iosize out of range (min = 16384 (0x4000), "
- "max = 16776960 (0x0xFFFF00)");
+ "max = 16776960 (0xFFFF00)");
return 1;
}
@@ -3764,6 +3926,8 @@ static struct {
char compl_args[2]; /* Completion argument info */
} commands[] = {
{"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
+ {"allinfo",cmd_allinfo,"<file> show all available info",
+ {COMPL_NONE,COMPL_NONE}},
{"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
{"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
{"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
@@ -3799,6 +3963,7 @@ static struct {
{"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
{"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
{"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
+ {"posix_encrypt",cmd_posix_encrypt,"<domain> <user> <password> start up transport encryption",{COMPL_REMOTE,COMPL_NONE}},
{"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
{"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
{"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
@@ -3879,7 +4044,7 @@ static int cmd_help(void)
int i=0,j;
char *buf;
- if (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
if ((i = process_tok(buf)) >= 0)
d_printf("HELP %s:\n\t%s\n\n",
commands[i].name,commands[i].description);
@@ -3911,7 +4076,8 @@ static int process_command_string(const char *cmd_in)
/* establish the connection if not already */
if (!cli) {
- cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+ cli = cli_cm_open(talloc_tos(), NULL, desthost,
+ service, true, smb_encrypt);
if (!cli) {
return 1;
}
@@ -3919,7 +4085,6 @@ static int process_command_string(const char *cmd_in)
while (cmd[0] != '\0') {
char *line;
- const char *ptr;
char *p;
char *tok;
int i;
@@ -3934,8 +4099,8 @@ static int process_command_string(const char *cmd_in)
}
/* and get the first part of the command */
- ptr = line;
- if (!next_token_nr_talloc(ctx,&ptr,&tok,NULL)) {
+ cmd_ptr = line;
+ if (!next_token_talloc(ctx, &cmd_ptr,&tok,NULL)) {
continue;
}
@@ -4252,16 +4417,22 @@ static void readline_callback(void)
timeout.tv_usec = 0;
sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
- /* We deliberately use receive_smb instead of
+ /* We deliberately use receive_smb_raw instead of
client_receive_smb as we want to receive
session keepalives and then drop them here.
*/
if (FD_ISSET(cli->fd,&fds)) {
- if (!receive_smb(cli->fd,cli->inbuf,0,&cli->smb_rw_error)) {
+ if (receive_smb_raw(cli->fd,cli->inbuf,0,0,&cli->smb_rw_error) == -1) {
DEBUG(0, ("Read from server failed, maybe it closed the "
"connection\n"));
return;
}
+ if(CVAL(cli->inbuf,0) != SMBkeepalive) {
+ DEBUG(0, ("Read from server "
+ "returned unexpected packet!\n"));
+ return;
+ }
+
goto again;
}
@@ -4279,7 +4450,6 @@ static void readline_callback(void)
static int process_stdin(void)
{
- const char *ptr;
int rc = 0;
while (1) {
@@ -4310,8 +4480,8 @@ static int process_stdin(void)
}
/* and get the first part of the command */
- ptr = line;
- if (!next_token_nr_talloc(frame,&ptr,&tok,NULL)) {
+ cmd_ptr = line;
+ if (!next_token_talloc(frame, &cmd_ptr,&tok,NULL)) {
TALLOC_FREE(frame);
SAFE_FREE(line);
continue;
@@ -4338,7 +4508,8 @@ static int process(const char *base_directory)
{
int rc = 0;
- cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+ cli = cli_cm_open(talloc_tos(), NULL,
+ desthost, service, true, smb_encrypt);
if (!cli) {
return 1;
}
@@ -4367,7 +4538,8 @@ static int process(const char *base_directory)
static int do_host_query(const char *query_host)
{
- cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true);
+ cli = cli_cm_open(talloc_tos(), NULL,
+ query_host, "IPC$", true, smb_encrypt);
if (!cli)
return 1;
@@ -4380,7 +4552,8 @@ static int do_host_query(const char *query_host)
cli_cm_shutdown();
cli_cm_set_port( 139 );
- cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true);
+ cli = cli_cm_open(talloc_tos(), NULL,
+ query_host, "IPC$", true, smb_encrypt);
}
if (cli == NULL) {
@@ -4405,7 +4578,8 @@ static int do_tar_op(const char *base_directory)
/* do we already have a connection? */
if (!cli) {
- cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+ cli = cli_cm_open(talloc_tos(), NULL,
+ desthost, service, true, smb_encrypt);
if (!cli)
return 1;
}
@@ -4512,6 +4686,7 @@ static int do_message_op(void)
{ "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" },
{ "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
{ "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" },
+ { "browse", 'B', POPT_ARG_NONE, NULL, 'B', "Browse SMB servers using DNS" },
POPT_COMMON_SAMBA
POPT_COMMON_CONNECTION
POPT_COMMON_CREDENTIALS
@@ -4538,7 +4713,7 @@ static int do_message_op(void)
set_global_myworkgroup( "" );
set_global_myname( "" );
- /* set default debug level to 0 regardless of what smb.conf sets */
+ /* set default debug level to 1 regardless of what smb.conf sets */
setup_logging( "smbclient", true );
DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
if ((dbf = x_fdup(x_stderr))) {
@@ -4654,6 +4829,12 @@ static int do_message_op(void)
case 'g':
grepable=true;
break;
+ case 'e':
+ smb_encrypt=true;
+ break;
+ case 'B':
+ return(do_smb_browse());
+
}
}
@@ -4741,6 +4922,7 @@ static int do_message_op(void)
calling_name = talloc_strdup(frame, global_myname() );
}
+ smb_encrypt = get_cmdline_auth_info_smb_encrypt();
init_names();
if(new_name_resolve_order)
diff --git a/source3/client/clitar.c b/source3/client/clitar.c
index 0b4a8b2943..04cc987889 100644
--- a/source3/client/clitar.c
+++ b/source3/client/clitar.c
@@ -100,6 +100,7 @@ char tar_type='\0';
static char **cliplist=NULL;
static int clipn=0;
static bool must_free_cliplist = False;
+static const char *cmd_ptr = NULL;
extern bool lowercase;
extern uint16 cnum;
@@ -512,6 +513,7 @@ static bool ensurepath(const char *fname)
char *partpath, *ffname;
const char *p=fname;
char *basehack;
+ char *saveptr;
DEBUG(5, ( "Ensurepath called with: %s\n", fname));
@@ -527,7 +529,7 @@ static bool ensurepath(const char *fname)
*partpath = 0;
- /* fname copied to ffname so can strtok */
+ /* fname copied to ffname so can strtok_r */
safe_strcpy(ffname, fname, strlen(fname));
@@ -540,7 +542,7 @@ static bool ensurepath(const char *fname)
*basehack='\0';
}
- p=strtok(ffname, "\\");
+ p=strtok_r(ffname, "\\", &saveptr);
while (p) {
safe_strcat(partpath, p, strlen(fname) + 1);
@@ -557,7 +559,7 @@ static bool ensurepath(const char *fname)
}
safe_strcat(partpath, "\\", strlen(fname) + 1);
- p = strtok(NULL,"/\\");
+ p = strtok_r(NULL, "/\\", &saveptr);
}
SAFE_FREE(partpath);
@@ -1273,7 +1275,7 @@ int cmd_block(void)
char *buf;
int block;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
DEBUG(0, ("blocksize <n>\n"));
return 1;
}
@@ -1298,7 +1300,7 @@ int cmd_tarmode(void)
TALLOC_CTX *ctx = talloc_tos();
char *buf;
- while (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
if (strequal(buf, "full"))
tar_inc=False;
else if (strequal(buf, "inc"))
@@ -1348,7 +1350,7 @@ int cmd_setmode(void)
attra[0] = attra[1] = 0;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
DEBUG(0, ("setmode <filename> <[+|-]rsha>\n"));
return 1;
}
@@ -1361,7 +1363,7 @@ int cmd_setmode(void)
return 1;
}
- while (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
q=buf;
while(*q) {
@@ -1402,6 +1404,55 @@ int cmd_setmode(void)
return 0;
}
+/**
+ Convert list of tokens to array; dependent on above routine.
+ Uses the global cmd_ptr from above - bit of a hack.
+**/
+
+static char **toktocliplist(int *ctok, const char *sep)
+{
+ char *s=(char *)cmd_ptr;
+ int ictok=0;
+ char **ret, **iret;
+
+ if (!sep)
+ sep = " \t\n\r";
+
+ while(*s && strchr_m(sep,*s))
+ s++;
+
+ /* nothing left? */
+ if (!*s)
+ return(NULL);
+
+ do {
+ ictok++;
+ while(*s && (!strchr_m(sep,*s)))
+ s++;
+ while(*s && strchr_m(sep,*s))
+ *s++=0;
+ } while(*s);
+
+ *ctok=ictok;
+ s=(char *)cmd_ptr;
+
+ if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1)))
+ return NULL;
+
+ while(ictok--) {
+ *iret++=s;
+ if (ictok > 0) {
+ while(*s++)
+ ;
+ while(!*s)
+ s++;
+ }
+ }
+
+ ret[*ctok] = NULL;
+ return ret;
+}
+
/****************************************************************************
Principal command for creating / extracting
***************************************************************************/
@@ -1414,14 +1465,16 @@ int cmd_tar(void)
int argcl = 0;
int ret;
- if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+ if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
return 1;
}
argl=toktocliplist(&argcl, NULL);
- if (!tar_parseargs(argcl, argl, buf, 0))
+ if (!tar_parseargs(argcl, argl, buf, 0)) {
+ SAFE_FREE(argl);
return 1;
+ }
ret = process_tar();
SAFE_FREE(argl);
diff --git a/source3/client/dnsbrowse.c b/source3/client/dnsbrowse.c
new file mode 100644
index 0000000000..5e3a4de9cf
--- /dev/null
+++ b/source3/client/dnsbrowse.c
@@ -0,0 +1,237 @@
+/*
+ Unix SMB/CIFS implementation.
+ DNS-SD browse client
+ Copyright (C) Rishi Srivatsavai 2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "client/client_proto.h"
+
+#ifdef WITH_DNSSD_SUPPORT
+
+#include <dns_sd.h>
+
+/* Holds service instances found during DNS browse */
+struct mdns_smbsrv_result
+{
+ char *serviceName;
+ char *regType;
+ char *domain;
+ uint32_t ifIndex;
+ struct mdns_smbsrv_result *nextResult;
+};
+
+/* Maintains state during DNS browse */
+struct mdns_browse_state
+{
+ struct mdns_smbsrv_result *listhead; /* Browse result list head */
+ int browseDone;
+
+};
+
+
+static void
+do_smb_resolve_reply (DNSServiceRef sdRef, DNSServiceFlags flags,
+ uint32_t interfaceIndex, DNSServiceErrorType errorCode,
+ const char *fullname, const char *hosttarget, uint16_t port,
+ uint16_t txtLen, const unsigned char *txtRecord, void *context)
+{
+ printf("SMB service available on %s port %u\n",
+ hosttarget, ntohs(port));
+}
+
+
+static void do_smb_resolve(struct mdns_smbsrv_result *browsesrv)
+{
+ DNSServiceRef mdns_conn_sdref = NULL;
+ int mdnsfd;
+ int fdsetsz;
+ int ret;
+ fd_set *fdset = NULL;
+ struct timeval tv;
+ DNSServiceErrorType err;
+
+ TALLOC_CTX * ctx = talloc_tos();
+
+ err = DNSServiceResolve(&mdns_conn_sdref, 0 /* flags */,
+ browsesrv->ifIndex,
+ browsesrv->serviceName, browsesrv->regType, browsesrv->domain,
+ do_smb_resolve_reply, NULL);
+
+ if (err != kDNSServiceErr_NoError) {
+ return;
+ }
+
+ mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
+ for (;;) {
+ if (fdset != NULL) {
+ TALLOC_FREE(fdset);
+ }
+
+ fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
+ fdset = TALLOC_ZERO(ctx, fdsetsz);
+ FD_SET(mdnsfd, fdset);
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ /* Wait until response received from mDNS daemon */
+ ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
+ if (ret <= 0 && errno != EINTR) {
+ break;
+ }
+
+ if (FD_ISSET(mdnsfd, fdset)) {
+ /* Invoke callback function */
+ DNSServiceProcessResult(mdns_conn_sdref);
+ break;
+ }
+ }
+
+ TALLOC_FREE(fdset);
+ DNSServiceRefDeallocate(mdns_conn_sdref);
+}
+
+
+static void
+do_smb_browse_reply(DNSServiceRef sdRef, DNSServiceFlags flags,
+ uint32_t interfaceIndex, DNSServiceErrorType errorCode,
+ const char *serviceName, const char *regtype,
+ const char *replyDomain, void *context)
+{
+ struct mdns_browse_state *bstatep = (struct mdns_browse_state *)context;
+ struct mdns_smbsrv_result *bresult;
+
+ if (bstatep == NULL) {
+ return;
+ }
+
+ if (errorCode != kDNSServiceErr_NoError) {
+ bstatep->browseDone = 1;
+ return;
+ }
+
+ if (flags & kDNSServiceFlagsMoreComing) {
+ bstatep->browseDone = 0;
+ } else {
+ bstatep->browseDone = 1;
+ }
+
+ if (!(flags & kDNSServiceFlagsAdd)) {
+ return;
+ }
+
+ bresult = TALLOC_ARRAY(talloc_tos(), struct mdns_smbsrv_result, 1);
+ if (bresult == NULL) {
+ return;
+ }
+
+ if (bstatep->listhead != NULL) {
+ bresult->nextResult = bstatep->listhead;
+ }
+
+ bresult->serviceName = talloc_strdup(talloc_tos(), serviceName);
+ bresult->regType = talloc_strdup(talloc_tos(), regtype);
+ bresult->domain = talloc_strdup(talloc_tos(), replyDomain);
+ bresult->ifIndex = interfaceIndex;
+ bstatep->listhead = bresult;
+}
+
+int do_smb_browse(void)
+{
+ int mdnsfd;
+ int fdsetsz;
+ int ret;
+ fd_set *fdset = NULL;
+ struct mdns_browse_state bstate;
+ struct mdns_smbsrv_result *resptr;
+ struct timeval tv;
+ DNSServiceRef mdns_conn_sdref = NULL;
+ DNSServiceErrorType err;
+
+ TALLOC_CTX * ctx = talloc_stackframe();
+
+ ZERO_STRUCT(bstate);
+
+ err = DNSServiceBrowse(&mdns_conn_sdref, 0, 0, "_smb._tcp", "",
+ do_smb_browse_reply, &bstate);
+
+ if (err != kDNSServiceErr_NoError) {
+ d_printf("Error connecting to the Multicast DNS daemon\n");
+ TALLOC_FREE(ctx);
+ return 1;
+ }
+
+ mdnsfd = DNSServiceRefSockFD(mdns_conn_sdref);
+ for (;;) {
+ if (fdset != NULL) {
+ TALLOC_FREE(fdset);
+ }
+
+ fdsetsz = howmany(mdnsfd + 1, NFDBITS) * sizeof(fd_mask);
+ fdset = TALLOC_ZERO(ctx, fdsetsz);
+ FD_SET(mdnsfd, fdset);
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ /* Wait until response received from mDNS daemon */
+ ret = sys_select(mdnsfd + 1, fdset, NULL, NULL, &tv);
+ if (ret <= 0 && errno != EINTR) {
+ break;
+ }
+
+ if (FD_ISSET(mdnsfd, fdset)) {
+ /* Invoke callback function */
+ if (DNSServiceProcessResult(mdns_conn_sdref)) {
+ break;
+ }
+ if (bstate.browseDone) {
+ break;
+ }
+ }
+ }
+
+ DNSServiceRefDeallocate(mdns_conn_sdref);
+
+ if (bstate.listhead != NULL) {
+ resptr = bstate.listhead;
+ while (resptr != NULL) {
+ struct mdns_smbsrv_result *oldresptr;
+ oldresptr = resptr;
+
+ /* Resolve smb service instance */
+ do_smb_resolve(resptr);
+
+ resptr = resptr->nextResult;
+ }
+ }
+
+ TALLOC_FREE(ctx);
+ return 0;
+}
+
+#else /* WITH_DNSSD_SUPPORT */
+
+int do_smb_browse(void)
+{
+ d_printf("DNS-SD browsing is not supported on this platform\n");
+ return 1;
+}
+
+#endif /* WITH_DNSSD_SUPPORT */
+
+
diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c
index ec245ed200..79f402a7d4 100644
--- a/source3/client/mount.cifs.c
+++ b/source3/client/mount.cifs.c
@@ -39,7 +39,7 @@
#include <fcntl.h>
#define MOUNT_CIFS_VERSION_MAJOR "1"
-#define MOUNT_CIFS_VERSION_MINOR "10"
+#define MOUNT_CIFS_VERSION_MINOR "11"
#ifndef MOUNT_CIFS_VENDOR_SUFFIX
#ifdef _SAMBA_BUILD_
@@ -62,6 +62,8 @@
#define MS_BIND 4096
#endif
+#define MAX_UNC_LEN 1024
+
#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr)))
const char *thisprogram;
@@ -73,7 +75,6 @@ static int got_ip = 0;
static int got_unc = 0;
static int got_uid = 0;
static int got_gid = 0;
-static int free_share_name = 0;
static char * user_name = NULL;
static char * mountpassword = NULL;
char * domain_name = NULL;
@@ -135,14 +136,16 @@ static void mount_cifs_usage(void)
printf("\nLess commonly used options:");
printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,rw,ro,");
printf("\n\tsep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,serverino,");
- printf("\n\tdirectio,mapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
+ printf("\n\tmapchars,nomapchars,nolock,servernetbiosname=<SRV_RFC1001NAME>");
+ printf("\n\tdirectio,nounix,cifsacl,sec=<authentication mechanism>,sign");
printf("\n\nOptions not needed for servers supporting CIFS Unix extensions");
printf("\n\t(e.g. unneeded for mounts to most Samba versions):");
printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>,sfu");
printf("\n\nRarely used options:");
printf("\n\tport=<tcpport>,rsize=<size>,wsize=<size>,unc=<unc_name>,ip=<ip_address>,");
printf("\n\tdev,nodev,nouser_xattr,netbiosname=<OUR_RFC1001NAME>,hard,soft,intr,");
- printf("\n\tnointr,ignorecase,noposixpaths,noacl");
+ printf("\n\tnointr,ignorecase,noposixpaths,noacl,prefixpath=<path>,nobrl");
+ printf("\n\tin6_addr");
printf("\n\nOptions are described in more detail in the manual page");
printf("\n\tman 8 mount.cifs\n");
printf("\nTo display the version number of the mount helper:");
@@ -828,17 +831,27 @@ static char * check_for_domain(char **ppuser)
return domainnm;
}
+/* replace all occurances of "from" in a string with "to" */
+static void replace_char(char *string, char from, char to)
+{
+ while (string) {
+ string = strchr(string, from);
+ if (string)
+ *string = to;
+ }
+}
+
/* Note that caller frees the returned buffer if necessary */
static char * parse_server(char ** punc_name)
{
char * unc_name = *punc_name;
- int length = strnlen(unc_name,1024);
+ int length = strnlen(unc_name, MAX_UNC_LEN);
char * share;
char * ipaddress_string = NULL;
struct hostent * host_entry = NULL;
struct in_addr server_ipaddr;
- if(length > 1023) {
+ if(length > (MAX_UNC_LEN - 1)) {
printf("mount error: UNC name too long");
return NULL;
}
@@ -857,7 +870,6 @@ static char * parse_server(char ** punc_name)
/* check for nfs syntax ie server:share */
share = strchr(unc_name,':');
if(share) {
- free_share_name = 1;
*punc_name = (char *)malloc(length+3);
if(*punc_name == NULL) {
/* put the original string back if
@@ -865,9 +877,9 @@ static char * parse_server(char ** punc_name)
*punc_name = unc_name;
return NULL;
}
-
*share = '/';
strncpy((*punc_name)+2,unc_name,length);
+ free(unc_name);
unc_name = *punc_name;
unc_name[length+2] = 0;
goto continue_unc_parsing;
@@ -878,18 +890,21 @@ static char * parse_server(char ** punc_name)
}
} else {
continue_unc_parsing:
- unc_name[0] = '/';
- unc_name[1] = '/';
+ unc_name[0] = '\\';
+ unc_name[1] = '\\';
unc_name += 2;
- if ((share = strchr(unc_name, '/')) ||
- (share = strchr(unc_name,'\\'))) {
+
+ /* convert any '/' in unc to '\\' */
+ replace_char(unc_name, '/', '\\');
+
+ if ((share = strchr(unc_name,'\\'))) {
*share = 0; /* temporarily terminate the string */
share += 1;
if(got_ip == 0) {
host_entry = gethostbyname(unc_name);
}
- *(share - 1) = '/'; /* put the slash back */
- if ((prefixpath = strchr(share, '/'))) {
+ *(share - 1) = '\\'; /* put delimiter back */
+ if ((prefixpath = strchr(share, '\\'))) {
*prefixpath = 0; /* permanently terminate the string */
if (!strlen(++prefixpath))
prefixpath = NULL; /* this needs to be done explicitly */
@@ -954,6 +969,25 @@ static struct option longopts[] = {
{ NULL, 0, NULL, 0 }
};
+/* convert a string to uppercase. return false if the string
+ * wasn't ASCII or was a NULL ptr */
+static int
+uppercase_string(char *string)
+{
+ if (!string)
+ return 0;
+
+ while (*string) {
+ /* check for unicode */
+ if ((unsigned char) string[0] & 0x80)
+ return 0;
+ *string = toupper((unsigned char) *string);
+ string++;
+ }
+
+ return 1;
+}
+
int main(int argc, char ** argv)
{
int c;
@@ -966,6 +1000,7 @@ int main(int argc, char ** argv)
char * options = NULL;
char * resolved_path = NULL;
char * temp;
+ char * dev_name;
int rc;
int rsize = 0;
int wsize = 0;
@@ -1002,8 +1037,16 @@ int main(int argc, char ** argv)
printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
#endif */
if(argc > 2) {
- share_name = argv[1];
+ dev_name = argv[1];
+ share_name = strndup(argv[1], MAX_UNC_LEN);
+ if (share_name == NULL) {
+ fprintf(stderr, "%s: %s", argv[0], strerror(ENOMEM));
+ exit(1);
+ }
mountpoint = argv[2];
+ } else {
+ mount_cifs_usage();
+ exit(1);
}
/* add sharename in opts string as unc= parm */
@@ -1143,7 +1186,7 @@ int main(int argc, char ** argv)
}
}
- if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) {
+ if((argc < 3) || (dev_name == NULL) || (mountpoint == NULL)) {
mount_cifs_usage();
exit(1);
}
@@ -1301,10 +1344,12 @@ mount_retry:
}
if(verboseflag)
printf("\nmount.cifs kernel mount options %s \n",options);
- if(mount(share_name, mountpoint, "cifs", flags, options)) {
- /* remember to kill daemon on error */
- char * tmp;
+ /* convert all '\\' to '/' so that /proc/mounts looks pretty */
+ replace_char(dev_name, '\\', '/');
+
+ if(mount(dev_name, mountpoint, "cifs", flags, options)) {
+ /* remember to kill daemon on error */
switch (errno) {
case 0:
printf("mount failed but no error number set\n");
@@ -1315,12 +1360,9 @@ mount_retry:
case ENXIO:
if(retry == 0) {
retry = 1;
- tmp = share_name;
- while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) {
- *tmp = toupper((unsigned char)*tmp);
- tmp++;
- }
- if(!*tmp) {
+ if (uppercase_string(dev_name) &&
+ uppercase_string(share_name) &&
+ uppercase_string(prefixpath)) {
printf("retrying with upper case share name\n");
goto mount_retry;
}
@@ -1334,7 +1376,7 @@ mount_retry:
} else {
pmntfile = setmntent(MOUNTED, "a+");
if(pmntfile) {
- mountent.mnt_fsname = share_name;
+ mountent.mnt_fsname = dev_name;
mountent.mnt_dir = mountpoint;
mountent.mnt_type = CONST_DISCARD(char *,"cifs");
mountent.mnt_opts = (char *)malloc(220);
@@ -1394,8 +1436,6 @@ mount_exit:
free(resolved_path);
}
- if(free_share_name) {
- free(share_name);
- }
+ free(share_name);
return rc;
}
diff --git a/source3/client/smbmnt.c b/source3/client/smbmnt.c
index 7f1e1d5003..198faca173 100644
--- a/source3/client/smbmnt.c
+++ b/source3/client/smbmnt.c
@@ -162,6 +162,7 @@ do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
char *release, *major, *minor;
char *data1, *data2;
int ret;
+ char *saveptr = NULL;
if (asprintf(&opts,
"version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s",
@@ -172,8 +173,8 @@ do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
uname(&uts);
release = uts.release;
- major = strtok(release, ".");
- minor = strtok(NULL, ".");
+ major = strtok_r(release, ".", &saveptr);
+ minor = strtok_r(NULL, ".", &saveptr);
if (major && minor && atoi(major) == 2 && atoi(minor) < 4) {
/* < 2.4, assume struct */
data1 = (char *) data;
diff --git a/source3/client/smbmount.c b/source3/client/smbmount.c
index 98c61a30d8..ee4b180a89 100644
--- a/source3/client/smbmount.c
+++ b/source3/client/smbmount.c
@@ -764,6 +764,7 @@ static void parse_mount_smb(int argc, char **argv)
char *opts;
char *opteq;
int val;
+ char *saveptr = NULL;
TALLOC_CTX *ctx = talloc_tos();
/* FIXME: This function can silently fail if the arguments are
@@ -813,7 +814,8 @@ static void parse_mount_smb(int argc, char **argv)
/*
* option parsing from nfsmount.c (util-linux-2.9u)
*/
- for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) {
+ for (opts = strtok_r(optarg, ",", &saveptr); opts;
+ opts = strtok_r(NULL, ",", &saveptr)) {
DEBUG(3, ("opts: %s\n", opts));
if ((opteq = strchr_m(opts, '='))) {
val = atoi(opteq + 1);
diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c
index 4270eb4272..e7df22c2bc 100644
--- a/source3/client/smbspool.c
+++ b/source3/client/smbspool.c
@@ -47,7 +47,9 @@ static struct cli_state *smb_complete_connection(const char *, const char *,int
static struct cli_state *smb_connect(const char *, const char *, int, const char *, const char *, const char *, const char *);
static int smb_print(struct cli_state *, char *, FILE *);
static char * uri_unescape_alloc(const char *);
-
+#if 0
+static bool smb_encrypt;
+#endif
/*
* 'main()' - Main entry for SMB backend.
@@ -468,6 +470,23 @@ static struct cli_state
return NULL;
}
+#if 0
+ /* Need to work out how to specify this on the URL. */
+ if (smb_encrypt)
+ {
+ if (!cli_cm_force_encryption(cli,
+ username,
+ password,
+ workgroup,
+ share))
+ {
+ fprintf(stderr, "ERROR: encryption setup failed\n");
+ cli_shutdown(cli);
+ return NULL;
+ }
+ }
+#endif
+
return cli;
}