diff options
Diffstat (limited to 'source3/client')
-rw-r--r-- | source3/client/cifs.spnego.c | 63 | ||||
-rw-r--r-- | source3/client/client.c | 271 | ||||
-rw-r--r-- | source3/client/clitar.c | 11 | ||||
-rw-r--r-- | source3/client/mount.cifs.c | 105 | ||||
-rw-r--r-- | source3/client/smbmnt.c | 331 | ||||
-rw-r--r-- | source3/client/smbmount.c | 1045 | ||||
-rw-r--r-- | source3/client/smbumount.c | 196 |
7 files changed, 273 insertions, 1749 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 267c13048e..1410fc2f33 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -309,6 +309,17 @@ static int cmd_pwd(void) } /**************************************************************************** + Ensure name has correct directory separators. +****************************************************************************/ + +static void normalize_name(char *newdir) +{ + if (!(cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) { + string_replace(newdir,'/','\\'); + } +} + +/**************************************************************************** Change directory - inner section. ****************************************************************************/ @@ -329,7 +340,8 @@ static int do_cd(const char *new_dir) TALLOC_FREE(ctx); return 1; } - string_replace(newdir,'/','\\'); + + normalize_name(newdir); /* Save the current directory in case the new directory is invalid */ @@ -349,17 +361,16 @@ static int do_cd(const char *new_dir) if (!new_cd) { goto out; } - if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) { - new_cd = talloc_asprintf_append(new_cd, CLI_DIRSEP_STR); - if (!new_cd) { - goto out; - } - } - client_set_cur_dir(new_cd); } - if (!new_cd) { - goto out; + + /* Ensure cur_dir ends in a DIRSEP */ + if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) { + new_cd = talloc_asprintf_append(new_cd, CLI_DIRSEP_STR); + if (!new_cd) { + goto out; + } } + client_set_cur_dir(new_cd); new_cd = clean_name(ctx, new_cd); client_set_cur_dir(new_cd); @@ -851,26 +862,15 @@ static int cmd_dir(void) int rc = 1; dir_total = 0; - if (strcmp(client_get_cur_dir(), CLI_DIRSEP_STR) != 0) { - mask = talloc_strdup(ctx, client_get_cur_dir()); - if (!mask) { - return 1; - } - if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) { - mask = talloc_asprintf_append(mask, CLI_DIRSEP_STR); - } - } else { - mask = talloc_strdup(ctx, CLI_DIRSEP_STR); - } - + mask = talloc_strdup(ctx, client_get_cur_dir()); if (!mask) { return 1; } if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { - string_replace(buf,'/','\\'); + normalize_name(buf); if (*buf == CLI_DIRSEP_CHAR) { - mask = talloc_strdup(ctx, buf + 1); + mask = talloc_strdup(ctx, buf); } else { mask = talloc_asprintf_append(mask, buf); } @@ -920,7 +920,7 @@ static int cmd_du(void) } if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { - string_replace(buf,'/','\\'); + normalize_name(buf); if (*buf == CLI_DIRSEP_CHAR) { mask = talloc_strdup(ctx, buf); } else { @@ -964,12 +964,20 @@ static int cmd_echo(void) Get a file from rname to lname ****************************************************************************/ +static NTSTATUS writefile_sink(char *buf, size_t n, void *priv) +{ + int *pfd = (int *)priv; + if (writefile(*pfd, buf, n) == -1) { + return map_nt_error_from_unix(errno); + } + return NT_STATUS_OK; +} + static int do_get(const char *rname, const char *lname_in, bool reget) { TALLOC_CTX *ctx = talloc_tos(); int handle = 0, fnum; bool newhandle = false; - char *data = NULL; struct timeval tp_start; int read_size = io_bufsize; uint16 attr; @@ -980,6 +988,7 @@ static int do_get(const char *rname, const char *lname_in, bool reget) struct cli_state *targetcli = NULL; char *targetname = NULL; char *lname = NULL; + NTSTATUS status; lname = talloc_strdup(ctx, lname_in); if (!lname) { @@ -1038,36 +1047,15 @@ static int do_get(const char *rname, const char *lname_in, bool reget) DEBUG(1,("getting file %s of size %.0f as %s ", rname, (double)size, lname)); - if(!(data = (char *)SMB_MALLOC(read_size))) { - d_printf("malloc fail for size %d\n", read_size); + status = cli_pull(targetcli, fnum, start, size, 1024*1024, + writefile_sink, (void *)&handle, &nread); + if (!NT_STATUS_IS_OK(status)) { + d_fprintf(stderr, "parallel_read returned %s\n", + nt_errstr(status)); cli_close(targetcli, fnum); return 1; } - while (1) { - int n = cli_read(targetcli, fnum, data, nread + start, read_size); - - if (n <= 0) - break; - - if (writefile(handle,data, n) != n) { - d_printf("Error writing local file\n"); - rc = 1; - break; - } - - nread += n; - } - - if (nread + start < size) { - DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n", - rname, (long)nread)); - - rc = 1; - } - - SAFE_FREE(data); - if (!cli_close(targetcli, fnum)) { d_printf("Error %s closing remote file\n",cli_errstr(cli)); rc = 1; @@ -1112,10 +1100,7 @@ static int cmd_get(void) char *rname = NULL; char *fname = NULL; - rname = talloc_asprintf(ctx, - "%s%s", - client_get_cur_dir(), - CLI_DIRSEP_STR); + rname = talloc_strdup(ctx, client_get_cur_dir()); if (!rname) { return 1; } @@ -1262,10 +1247,7 @@ static int cmd_more(void) int fd; int rc = 0; - rname = talloc_asprintf(ctx, - "%s%s", - client_get_cur_dir(), - CLI_DIRSEP_STR); + rname = talloc_strdup(ctx, client_get_cur_dir()); if (!rname) { return 1; } @@ -1334,15 +1316,6 @@ static int cmd_mget(void) if (!mget_mask) { return 1; } - if ((mget_mask[0] != '\0') && - (mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR)) { - mget_mask = talloc_asprintf_append(mget_mask, - CLI_DIRSEP_STR); - if (!mget_mask) { - return 1; - } - } - if (*buf == CLI_DIRSEP_CHAR) { mget_mask = talloc_strdup(ctx, buf); } else { @@ -1356,18 +1329,9 @@ static int cmd_mget(void) } if (!*mget_mask) { - mget_mask = talloc_strdup(ctx, client_get_cur_dir()); - if (!mget_mask) { - return 1; - } - if(mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR) { - mget_mask = talloc_asprintf_append(mget_mask, - CLI_DIRSEP_STR); - if (!mget_mask) { - return 1; - } - } - mget_mask = talloc_asprintf_append(mget_mask, "*"); + mget_mask = talloc_asprintf(ctx, + "%s*", + client_get_cur_dir()); if (!mget_mask) { return 1; } @@ -1463,6 +1427,7 @@ static int cmd_mkdir(void) struct cli_state *targetcli; char *targetname = NULL; char *p = NULL; + char *saveptr; ddir2 = talloc_strdup(ctx, ""); if (!ddir2) { @@ -1478,7 +1443,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) { @@ -1491,7 +1456,7 @@ static int cmd_mkdir(void) if (!ddir2) { return 1; } - p = strtok(NULL,"/\\"); + p = strtok_r(NULL, "/\\", &saveptr); } } else { do_mkdir(mask); @@ -1528,6 +1493,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. ****************************************************************************/ @@ -1673,10 +1724,7 @@ static int cmd_put(void) char *rname; char *buf; - rname = talloc_asprintf(ctx, - "%s%s", - client_get_cur_dir(), - CLI_DIRSEP_STR); + rname = talloc_strdup(ctx, client_get_cur_dir()); if (!rname) { return 1; } @@ -1893,10 +1941,10 @@ static int cmd_mput(void) break; } else { /* Yes */ SAFE_FREE(rname); - if(asprintf(&rname, "%s%s", cur_dir, lname) < 0) { + if(asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) { break; } - string_replace(rname,'/','\\'); + normalize_name(rname); if (!cli_chkpath(cli, rname) && !do_mkdir(rname)) { DEBUG (0, ("Unable to make dir, skipping...")); @@ -1920,12 +1968,12 @@ static int cmd_mput(void) /* Yes */ SAFE_FREE(rname); - if (asprintf(&rname, "%s%s", cur_dir, lname) < 0) { + if (asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) { break; } } - string_replace(rname,'/','\\'); + normalize_name(rname); do_put(rname, lname, false); } @@ -3469,10 +3517,7 @@ static int cmd_reget(void) char *fname = NULL; char *p = NULL; - remote_name = talloc_asprintf(ctx, - "%s%s", - client_get_cur_dir(), - CLI_DIRSEP_STR); + remote_name = talloc_strdup(ctx, client_get_cur_dir()); if (!remote_name) { return 1; } @@ -3511,10 +3556,7 @@ static int cmd_reput(void) char *buf; SMB_STRUCT_STAT st; - remote_name = talloc_asprintf(ctx, - "%s%s", - client_get_cur_dir(), - CLI_DIRSEP_STR); + remote_name = talloc_strdup(ctx, client_get_cur_dir()); if (!remote_name) { return 1; } @@ -3839,6 +3881,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}}, @@ -4069,7 +4113,7 @@ static void completion_remote_filter(const char *mnt, return; } if (f->mode & aDIR) { - tmp = talloc_asprintf_append(tmp, "/"); + tmp = talloc_asprintf_append(tmp, CLI_DIRSEP_STR); } if (!tmp) { TALLOC_FREE(ctx); @@ -4333,9 +4377,30 @@ static void readline_callback(void) session keepalives and then drop them here. */ if (FD_ISSET(cli->fd,&fds)) { - 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")); + NTSTATUS status; + size_t len; + + set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK); + + status = receive_smb_raw(cli->fd, cli->inbuf, 0, 0, &len); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Read from server failed, maybe it closed " + "the connection\n")); + + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { + set_smb_read_error(&cli->smb_rw_error, + SMB_READ_EOF); + return; + } + + if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { + set_smb_read_error(&cli->smb_rw_error, + SMB_READ_TIMEOUT); + return; + } + + set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR); return; } if(CVAL(cli->inbuf,0) != SMBkeepalive) { diff --git a/source3/client/clitar.c b/source3/client/clitar.c index 135815c3cd..04cc987889 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -513,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)); @@ -528,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)); @@ -541,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); @@ -558,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); @@ -1470,8 +1471,10 @@ int cmd_tar(void) } 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/mount.cifs.c b/source3/client/mount.cifs.c index 79f402a7d4..e73d90859c 100644 --- a/source3/client/mount.cifs.c +++ b/source3/client/mount.cifs.c @@ -37,6 +37,7 @@ #include <string.h> #include <mntent.h> #include <fcntl.h> +#include <limits.h> #define MOUNT_CIFS_VERSION_MAJOR "1" #define MOUNT_CIFS_VERSION_MINOR "11" @@ -62,8 +63,6 @@ #define MS_BIND 4096 #endif -#define MAX_UNC_LEN 1024 - #define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr))) const char *thisprogram; @@ -75,6 +74,7 @@ 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; @@ -205,8 +205,10 @@ static int open_cred_file(char * file_name) /* go past equals sign */ temp_val++; for(length = 0;length<4087;length++) { - if(temp_val[length] == '\n') + if ((temp_val[length] == '\n') + || (temp_val[length] == '\0')) { break; + } } if(length > 4086) { printf("mount.cifs failed due to malformed username in credentials file"); @@ -229,8 +231,10 @@ static int open_cred_file(char * file_name) /* go past equals sign */ temp_val++; for(length = 0;length<65;length++) { - if(temp_val[length] == '\n') + if ((temp_val[length] == '\n') + || (temp_val[length] == '\0')) { break; + } } if(length > 64) { printf("mount.cifs failed: password in credentials file too long\n"); @@ -258,8 +262,10 @@ static int open_cred_file(char * file_name) if(verboseflag) printf("\nDomain %s\n",temp_val); for(length = 0;length<65;length++) { - if(temp_val[length] == '\n') - break; + if ((temp_val[length] == '\n') + || (temp_val[length] == '\0')) { + break; + } } if(length > 64) { printf("mount.cifs failed: domain in credentials file too long\n"); @@ -831,27 +837,17 @@ 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, MAX_UNC_LEN); + int length = strnlen(unc_name,1024); char * share; char * ipaddress_string = NULL; struct hostent * host_entry = NULL; struct in_addr server_ipaddr; - if(length > (MAX_UNC_LEN - 1)) { + if(length > 1023) { printf("mount error: UNC name too long"); return NULL; } @@ -870,6 +866,7 @@ 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 @@ -877,9 +874,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; @@ -890,21 +887,18 @@ 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; - - /* convert any '/' in unc to '\\' */ - replace_char(unc_name, '/', '\\'); - - if ((share = strchr(unc_name,'\\'))) { + if ((share = strchr(unc_name, '/')) || + (share = strchr(unc_name,'\\'))) { *share = 0; /* temporarily terminate the string */ share += 1; if(got_ip == 0) { host_entry = gethostbyname(unc_name); } - *(share - 1) = '\\'; /* put delimiter back */ - if ((prefixpath = strchr(share, '\\'))) { + *(share - 1) = '/'; /* put the slash back */ + if ((prefixpath = strchr(share, '/'))) { *prefixpath = 0; /* permanently terminate the string */ if (!strlen(++prefixpath)) prefixpath = NULL; /* this needs to be done explicitly */ @@ -969,25 +963,6 @@ 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; @@ -1000,7 +975,6 @@ 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; @@ -1037,16 +1011,8 @@ 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) { - 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); - } + share_name = argv[1]; mountpoint = argv[2]; - } else { - mount_cifs_usage(); - exit(1); } /* add sharename in opts string as unc= parm */ @@ -1186,7 +1152,7 @@ int main(int argc, char ** argv) } } - if((argc < 3) || (dev_name == NULL) || (mountpoint == NULL)) { + if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) { mount_cifs_usage(); exit(1); } @@ -1344,12 +1310,10 @@ mount_retry: } if(verboseflag) printf("\nmount.cifs kernel mount options %s \n",options); - - /* convert all '\\' to '/' so that /proc/mounts looks pretty */ - replace_char(dev_name, '\\', '/'); - - if(mount(dev_name, mountpoint, "cifs", flags, options)) { + if(mount(share_name, mountpoint, "cifs", flags, options)) { /* remember to kill daemon on error */ + char * tmp; + switch (errno) { case 0: printf("mount failed but no error number set\n"); @@ -1360,9 +1324,12 @@ mount_retry: case ENXIO: if(retry == 0) { retry = 1; - if (uppercase_string(dev_name) && - uppercase_string(share_name) && - uppercase_string(prefixpath)) { + tmp = share_name; + while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) { + *tmp = toupper((unsigned char)*tmp); + tmp++; + } + if(!*tmp) { printf("retrying with upper case share name\n"); goto mount_retry; } @@ -1376,7 +1343,7 @@ mount_retry: } else { pmntfile = setmntent(MOUNTED, "a+"); if(pmntfile) { - mountent.mnt_fsname = dev_name; + mountent.mnt_fsname = share_name; mountent.mnt_dir = mountpoint; mountent.mnt_type = CONST_DISCARD(char *,"cifs"); mountent.mnt_opts = (char *)malloc(220); @@ -1436,6 +1403,8 @@ mount_exit: free(resolved_path); } - free(share_name); + if(free_share_name) { + free(share_name); + } return rc; } diff --git a/source3/client/smbmnt.c b/source3/client/smbmnt.c deleted file mode 100644 index 7f1e1d5003..0000000000 --- a/source3/client/smbmnt.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * smbmnt.c - * - * Copyright (C) 1995-1998 by Paal-Kr. Engstad and Volker Lendecke - * extensively modified by Tridge - * - * 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/>. - * - */ - -#define SMBMOUNT_MALLOC 1 - -#include "includes.h" - -#include <mntent.h> -#include <sys/utsname.h> - -#include <asm/types.h> -#include <asm/posix_types.h> -#include <linux/smb.h> -#include <linux/smb_mount.h> -#include <asm/unistd.h> - -#ifndef MS_MGC_VAL -/* This may look strange but MS_MGC_VAL is what we are looking for and - is what we need from <linux/fs.h> under libc systems and is - provided in standard includes on glibc systems. So... We - switch on what we need... */ -#include <linux/fs.h> -#endif - -static uid_t mount_uid; -static gid_t mount_gid; -static int mount_ro; -static unsigned mount_fmask; -static unsigned mount_dmask; -static int user_mount; -static char *options; - -static void -help(void) -{ - printf("\n"); - printf("Usage: smbmnt mount-point [options]\n"); - printf("Version %s\n\n",SAMBA_VERSION_STRING); - printf("-s share share name on server\n" - "-r mount read-only\n" - "-u uid mount as uid\n" - "-g gid mount as gid\n" - "-f mask permission mask for files\n" - "-d mask permission mask for directories\n" - "-o options name=value, list of options\n" - "-h print this help text\n"); -} - -static int -parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share) -{ - int opt; - - while ((opt = getopt (argc, argv, "s:u:g:rf:d:o:")) != EOF) - { - switch (opt) - { - case 's': - *share = optarg; - break; - case 'u': - if (!user_mount) { - mount_uid = strtol(optarg, NULL, 0); - } - break; - case 'g': - if (!user_mount) { - mount_gid = strtol(optarg, NULL, 0); - } - break; - case 'r': - mount_ro = 1; - break; - case 'f': - mount_fmask = strtol(optarg, NULL, 8); - break; - case 'd': - mount_dmask = strtol(optarg, NULL, 8); - break; - case 'o': - options = optarg; - break; - default: - return -1; - } - } - return 0; - -} - -static char * -fullpath(const char *p) -{ - char path[PATH_MAX+1]; - - if (strlen(p) > PATH_MAX) { - return NULL; - } - - if (realpath(p, path) == NULL) { - fprintf(stderr,"Failed to find real path for mount point %s: %s\n", - p, strerror(errno)); - exit(1); - } - return strdup(path); -} - -/* Check whether user is allowed to mount on the specified mount point. If it's - OK then we change into that directory - this prevents race conditions */ -static int mount_ok(char *mount_point) -{ - struct stat st; - - if (chdir(mount_point) != 0) { - return -1; - } - - if (stat(".", &st) != 0) { - return -1; - } - - if (!S_ISDIR(st.st_mode)) { - errno = ENOTDIR; - return -1; - } - - if ((getuid() != 0) && - ((getuid() != st.st_uid) || - ((st.st_mode & S_IRWXU) != S_IRWXU))) { - errno = EPERM; - return -1; - } - - return 0; -} - -/* Tries to mount using the appropriate format. For 2.2 the struct, - for 2.4 the ascii version. */ -static int -do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data) -{ - char *opts; - struct utsname uts; - char *release, *major, *minor; - char *data1, *data2; - int ret; - - if (asprintf(&opts, - "version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s", - mount_uid, mount_gid, data->file_mode, - data->dir_mode,options) < 0) { - return -1; - } - - uname(&uts); - release = uts.release; - major = strtok(release, "."); - minor = strtok(NULL, "."); - if (major && minor && atoi(major) == 2 && atoi(minor) < 4) { - /* < 2.4, assume struct */ - data1 = (char *) data; - data2 = opts; - } else { - /* >= 2.4, assume ascii but fall back on struct */ - data1 = opts; - data2 = (char *) data; - } - - if (mount(share_name, ".", "smbfs", flags, data1) == 0) { - SAFE_FREE(opts); - return 0; - } - ret = mount(share_name, ".", "smbfs", flags, data2); - SAFE_FREE(opts); - return ret; -} - - int main(int argc, char *argv[]) -{ - char *mount_point, *share_name = NULL; - FILE *mtab; - int fd; - unsigned int flags; - struct smb_mount_data data; - struct mntent ment; - - memset(&data, 0, sizeof(struct smb_mount_data)); - - if (argc < 2) { - help(); - exit(1); - } - - if (argv[1][0] == '-') { - help(); - exit(1); - } - - if (getuid() != 0) { - user_mount = 1; - } - - if (geteuid() != 0) { - fprintf(stderr, "smbmnt must be installed suid root for direct user mounts (%d,%d)\n", getuid(), geteuid()); - exit(1); - } - - mount_uid = getuid(); - mount_gid = getgid(); - mount_fmask = umask(0); - umask(mount_fmask); - mount_fmask = ~mount_fmask; - - mount_point = fullpath(argv[1]); - - argv += 1; - argc -= 1; - - if (mount_ok(mount_point) != 0) { - fprintf(stderr, "cannot mount on %s: %s\n", - mount_point, strerror(errno)); - exit(1); - } - - data.version = SMB_MOUNT_VERSION; - - /* getuid() gives us the real uid, who may umount the fs */ - data.mounted_uid = getuid(); - - if (parse_args(argc, argv, &data, &share_name) != 0) { - help(); - return -1; - } - - data.uid = mount_uid; // truncates to 16-bits here!!! - data.gid = mount_gid; - data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_fmask; - data.dir_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_dmask; - - if (mount_dmask == 0) { - data.dir_mode = data.file_mode; - if ((data.dir_mode & S_IRUSR) != 0) - data.dir_mode |= S_IXUSR; - if ((data.dir_mode & S_IRGRP) != 0) - data.dir_mode |= S_IXGRP; - if ((data.dir_mode & S_IROTH) != 0) - data.dir_mode |= S_IXOTH; - } - - flags = MS_MGC_VAL | MS_NOSUID | MS_NODEV; - - if (mount_ro) flags |= MS_RDONLY; - - if (do_mount(share_name, flags, &data) < 0) { - switch (errno) { - case ENODEV: - fprintf(stderr, "ERROR: smbfs filesystem not supported by the kernel\n"); - break; - default: - perror("mount error"); - } - fprintf(stderr, "Please refer to the smbmnt(8) manual page\n"); - return -1; - } - - ment.mnt_fsname = share_name ? share_name : (char *)"none"; - ment.mnt_dir = mount_point; - ment.mnt_type = (char *)"smbfs"; - ment.mnt_opts = (char *)""; - ment.mnt_freq = 0; - ment.mnt_passno= 0; - - mount_point = ment.mnt_dir; - - if (mount_point == NULL) - { - fprintf(stderr, "Mount point too long\n"); - return -1; - } - - if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) - { - fprintf(stderr, "Can't get "MOUNTED"~ lock file"); - return 1; - } - close(fd); - - if ((mtab = setmntent(MOUNTED, "a+")) == NULL) - { - fprintf(stderr, "Can't open " MOUNTED); - return 1; - } - - if (addmntent(mtab, &ment) == 1) - { - fprintf(stderr, "Can't write mount entry"); - return 1; - } - if (fchmod(fileno(mtab), 0644) == -1) - { - fprintf(stderr, "Can't set perms on "MOUNTED); - return 1; - } - endmntent(mtab); - - if (unlink(MOUNTED"~") == -1) - { - fprintf(stderr, "Can't remove "MOUNTED"~"); - return 1; - } - - return 0; -} diff --git a/source3/client/smbmount.c b/source3/client/smbmount.c deleted file mode 100644 index 98c61a30d8..0000000000 --- a/source3/client/smbmount.c +++ /dev/null @@ -1,1045 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SMBFS mount program - Copyright (C) Andrew Tridgell 1999 - - 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 <mntent.h> -#include <asm/types.h> -#include <linux/smb_fs.h> - -extern bool in_client; -extern char *optarg; -extern int optind; - -static char *credentials; -static fstring my_netbios_name; -static char *password; -static char *username; -static fstring workgroup; -static char *mpoint; -static char *service; -static char *options; - -static struct sockaddr_storage dest_ip; -static bool have_ip; -static int smb_port = 0; -static bool got_user; -static bool got_pass; -static uid_t mount_uid; -static gid_t mount_gid; -static int mount_ro; -static unsigned mount_fmask; -static unsigned mount_dmask; -static bool use_kerberos; -/* TODO: Add code to detect smbfs version in kernel */ -static bool status32_smbfs = False; -static bool smbfs_has_unicode = False; -static bool smbfs_has_lfs = False; - -static void usage(void); - -static void exit_parent(int sig) -{ - /* parent simply exits when child says go... */ - exit(0); -} - -static void daemonize(void) -{ - int j, status; - pid_t child_pid; - - signal( SIGTERM, exit_parent ); - - if ((child_pid = sys_fork()) < 0) { - DEBUG(0,("could not fork\n")); - } - - if (child_pid > 0) { - while( 1 ) { - j = waitpid( child_pid, &status, 0 ); - if( j < 0 ) { - if( EINTR == errno ) { - continue; - } - status = errno; - } - break; - } - - /* If we get here - the child exited with some error status */ - if (WIFSIGNALED(status)) - exit(128 + WTERMSIG(status)); - else - exit(WEXITSTATUS(status)); - } - - signal( SIGTERM, SIG_DFL ); - chdir("/"); -} - -static void close_our_files(int client_fd) -{ - int i; - struct rlimit limits; - - getrlimit(RLIMIT_NOFILE,&limits); - for (i = 0; i< limits.rlim_max; i++) { - if (i == client_fd) - continue; - close(i); - } -} - -static void usr1_handler(int x) -{ - return; -} - - -/***************************************************** -return a connection to a server -*******************************************************/ -static struct cli_state *do_connection(char *the_service) -{ - struct cli_state *c; - struct nmb_name called, calling; - char *server_n; - struct sockaddr_storage ip; - char *server; - char *share; - const char *c_username; - const char *c_password; - TALLOC_CTX *ctx = talloc_tos(); - - if (the_service[0] != '\\' || the_service[1] != '\\') { - usage(); - exit(1); - } - - server = talloc_strdup(ctx, the_service+2); - if (!server) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - share = strchr_m(server,'\\'); - if (!share) { - usage(); - exit(1); - } - *share = 0; - share++; - - server_n = server; - - make_nmb_name(&calling, my_netbios_name, 0x0); - make_nmb_name(&called , server, 0x20); - - again: - zero_addr(&ip); - if (have_ip) ip = dest_ip; - - /* have to open a new connection */ - if (!(c=cli_initialise()) || (cli_set_port(c, smb_port) != smb_port) || - !NT_STATUS_IS_OK(cli_connect(c, server_n, &ip))) { - DEBUG(0,("%d: Connection to %s failed\n", sys_getpid(), server_n)); - if (c) { - cli_shutdown(c); - } - return NULL; - } - - /* SPNEGO doesn't work till we get NTSTATUS error support */ - /* But it is REQUIRED for kerberos authentication */ - if(!use_kerberos) c->use_spnego = False; - - /* The kernel doesn't yet know how to sign it's packets */ - c->sign_info.allow_smb_signing = False; - - /* Use kerberos authentication if specified */ - c->use_kerberos = use_kerberos; - - if (!cli_session_request(c, &calling, &called)) { - char *p; - DEBUG(0,("%d: session request to %s failed (%s)\n", - sys_getpid(), called.name, cli_errstr(c))); - cli_shutdown(c); - if ((p=strchr_m(called.name, '.'))) { - *p = 0; - goto again; - } - if (strcmp(called.name, "*SMBSERVER")) { - make_nmb_name(&called , "*SMBSERVER", 0x20); - goto again; - } - return NULL; - } - - DEBUG(4,("%d: session request ok\n", sys_getpid())); - - if (!cli_negprot(c)) { - DEBUG(0,("%d: protocol negotiation failed\n", sys_getpid())); - cli_shutdown(c); - return NULL; - } - - if (!got_pass) { - char *pass = getpass("Password: "); - if (pass) { - password = talloc_strdup(talloc_tos(), pass); - if (!password) { - return NULL; - } - } - } - - /* This should be right for current smbfs. Future versions will support - large files as well as unicode and oplocks. */ - c->capabilities &= ~(CAP_NT_SMBS | CAP_NT_FIND | CAP_LEVEL_II_OPLOCKS); - if (!smbfs_has_lfs) - c->capabilities &= ~CAP_LARGE_FILES; - if (!smbfs_has_unicode) - c->capabilities &= ~CAP_UNICODE; - if (!status32_smbfs) { - c->capabilities &= ~CAP_STATUS32; - c->force_dos_errors = True; - } - - c_password = password ? password : ""; - c_username = username ? username : ""; - - if (!NT_STATUS_IS_OK(cli_session_setup(c, - c_username, - c_password, strlen(c_password), - c_password, strlen(c_password), - workgroup))) { - /* if a password was not supplied then try again with a - null username */ - if (c_password[0] || !c_username[0] || - !NT_STATUS_IS_OK(cli_session_setup(c, "", "", 0, "", 0, workgroup))) { - DEBUG(0,("%d: session setup failed: %s\n", - sys_getpid(), cli_errstr(c))); - cli_shutdown(c); - return NULL; - } - DEBUG(0,("Anonymous login successful\n")); - } - - DEBUG(4,("%d: session setup ok\n", sys_getpid())); - - if (!cli_send_tconX(c, share, "?????", - c_password, strlen(c_password)+1)) { - DEBUG(0,("%d: tree connect failed: %s\n", - sys_getpid(), cli_errstr(c))); - cli_shutdown(c); - return NULL; - } - - DEBUG(4,("%d: tconx ok\n", sys_getpid())); - - got_pass = True; - - return c; -} - -/**************************************************************************** -unmount smbfs (this is a bailout routine to clean up if a reconnect fails) - Code blatently stolen from smbumount.c - -mhw- -****************************************************************************/ -static void smb_umount(char *mount_point) -{ - int fd; - struct mntent *mnt; - FILE* mtab; - FILE* new_mtab; - - /* Programmers Note: - This routine only gets called to the scene of a disaster - to shoot the survivors... A connection that was working - has now apparently failed. We have an active mount point - (presumably) that we need to dump. If we get errors along - the way - make some noise, but we are already turning out - the lights to exit anyways... - */ - if (umount(mount_point) != 0) { - DEBUG(0,("%d: Could not umount %s: %s\n", - sys_getpid(), mount_point, strerror(errno))); - return; - } - - if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) { - DEBUG(0,("%d: Can't get "MOUNTED"~ lock file", sys_getpid())); - return; - } - - close(fd); - - if ((mtab = setmntent(MOUNTED, "r")) == NULL) { - DEBUG(0,("%d: Can't open " MOUNTED ": %s\n", - sys_getpid(), strerror(errno))); - return; - } - -#define MOUNTED_TMP MOUNTED".tmp" - - if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { - DEBUG(0,("%d: Can't open " MOUNTED_TMP ": %s\n", - sys_getpid(), strerror(errno))); - endmntent(mtab); - return; - } - - while ((mnt = getmntent(mtab)) != NULL) { - if (strcmp(mnt->mnt_dir, mount_point) != 0) { - addmntent(new_mtab, mnt); - } - } - - endmntent(mtab); - - if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { - DEBUG(0,("%d: Error changing mode of %s: %s\n", - sys_getpid(), MOUNTED_TMP, strerror(errno))); - return; - } - - endmntent(new_mtab); - - if (rename(MOUNTED_TMP, MOUNTED) < 0) { - DEBUG(0,("%d: Cannot rename %s to %s: %s\n", - sys_getpid(), MOUNTED, MOUNTED_TMP, strerror(errno))); - return; - } - - if (unlink(MOUNTED"~") == -1) { - DEBUG(0,("%d: Can't remove "MOUNTED"~", sys_getpid())); - return; - } -} - - -/* - * Call the smbfs ioctl to install a connection socket, - * then wait for a signal to reconnect. Note that we do - * not exit after open_sockets() or send_login() errors, - * as the smbfs mount would then have no way to recover. - */ -static void send_fs_socket(char *the_service, char *mount_point, struct cli_state *c) -{ - int fd, closed = 0, res = 1; - pid_t parentpid = getppid(); - struct smb_conn_opt conn_options; - - memset(&conn_options, 0, sizeof(conn_options)); - - while (1) { - if ((fd = open(mount_point, O_RDONLY)) < 0) { - DEBUG(0,("mount.smbfs[%d]: can't open %s\n", - sys_getpid(), mount_point)); - break; - } - - conn_options.fd = c->fd; - conn_options.protocol = c->protocol; - conn_options.case_handling = SMB_CASE_DEFAULT; - conn_options.max_xmit = c->max_xmit; - conn_options.server_uid = c->vuid; - conn_options.tid = c->cnum; - conn_options.secmode = c->sec_mode; - conn_options.rawmode = 0; - conn_options.sesskey = c->sesskey; - conn_options.maxraw = 0; - conn_options.capabilities = c->capabilities; - conn_options.serverzone = c->serverzone/60; - - res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options); - if (res != 0) { - DEBUG(0,("mount.smbfs[%d]: ioctl failed, res=%d\n", - sys_getpid(), res)); - close(fd); - break; - } - - if (parentpid) { - /* Ok... We are going to kill the parent. Now - is the time to break the process group... */ - setsid(); - /* Send a signal to the parent to terminate */ - kill(parentpid, SIGTERM); - parentpid = 0; - } - - close(fd); - - /* This looks wierd but we are only closing the userspace - side, the connection has already been passed to smbfs and - it has increased the usage count on the socket. - - If we don't do this we will "leak" sockets and memory on - each reconnection we have to make. */ - c->smb_rw_error = SMB_DO_NOT_DO_TDIS; - cli_shutdown(c); - c = NULL; - - if (!closed) { - /* close the name cache so that close_our_files() doesn't steal its FD */ - namecache_shutdown(); - - /* redirect stdout & stderr since we can't know that - the library functions we use are using DEBUG. */ - if ( (fd = open("/dev/null", O_WRONLY)) < 0) - DEBUG(2,("mount.smbfs: can't open /dev/null\n")); - close_our_files(fd); - if (fd >= 0) { - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - close(fd); - } - - /* here we are no longer interactive */ - set_remote_machine_name("smbmount", False); /* sneaky ... */ - setup_logging("mount.smbfs", False); - reopen_logs(); - DEBUG(0, ("mount.smbfs: entering daemon mode for service %s, pid=%d\n", the_service, sys_getpid())); - - closed = 1; - } - - /* Wait for a signal from smbfs ... but don't continue - until we actually get a new connection. */ - while (!c) { - CatchSignal(SIGUSR1, &usr1_handler); - pause(); - DEBUG(2,("mount.smbfs[%d]: got signal, getting new socket\n", sys_getpid())); - c = do_connection(the_service); - } - } - - smb_umount(mount_point); - DEBUG(2,("mount.smbfs[%d]: exit\n", sys_getpid())); - exit(1); -} - - -/** - * Mount a smbfs - **/ - -#define NUM_ARGS 20 - -static void init_mount(void) -{ - char mount_point[PATH_MAX+1]; - TALLOC_CTX *ctx = talloc_tos(); - char *svc2; - struct cli_state *c; - const char *args[NUM_ARGS]; - int i, status; - - if (realpath(mpoint, mount_point) == NULL) { - fprintf(stderr, "Could not resolve mount point %s\n", mpoint); - return; - } - - - c = do_connection(service); - if (!c) { - fprintf(stderr,"SMB connection failed\n"); - exit(1); - } - - /* - Set up to return as a daemon child and wait in the parent - until the child say it's ready... - */ - daemonize(); - - svc2 = talloc_strdup(ctx, service); - if (!svc2) { - fprintf(stderr, "Out of memory.\n"); - exit(ENOMEM); - } - string_replace(svc2, '\\','/'); - string_replace(svc2, ' ','_'); - - memset(args, 0, sizeof(args[0])*NUM_ARGS); - - i=0; - args[i++] = "smbmnt"; - - args[i++] = mount_point; - args[i++] = "-s"; - args[i++] = svc2; - - if (mount_ro && i < NUM_ARGS-2) { - args[i++] = "-r"; - } - if (mount_uid && i < NUM_ARGS-3) { - args[i++] = "-u"; - args[i] = talloc_asprintf(ctx, "%d", mount_uid); - if (!args[i]) { - fprintf(stderr, "Out of memory.\n"); - exit(ENOMEM); - } - i++; - } - if (mount_gid && i < NUM_ARGS-3) { - args[i++] = "-g"; - args[i] = talloc_asprintf(ctx, "%d", mount_gid); - if (!args[i]) { - fprintf(stderr, "Out of memory.\n"); - exit(ENOMEM); - } - i++; - } - if (mount_fmask && i < NUM_ARGS-3) { - args[i++] = "-f"; - args[i] = talloc_asprintf(ctx, "0%o", mount_fmask); - if (!args[i]) { - fprintf(stderr, "Out of memory.\n"); - exit(ENOMEM); - } - i++; - } - if (mount_dmask && i < NUM_ARGS-3) { - args[i++] = "-d"; - args[i] = talloc_asprintf(ctx, "0%o", mount_dmask); - if (!args[i]) { - fprintf(stderr, "Out of memory.\n"); - exit(ENOMEM); - } - i++; - } - if (options && i < NUM_ARGS-3) { - args[i++] = "-o"; - args[i++] = options; - } - - if (sys_fork() == 0) { - char *smbmnt_path; - - asprintf(&smbmnt_path, "%s/smbmnt", get_dyn_BINDIR()); - - if (file_exist(smbmnt_path, NULL)) { - execv(smbmnt_path, (char * const *)args); - fprintf(stderr, - "smbfs/init_mount: execv of %s failed. Error was %s.", - smbmnt_path, strerror(errno)); - } else { - execvp("smbmnt", (char * const *)args); - fprintf(stderr, - "smbfs/init_mount: execv of %s failed. Error was %s.", - "smbmnt", strerror(errno)); - } - free(smbmnt_path); - exit(1); - } - - if (waitpid(-1, &status, 0) == -1) { - fprintf(stderr,"waitpid failed: Error was %s", strerror(errno) ); - /* FIXME: do some proper error handling */ - exit(1); - } - - if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { - fprintf(stderr,"smbmnt failed: %d\n", WEXITSTATUS(status)); - /* FIXME: do some proper error handling */ - exit(1); - } else if (WIFSIGNALED(status)) { - fprintf(stderr, "smbmnt killed by signal %d\n", WTERMSIG(status)); - exit(1); - } - - /* Ok... This is the rubicon for that mount point... At any point - after this, if the connections fail and can not be reconstructed - for any reason, we will have to unmount the mount point. There - is no exit from the next call... - */ - send_fs_socket(service, mount_point, c); -} - - -/**************************************************************************** -get a password from a a file or file descriptor -exit on failure (from smbclient, move to libsmb or shared .c file?) -****************************************************************************/ - -static void get_password_file(void) -{ - int fd = -1; - char *p; - bool close_it = False; - char *spec = NULL; - TALLOC_CTX *ctx = talloc_tos(); - char pass[128]; - - if ((p = getenv("PASSWD_FD")) != NULL) { - spec = talloc_asprintf(ctx, - "descriptor %s", - p); - if (!spec) { - fprintf(stderr, "Out of memory.\n"); - exit(ENOMEM); - } - fd = atoi(p); - close_it = False; - } else if ((p = getenv("PASSWD_FILE")) != NULL) { - fd = sys_open(p, O_RDONLY, 0); - spec = talloc_strdup(ctx, p); - if (!spec) { - fprintf(stderr, "Out of memory.\n"); - exit(ENOMEM); - } - if (fd < 0) { - fprintf(stderr, "Error opening PASSWD_FILE %s: %s\n", - spec, strerror(errno)); - exit(1); - } - close_it = True; - } - - for(p = pass, *p = '\0'; /* ensure that pass is null-terminated */ - p && p - pass < sizeof(pass);) { - switch (read(fd, p, 1)) { - case 1: - if (*p != '\n' && *p != '\0') { - *++p = '\0'; /* advance p, and null-terminate pass */ - break; - } - case 0: - if (p - pass) { - *p = '\0'; /* null-terminate it, just in case... */ - p = NULL; /* then force the loop condition to become false */ - break; - } else { - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, "empty password\n"); - exit(1); - } - - default: - fprintf(stderr, "Error reading password from file %s: %s\n", - spec, strerror(errno)); - exit(1); - } - } - password = talloc_strdup(ctx, pass); - if (close_it) - close(fd); -} - -/**************************************************************************** -get username and password from a credentials file -exit on failure (from smbclient, move to libsmb or shared .c file?) -****************************************************************************/ - -static void read_credentials_file(const char *filename) -{ - FILE *auth; - fstring buf; - uint16 len = 0; - char *ptr, *val, *param; - - if ((auth=sys_fopen(filename, "r")) == NULL) - { - /* fail if we can't open the credentials file */ - DEBUG(0,("ERROR: Unable to open credentials file!\n")); - exit (-1); - } - - while (!feof(auth)) - { - /* get a line from the file */ - if (!fgets (buf, sizeof(buf), auth)) - continue; - len = strlen(buf); - - if ((len) && (buf[len-1]=='\n')) - { - buf[len-1] = '\0'; - len--; - } - if (len == 0) - continue; - - /* break up the line into parameter & value. - will need to eat a little whitespace possibly */ - param = buf; - if (!(ptr = strchr (buf, '='))) - continue; - val = ptr+1; - *ptr = '\0'; - - /* eat leading white space */ - while ((*val!='\0') && ((*val==' ') || (*val=='\t'))) - val++; - - if (strwicmp("password", param) == 0) - { - password = talloc_strdup(talloc_tos(),val); - got_pass = True; - } - else if (strwicmp("username", param) == 0) { - username = talloc_strdup(talloc_tos(), val); - } - - memset(buf, 0, sizeof(buf)); - } - fclose(auth); -} - - -/**************************************************************************** -usage on the program -****************************************************************************/ -static void usage(void) -{ - printf("Usage: mount.smbfs service mountpoint [-o options,...]\n"); - - printf("Version %s\n\n",SAMBA_VERSION_STRING); - - printf("Please be aware that smbfs is deprecated in favor of " - "cifs\n\n"); - - printf( -"Options:\n\ - username=<arg> SMB username\n\ - password=<arg> SMB password\n\ - credentials=<filename> file with username/password\n\ - krb use kerberos (active directory)\n\ - netbiosname=<arg> source NetBIOS name\n\ - uid=<arg> mount uid or username\n\ - gid=<arg> mount gid or groupname\n\ - port=<arg> remote SMB port number\n\ - fmask=<arg> file umask\n\ - dmask=<arg> directory umask\n\ - debug=<arg> debug level\n\ - ip=<arg> destination host or IP address\n\ - workgroup=<arg> workgroup on destination\n\ - sockopt=<arg> TCP socket options\n\ - scope=<arg> NetBIOS scope\n\ - iocharset=<arg> Linux charset (iso8859-1, utf8)\n\ - codepage=<arg> server codepage (cp850)\n\ - unicode use unicode when communicating with server\n\ - lfs large file system support\n\ - ttl=<arg> dircache time to live\n\ - guest don't prompt for a password\n\ - ro mount read-only\n\ - rw mount read-write\n\ -\n\ -This command is designed to be run from within /bin/mount by giving\n\ -the option '-t smbfs'. For example:\n\ - mount -t smbfs -o username=tridge,password=foobar //fjall/test /data/test\n\ -"); -} - - -/**************************************************************************** - Argument parsing for mount.smbfs interface - mount will call us like this: - mount.smbfs device mountpoint -o <options> - - <options> is never empty, containing at least rw or ro - ****************************************************************************/ -static void parse_mount_smb(int argc, char **argv) -{ - int opt; - char *opts; - char *opteq; - int val; - TALLOC_CTX *ctx = talloc_tos(); - - /* FIXME: This function can silently fail if the arguments are - * not in the expected order. - - > The arguments syntax of smbmount 2.2.3a (smbfs of Debian stable) - > requires that one gives "-o" before further options like username=... - > . Without -o, the username=.. setting is *silently* ignored. I've - > spent about an hour trying to find out why I couldn't log in now.. - - */ - - - if (argc < 2 || argv[1][0] == '-') { - usage(); - exit(1); - } - - service = talloc_strdup(ctx, argv[1]); - if (!service) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - mpoint = talloc_strdup(ctx, argv[2]); - if (!mpoint) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - - /* Convert any '/' characters in the service name to - '\' characters */ - string_replace(service, '/','\\'); - argc -= 2; - argv += 2; - - opt = getopt(argc, argv, "o:"); - if(opt != 'o') { - return; - } - - options = talloc_strdup(ctx, ""); - if (!options) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - - /* - * option parsing from nfsmount.c (util-linux-2.9u) - */ - for (opts = strtok(optarg, ","); opts; opts = strtok(NULL, ",")) { - DEBUG(3, ("opts: %s\n", opts)); - if ((opteq = strchr_m(opts, '='))) { - val = atoi(opteq + 1); - *opteq = '\0'; - - if (!strcmp(opts, "username") || - !strcmp(opts, "logon")) { - char *lp; - got_user = True; - username = talloc_strdup(ctx, opteq+1); - if (!username) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - if ((lp=strchr_m(username,'%'))) { - *lp = 0; - password = talloc_strdup(ctx, lp+1); - if (!password) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - got_pass = True; - memset(strchr_m(opteq+1,'%')+1,'X',strlen(password)); - } - if ((lp=strchr_m(username,'/'))) { - *lp = 0; - fstrcpy(workgroup,lp+1); - } - } else if(!strcmp(opts, "passwd") || - !strcmp(opts, "password")) { - password = talloc_strdup(ctx,opteq+1); - if (!password) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - got_pass = True; - memset(opteq+1,'X',strlen(password)); - } else if(!strcmp(opts, "credentials")) { - credentials = talloc_strdup(ctx,opteq+1); - if (!credentials) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - } else if(!strcmp(opts, "netbiosname")) { - fstrcpy(my_netbios_name,opteq+1); - } else if(!strcmp(opts, "uid")) { - mount_uid = nametouid(opteq+1); - } else if(!strcmp(opts, "gid")) { - mount_gid = nametogid(opteq+1); - } else if(!strcmp(opts, "port")) { - smb_port = val; - } else if(!strcmp(opts, "fmask")) { - mount_fmask = strtol(opteq+1, NULL, 8); - } else if(!strcmp(opts, "dmask")) { - mount_dmask = strtol(opteq+1, NULL, 8); - } else if(!strcmp(opts, "debug")) { - DEBUGLEVEL = val; - } else if(!strcmp(opts, "ip")) { - if (!interpret_string_addr(&dest_ip, opteq+1, - 0)) { - fprintf(stderr,"Can't resolve address %s\n", opteq+1); - exit(1); - } - have_ip = True; - } else if(!strcmp(opts, "workgroup")) { - fstrcpy(workgroup,opteq+1); - } else if(!strcmp(opts, "sockopt")) { - lp_do_parameter(-1, "socket options", opteq+1); - } else if(!strcmp(opts, "scope")) { - set_global_scope(opteq+1); - } else { - options = talloc_asprintf_append(options, - "%s=%s,", - opts, opteq+1); - if (!options) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - } - } else { - val = 1; - if(!strcmp(opts, "nocaps")) { - fprintf(stderr, "Unhandled option: %s\n", opteq+1); - exit(1); - } else if(!strcmp(opts, "guest")) { - password = talloc_strdup(talloc_tos(), ""); - if (!password) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - got_pass = True; - } else if(!strcmp(opts, "krb")) { -#ifdef HAVE_KRB5 - - use_kerberos = True; - if(!status32_smbfs) - fprintf(stderr, "Warning: kerberos support will only work for samba servers\n"); -#else - fprintf(stderr,"No kerberos support compiled in\n"); - exit(1); -#endif - } else if(!strcmp(opts, "rw")) { - mount_ro = 0; - } else if(!strcmp(opts, "ro")) { - mount_ro = 1; - } else if(!strcmp(opts, "unicode")) { - smbfs_has_unicode = True; - } else if(!strcmp(opts, "lfs")) { - smbfs_has_lfs = True; - } else { - options = talloc_asprintf_append(options, - "%s,", - opts); - if (!options) { - fprintf(stderr,"Out of memory\n"); - exit(ENOMEM); - } - } - } - } - - if (!service || !*service) { - usage(); - exit(1); - } - - if (options && *options && options[strlen(options)-1] == ',') { - options[strlen(options)-1] = '\0'; /* remove trailing , */ - DEBUG(3,("passthrough options '%s'\n", options)); - } -} - -/**************************************************************************** - main program -****************************************************************************/ - int main(int argc,char *argv[]) -{ - TALLOC_CTX *frame = talloc_stackframe(); - char *p; - - DEBUGLEVEL = 1; - - load_case_tables(); - - /* here we are interactive, even if run from autofs */ - setup_logging("mount.smbfs",True); - -#if 0 /* JRA - Urban says not needed ? */ - /* CLI_FORCE_ASCII=false makes smbmount negotiate unicode. The default - is to not announce any unicode capabilities as current smbfs does - not support it. */ - p = getenv("CLI_FORCE_ASCII"); - if (p && !strcmp(p, "false")) - unsetenv("CLI_FORCE_ASCII"); - else - setenv("CLI_FORCE_ASCII", "true", 1); -#endif - - in_client = True; /* Make sure that we tell lp_load we are */ - - if (getenv("USER")) { - username = talloc_strdup(frame, getenv("USER")); - if (!username) { - exit(ENOMEM); - } - - if ((p=strchr_m(username,'%'))) { - *p = 0; - password = talloc_strdup(frame, p+1); - if (!password) { - exit(ENOMEM); - } - got_pass = True; - memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password)); - } - strupper_m(username); - } - - if (getenv("PASSWD")) { - password = talloc_strdup(frame, getenv("PASSWD")); - if (!password) { - exit(ENOMEM); - } - got_pass = True; - } - - if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) { - get_password_file(); - got_pass = True; - } - - if ((!username || *username == 0) && getenv("LOGNAME")) { - username = talloc_strdup(frame, getenv("LOGNAME")); - if (!username) { - exit(ENOMEM); - } - } - - if (!lp_load(get_dyn_CONFIGFILE(),True,False,False,True)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", - get_dyn_CONFIGFILE()); - } - - parse_mount_smb(argc, argv); - - if (use_kerberos && !got_user) { - got_pass = True; - } - - if (credentials && *credentials != 0) { - read_credentials_file(credentials); - } - - DEBUG(3,("mount.smbfs started (version %s)\n", SAMBA_VERSION_STRING)); - - if (*workgroup == 0) { - fstrcpy(workgroup,lp_workgroup()); - } - - load_interfaces(); - if (!*my_netbios_name) { - fstrcpy(my_netbios_name, myhostname()); - } - strupper_m(my_netbios_name); - - init_mount(); - TALLOC_FREE(frame); - return 0; -} diff --git a/source3/client/smbumount.c b/source3/client/smbumount.c deleted file mode 100644 index e74c31299c..0000000000 --- a/source3/client/smbumount.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * smbumount.c - * - * Copyright (C) 1995-1998 by Volker Lendecke - * - */ - -#define SMBMOUNT_MALLOC 1 - -#include "includes.h" - -#include <mntent.h> - -#include <asm/types.h> -#include <asm/posix_types.h> -#include <linux/smb.h> -#include <linux/smb_mount.h> -#include <linux/smb_fs.h> - -/* This is a (hopefully) temporary hack due to the fact that - sizeof( uid_t ) != sizeof( __kernel_uid_t ) under glibc. - This may change in the future and smb.h may get fixed in the - future. In the mean time, it's ugly hack time - get over it. -*/ -#undef SMB_IOC_GETMOUNTUID -#define SMB_IOC_GETMOUNTUID _IOR('u', 1, __kernel_uid_t) - -#ifndef O_NOFOLLOW -#define O_NOFOLLOW 0400000 -#endif - -static void -usage(void) -{ - printf("usage: smbumount mountpoint\n\n"); - printf("Please be aware that smbfs is deprecated in favor of " - "cifs\n"); -} - -static int -umount_ok(const char *mount_point) -{ - /* we set O_NOFOLLOW to prevent users playing games with symlinks to - umount filesystems they don't own */ - int fid = open(mount_point, O_RDONLY|O_NOFOLLOW, 0); - __kernel_uid32_t mount_uid; - - if (fid == -1) { - fprintf(stderr, "Could not open %s: %s\n", - mount_point, strerror(errno)); - return -1; - } - - if (ioctl(fid, SMB_IOC_GETMOUNTUID32, &mount_uid) != 0) { - __kernel_uid_t mount_uid16; - if (ioctl(fid, SMB_IOC_GETMOUNTUID, &mount_uid16) != 0) { - fprintf(stderr, "%s probably not smb-filesystem\n", - mount_point); - return -1; - } - mount_uid = mount_uid16; - } - - if ((getuid() != 0) - && (mount_uid != getuid())) { - fprintf(stderr, "You are not allowed to umount %s\n", - mount_point); - return -1; - } - - close(fid); - return 0; -} - -/* Make a canonical pathname from PATH. Returns a freshly malloced string. - It is up the *caller* to ensure that the PATH is sensible. i.e. - canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.'' - is not a legal pathname for ``/dev/fd0'' Anything we cannot parse - we return unmodified. */ -static char * -canonicalize (char *path) -{ - char *canonical = (char*)malloc (PATH_MAX + 1); - - if (!canonical) { - fprintf(stderr, "Error! Not enough memory!\n"); - return NULL; - } - - if (strlen(path) > PATH_MAX) { - fprintf(stderr, "Mount point string too long\n"); - return NULL; - } - - if (path == NULL) - return NULL; - - if (realpath (path, canonical)) - return canonical; - - strncpy (canonical, path, PATH_MAX); - canonical[PATH_MAX] = '\0'; - return canonical; -} - - -int -main(int argc, char *argv[]) -{ - int fd; - char* mount_point; - struct mntent *mnt; - FILE* mtab; - FILE* new_mtab; - TALLOC_CTX *frame = talloc_stackframe(); - - if (argc != 2) { - usage(); - exit(1); - } - - if (geteuid() != 0) { - fprintf(stderr, "smbumount must be installed suid root\n"); - exit(1); - } - - mount_point = canonicalize(argv[1]); - - if (mount_point == NULL) - { - exit(1); - } - - if (umount_ok(mount_point) != 0) { - exit(1); - } - - if (umount(mount_point) != 0) { - fprintf(stderr, "Could not umount %s: %s\n", - mount_point, strerror(errno)); - exit(1); - } - - if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) - { - fprintf(stderr, "Can't get "MOUNTED"~ lock file"); - return 1; - } - close(fd); - - if ((mtab = setmntent(MOUNTED, "r")) == NULL) { - fprintf(stderr, "Can't open " MOUNTED ": %s\n", - strerror(errno)); - return 1; - } - -#define MOUNTED_TMP MOUNTED".tmp" - - if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) { - fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n", - strerror(errno)); - endmntent(mtab); - return 1; - } - - while ((mnt = getmntent(mtab)) != NULL) { - if (strcmp(mnt->mnt_dir, mount_point) != 0) { - addmntent(new_mtab, mnt); - } - } - - endmntent(mtab); - - if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { - fprintf(stderr, "Error changing mode of %s: %s\n", - MOUNTED_TMP, strerror(errno)); - exit(1); - } - - endmntent(new_mtab); - - if (rename(MOUNTED_TMP, MOUNTED) < 0) { - fprintf(stderr, "Cannot rename %s to %s: %s\n", - MOUNTED, MOUNTED_TMP, strerror(errno)); - exit(1); - } - - if (unlink(MOUNTED"~") == -1) - { - fprintf(stderr, "Can't remove "MOUNTED"~"); - return 1; - } - - TALLOC_FREE(frame); - return 0; -} |