diff options
Diffstat (limited to 'source3/client')
-rw-r--r-- | source3/client/cifs.spnego.c | 63 | ||||
-rw-r--r-- | source3/client/client.c | 356 | ||||
-rw-r--r-- | source3/client/clitar.c | 71 | ||||
-rw-r--r-- | source3/client/dnsbrowse.c | 237 | ||||
-rw-r--r-- | source3/client/mount.cifs.c | 98 | ||||
-rw-r--r-- | source3/client/smbmnt.c | 5 | ||||
-rw-r--r-- | source3/client/smbmount.c | 4 | ||||
-rw-r--r-- | source3/client/smbspool.c | 21 |
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, §ype, &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; } |