diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/client/smbmnt.c | 297 | ||||
-rw-r--r-- | source3/client/smbmount.c | 941 | ||||
-rw-r--r-- | source3/client/smbumount.c | 191 |
3 files changed, 1429 insertions, 0 deletions
diff --git a/source3/client/smbmnt.c b/source3/client/smbmnt.c new file mode 100644 index 0000000000..9bb7f56672 --- /dev/null +++ b/source3/client/smbmnt.c @@ -0,0 +1,297 @@ +/* + * smbmount.c + * + * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke + * + */ + +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <pwd.h> +#include <grp.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/stat.h> +#include <sys/types.h> +/* #include <sys/wait.h> */ /* generates a warning here */ +extern pid_t waitpid(pid_t, int *, int); +#include <sys/errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> +#include <stdlib.h> +#include <sys/mount.h> +#include <mntent.h> + +#include <linux/fs.h> +#include <linux/smb.h> +#include <linux/smb_mount.h> + +#include <asm/unistd.h> + +static char *progname; + + +static void +usage(void) +{ + printf("usage: %s mount-point [options]\n", progname); + printf("Try `%s -h' for more information\n", progname); +} + +static void +help(void) +{ + printf("\n"); + printf("usage: %s mount-point [options]\n", progname); + printf("-u uid uid the mounted files get\n" + "-g gid gid the mounted files get\n" + "-f mode permission the files get (octal notation)\n" + "-d mode permission the dirs get (octal notation)\n" + "-P pid connection handler's pid\n\n" + "-h print this help text\n"); +} + +static int +parse_args(int argc, char *argv[], struct smb_mount_data *data) +{ + int opt; + struct passwd *pwd; + struct group *grp; + + while ((opt = getopt (argc, argv, "u:g:f:d:")) + != EOF) + { + switch (opt) + { + case 'u': + if (isdigit(optarg[0])) + { + data->uid = atoi(optarg); + } + else + { + pwd = getpwnam(optarg); + if (pwd == NULL) + { + fprintf(stderr, "Unknown user: %s\n", + optarg); + return 1; + } + data->uid = pwd->pw_uid; + } + break; + case 'g': + if (isdigit(optarg[0])) + { + data->gid = atoi(optarg); + } + else + { + grp = getgrnam(optarg); + if (grp == NULL) + { + fprintf(stderr, "Unknown group: %s\n", + optarg); + return 1; + } + data->gid = grp->gr_gid; + } + break; + case 'f': + data->file_mode = strtol(optarg, NULL, 8); + break; + case 'd': + data->dir_mode = strtol(optarg, NULL, 8); + break; + default: + return -1; + } + } + return 0; + +} + +static char * +fullpath(const char *p) +{ + char path[MAXPATHLEN]; + + if (strlen(p) > MAXPATHLEN-1) + { + return NULL; + } + + if (realpath(p, path) == NULL) + { + return strdup(p); + } + return strdup(path); +} + +/* Check whether user is allowed to mount on the specified mount point */ +static int +mount_ok(struct stat *st) +{ + 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; +} + +int +main(int argc, char *argv[]) +{ + struct smb_mount_data data; + struct stat st; + + int fd; + int um; + unsigned int flags; + + char *mount_point; + + struct mntent ment; + FILE *mtab; + + progname = argv[0]; + + memset(&data, 0, sizeof(struct smb_mount_data)); + + if ( (argc == 2) + && (argv[1][0] == '-') + && (argv[1][1] == 'h') + && (argv[1][2] == '\0')) + { + help(); + return 0; + } + + if (geteuid() != 0) { + fprintf(stderr, "%s must be installed suid root\n", progname); + exit(1); + } + + if (argc < 2) + { + usage(); + return 1; + } + + mount_point = argv[1]; + + argv += 1; + argc -= 1; + + if (stat(mount_point, &st) == -1) { + fprintf(stderr, "could not find mount point %s: %s\n", + mount_point, strerror(errno)); + exit(1); + } + + if (mount_ok(&st) != 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(); + + data.uid = getuid(); + data.gid = getgid(); + um = umask(0); + umask(um); + data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um; + data.dir_mode = 0; + + if (parse_args(argc, argv, &data) != 0) { + usage(); + return -1; + } + + if (data.dir_mode == 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; + + if (mount(NULL, mount_point, "smbfs", + flags, (char *)&data) < 0) { + perror("mount error"); + printf("Please look at smbmount's manual page for " + "possible reasons\n"); + return -1; + } + + ment.mnt_fsname = "none"; + ment.mnt_dir = fullpath(mount_point); + ment.mnt_type = "smbfs"; + ment.mnt_opts = ""; + 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 new file mode 100644 index 0000000000..2ef426abc0 --- /dev/null +++ b/source3/client/smbmount.c @@ -0,0 +1,941 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB client + Copyright (C) Andrew Tridgell 1994-1997 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" +#include <linux/smb_fs.h> +static struct smb_conn_opt conn_options; + +#ifndef REGISTER +#define REGISTER 0 +#endif + +pstring cur_dir = "\\"; +pstring cd_path = ""; +extern pstring service; +extern pstring desthost; +extern pstring myname; +extern pstring myhostname; +extern pstring password; +extern pstring username; +extern pstring workgroup; +char *cmdstr=""; +extern BOOL got_pass; +extern BOOL connect_as_printer; +extern BOOL connect_as_ipc; +extern struct in_addr ipzero; + +extern BOOL doencrypt; + +extern pstring user_socket_options; + +/* 30 second timeout on most commands */ +#define CLIENT_TIMEOUT (30*1000) +#define SHORT_TIMEOUT (5*1000) + +/* value for unused fid field in trans2 secondary request */ +#define FID_UNUSED (0xFFFF) + +extern int name_type; + +extern int max_protocol; + + +time_t newer_than = 0; +int archive_level = 0; + +extern pstring debugf; +extern int DEBUGLEVEL; + +BOOL translation = False; + +extern int cnum; +extern int mid; +extern int pid; +extern int tid; +extern int gid; +extern int uid; + +extern BOOL have_ip; +extern int max_xmit; + +/* clitar bits insert */ +extern int blocksize; +extern BOOL tar_inc; +extern BOOL tar_reset; +/* clitar bits end */ + + +int myumask = 0755; + +extern pstring scope; + +BOOL prompt = True; + +int printmode = 1; + +BOOL recurse = False; +BOOL lowercase = False; + +struct in_addr dest_ip; + +#define SEPARATORS " \t\n\r" + +BOOL abort_mget = True; + +extern int Protocol; + +extern BOOL readbraw_supported ; +extern BOOL writebraw_supported; + +pstring fileselection = ""; + +extern file_info def_finfo; + +/* timing globals */ +int get_total_size = 0; +int get_total_time_ms = 0; +int put_total_size = 0; +int put_total_time_ms = 0; + +/* totals globals */ +int dir_total = 0; + +extern int Client; + +#define USENMB + +static BOOL setup_term_code(char *code) +{ + interpret_coding_system(code); + return True; +} +#define CNV_LANG(s) dos2unix_format(s,False) +#define CNV_INPUT(s) unix2dos_format(s,True) + +/**************************************************************************** +check for existance of a dir +****************************************************************************/ +static BOOL chkpath(char *path,BOOL report) +{ + fstring path2; + pstring inbuf,outbuf; + char *p; + + strcpy(path2,path); + trim_string(path2,NULL,"\\"); + if (!*path2) *path2 = '\\'; + + bzero(outbuf,smb_size); + set_message(outbuf,0,4 + strlen(path2),True); + SCVAL(outbuf,smb_com,SMBchkpth); + SSVAL(outbuf,smb_tid,cnum); + cli_setup_pkt(outbuf); + + p = smb_buf(outbuf); + *p++ = 4; + strcpy(p,path2); + +#if 0 + { + /* this little bit of code can be used to extract NT error codes. + Just feed a bunch of "cd foo" commands to smbclient then watch + in netmon (tridge) */ + static int code=0; + SIVAL(outbuf, smb_rcls, code | 0xC0000000); + SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14)); + code++; + } +#endif + + send_smb(Client,outbuf); + client_receive_smb(Client,inbuf,CLIENT_TIMEOUT); + + if (report && CVAL(inbuf,smb_rcls) != 0) + DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf))); + + return(CVAL(inbuf,smb_rcls) == 0); +} + + +/* #define SMBFS_DEBUG 1 */ + +static void +daemonize(void) +{ + int i; + if ((i = fork()) < 0) + { + DEBUG(0, ("could not fork\n")); + } + if (i > 0) + { + /* parent simply exits */ + exit(0); + } + setsid(); + chdir("/"); +} + +static void +close_our_files(void) +{ + int i; + for (i = 0; i < NR_OPEN; i++) { + if (i == Client) { + continue; + } + close(i); + } +} + +static void +usr1_handler(int x) +{ + return; +} + +/* + * Send a login and store the connection options. This is a separate + * function to keep clientutil.c independent of linux kernel changes. + */ +static BOOL mount_send_login(char *inbuf, char *outbuf) +{ + struct connection_options opt; + int res = cli_send_login(inbuf, outbuf, True, True, &opt); + + if (!res) + return res; + + conn_options.protocol = opt.protocol; + conn_options.case_handling = CASE_LOWER; + conn_options.max_xmit = opt.max_xmit; + conn_options.server_uid = opt.server_uid; + conn_options.tid = opt.tid; + conn_options.secmode = opt.sec_mode; + conn_options.maxmux = opt.max_mux; + conn_options.maxvcs = opt.max_vcs; + conn_options.rawmode = opt.rawmode; + conn_options.sesskey = opt.sesskey; + conn_options.maxraw = opt.maxraw; + conn_options.capabilities = opt.capabilities; + conn_options.serverzone = opt.serverzone; + + return True; +} + +/* + * 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 *mount_point, char *inbuf, char *outbuf) +{ + int fd, closed = 0, res = 1; + + while (1) + { + if ((fd = open(mount_point, O_RDONLY)) < 0) + { +#ifdef SMBFS_DEBUG + printf("smbclient: can't open %s\n", mount_point); +#endif + break; + } + + /* + * Call the ioctl even if we couldn't get a socket ... + * there's no point in making smbfs wait for a timeout. + */ + conn_options.fd = -1; + if (res) + conn_options.fd = Client; + res = ioctl(fd, SMB_IOC_NEWCONN, &conn_options); + if (res != 0) + { +#ifdef SMBFS_DEBUG + printf("smbclient: ioctl failed, res=%d\n",res); +#endif + } + + close_sockets(); + close(fd); + /* + * Close all open files if we haven't done so yet. + */ +#ifndef SMBFS_DEBUG + if (!closed) + { + closed = 1; + close_our_files(); + } +#endif + + /* + * Wait for a signal from smbfs ... + */ + signal(SIGUSR1, &usr1_handler); + pause(); +#ifdef SMBFS_DEBUG + printf("smbclient: got signal, getting new socket\n"); +#endif + + res = mount_send_login(inbuf,outbuf); + if (!res) + { +#ifdef SMBFS_DEBUG + printf("smbclient: login failed\n"); +#endif + } + } +#ifdef SMBFS_DEBUG + printf("smbclient: exit\n"); +#endif + exit(1); +} + +/**************************************************************************** +mount smbfs +****************************************************************************/ +static void cmd_mount(char *inbuf,char *outbuf) +{ + pstring mpoint; + char mount_point[MAXPATHLEN+1]; + pstring mount_command; + fstring buf; + int retval; + + if (!next_token(NULL, mpoint, NULL)) + { + DEBUG(0,("You must supply a mount point\n")); + return; + } + + memset(mount_point, 0, sizeof(mount_point)); + + if (realpath(mpoint, mount_point) == NULL) + { + DEBUG(0, ("Could not resolve mount point\n")); + return; + } + + sprintf(mount_command, "smbmnt %s", mount_point); + + while(next_token(NULL, buf, NULL)) + { + strcat(mount_command, " "); + strcat(mount_command, buf); + } + + DEBUG(3,("mount command: %s\n", mount_command)); + + /* + * Create the background process before trying the mount. + * (We delay closing files to allow diagnostic messages.) + */ + daemonize(); + + /* The parent has exited here, the child handles the connection: */ + if ((retval = system(mount_command)) != 0) + { + DEBUG(0,("mount failed\n")); + exit(1); + } + send_fs_socket(mount_point, inbuf, outbuf); +} + + + + + +/* This defines the commands supported by this client */ +struct +{ + char *name; + void (*fn)(); + char *description; +} commands[] = +{ + {"mount", cmd_mount, "<mount-point options> mount an smbfs file system"}, + {"",NULL,NULL} +}; + + +/******************************************************************* + lookup a command string in the list of commands, including + abbreviations + ******************************************************************/ +static int process_tok(fstring tok) +{ + int i = 0, matches = 0; + int cmd=0; + int tok_len = strlen(tok); + + while (commands[i].fn != NULL) + { + if (strequal(commands[i].name,tok)) + { + matches = 1; + cmd = i; + break; + } + else if (strnequal(commands[i].name, tok, tok_len)) + { + matches++; + cmd = i; + } + i++; + } + + if (matches == 0) + return(-1); + else if (matches == 1) + return(cmd); + else + return(-2); +} + +/**************************************************************************** +help +****************************************************************************/ +void cmd_help(void) +{ + int i=0,j; + fstring buf; + + if (next_token(NULL,buf,NULL)) + { + if ((i = process_tok(buf)) >= 0) + DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description)); + } + else + while (commands[i].description) + { + for (j=0; commands[i].description && (j<5); j++) { + DEBUG(0,("%-15s",commands[i].name)); + i++; + } + DEBUG(0,("\n")); + } +} + +/**************************************************************************** +wait for keyboard activity, swallowing network packets +****************************************************************************/ +#ifdef CLIX +static char wait_keyboard(char *buffer) +#else +static void wait_keyboard(char *buffer) +#endif +{ + fd_set fds; + int selrtn; + struct timeval timeout; + +#ifdef CLIX + int delay = 0; +#endif + + while (1) + { + extern int Client; + FD_ZERO(&fds); + FD_SET(Client,&fds); +#ifndef CLIX + FD_SET(fileno(stdin),&fds); +#endif + + timeout.tv_sec = 20; + timeout.tv_usec = 0; +#ifdef CLIX + timeout.tv_sec = 0; +#endif + selrtn = sys_select(&fds,&timeout); + +#ifndef CLIX + if (FD_ISSET(fileno(stdin),&fds)) + return; +#else + { + char ch; + int readret; + + set_blocking(fileno(stdin), False); + readret = read_data( fileno(stdin), &ch, 1); + set_blocking(fileno(stdin), True); + if (readret == -1) + { + if (errno != EAGAIN) + { + /* should crash here */ + DEBUG(1,("readchar stdin failed\n")); + } + } + else if (readret != 0) + { + return ch; + } + } +#endif + + /* We deliberately use receive_smb instead of + client_receive_smb as we want to receive + session keepalives and then drop them here. + */ + if (FD_ISSET(Client,&fds)) + receive_smb(Client,buffer,0); + +#ifdef CLIX + delay++; + if (delay > 100000) + { + delay = 0; + chkpath("\\",False); + } +#else + chkpath("\\",False); +#endif + } +} + + +/**************************************************************************** + process commands from the client +****************************************************************************/ +static BOOL process(char *base_directory) +{ + extern FILE *dbf; + pstring line; + char *cmd; + + char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + + if ((InBuffer == NULL) || (OutBuffer == NULL)) + return(False); + + bzero(OutBuffer,smb_size); + + if (!mount_send_login(InBuffer,OutBuffer)) + return(False); + + cmd = cmdstr; + if (cmd[0] != '\0') while (cmd[0] != '\0') + { + char *p; + fstring tok; + int i; + + if ((p = strchr(cmd, ';')) == 0) + { + strncpy(line, cmd, 999); + line[1000] = '\0'; + cmd += strlen(cmd); + } + else + { + if (p - cmd > 999) p = cmd + 999; + strncpy(line, cmd, p - cmd); + line[p - cmd] = '\0'; + cmd = p + 1; + } + + /* input language code to internal one */ + CNV_INPUT (line); + + /* and get the first part of the command */ + { + char *ptr = line; + if (!next_token(&ptr,tok,NULL)) continue; + } + + if ((i = process_tok(tok)) >= 0) + commands[i].fn(InBuffer,OutBuffer); + else if (i == -2) + DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok))); + else + DEBUG(0,("%s: command not found\n",CNV_LANG(tok))); + } + else while (!feof(stdin)) + { + fstring tok; + int i; + + bzero(OutBuffer,smb_size); + + /* display a prompt */ + DEBUG(0,("smb: %s> ", CNV_LANG(cur_dir))); + fflush(dbf); + +#ifdef CLIX + line[0] = wait_keyboard(InBuffer); + /* this might not be such a good idea... */ + if ( line[0] == EOF) + break; +#else + wait_keyboard(InBuffer); +#endif + + /* and get a response */ +#ifdef CLIX + fgets( &line[1],999, stdin); +#else + if (!fgets(line,1000,stdin)) + break; +#endif + + /* input language code to internal one */ + CNV_INPUT (line); + + /* special case - first char is ! */ + if (*line == '!') + { + system(line + 1); + continue; + } + + /* and get the first part of the command */ + { + char *ptr = line; + if (!next_token(&ptr,tok,NULL)) continue; + } + + if ((i = process_tok(tok)) >= 0) + commands[i].fn(InBuffer,OutBuffer); + else if (i == -2) + DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok))); + else + DEBUG(0,("%s: command not found\n",CNV_LANG(tok))); + } + + cli_send_logout(); + return(True); +} + +/**************************************************************************** +usage on the program +****************************************************************************/ +static void usage(char *pname) +{ + DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ", + pname)); + + DEBUG(0,("\nVersion %s\n",VERSION)); + DEBUG(0,("\t-p port connect to the specified port\n")); + DEBUG(0,("\t-d debuglevel set the debuglevel\n")); + DEBUG(0,("\t-l log basename. Basename for log/debug files\n")); + DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n")); + DEBUG(0,("\t-N don't ask for a password\n")); + DEBUG(0,("\t-P connect to service as a printer\n")); + DEBUG(0,("\t-M host send a winpopup message to the host\n")); + DEBUG(0,("\t-m max protocol set the max protocol level\n")); + DEBUG(0,("\t-L host get a list of shares available on a host\n")); + DEBUG(0,("\t-I dest IP use this IP to connect to\n")); + DEBUG(0,("\t-E write messages to stderr instead of stdout\n")); + DEBUG(0,("\t-U username set the network username\n")); + DEBUG(0,("\t-W workgroup set the workgroup name\n")); + DEBUG(0,("\t-c command string execute semicolon separated commands\n")); + DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n")); + DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n")); + DEBUG(0,("\t-D directory start from directory\n")); + DEBUG(0,("\n")); +} + +/**************************************************************************** + main program +****************************************************************************/ + int main(int argc,char *argv[]) +{ + fstring base_directory; + char *pname = argv[0]; + int port = SMB_PORT; + int opt; + extern FILE *dbf; + extern char *optarg; + extern int optind; + pstring query_host; + BOOL nt_domain_logon = False; + static pstring servicesf = CONFIGFILE; + pstring term_code; + char *p; + +#ifdef KANJI + strcpy(term_code, KANJI); +#else /* KANJI */ + *term_code = 0; +#endif /* KANJI */ + + *query_host = 0; + *base_directory = 0; + + DEBUGLEVEL = 2; + + setup_logging(pname,True); + + TimeInit(); + charset_initialise(); + + pid = getpid(); + uid = getuid(); + gid = getgid(); + mid = pid + 100; + myumask = umask(0); + umask(myumask); + + if (getenv("USER")) + { + strcpy(username,getenv("USER")); + + /* modification to support userid%passwd syntax in the USER var + 25.Aug.97, jdblair@uab.edu */ + + if ((p=strchr(username,'%'))) + { + *p = 0; + strcpy(password,p+1); + got_pass = True; + memset(strchr(getenv("USER"),'%')+1,'X',strlen(password)); + } + strupper(username); + } + + /* modification to support PASSWD environmental var + 25.Aug.97, jdblair@uab.edu */ + + if (getenv("PASSWD")) + strcpy(password,getenv("PASSWD")); + + if (*username == 0 && getenv("LOGNAME")) + { + strcpy(username,getenv("LOGNAME")); + strupper(username); + } + + if (argc < 2) + { + usage(pname); + exit(1); + } + + if (*argv[1] != '-') + { + + strcpy(service,argv[1]); + /* Convert any '/' characters in the service name to '\' characters */ + string_replace( service, '/','\\'); + argc--; + argv++; + + if (count_chars(service,'\\') < 3) + { + usage(pname); + printf("\n%s: Not enough '\\' characters in service\n",service); + exit(1); + } + +/* + if (count_chars(service,'\\') > 3) + { + usage(pname); + printf("\n%s: Too many '\\' characters in service\n",service); + exit(1); + } + */ + + if (argc > 1 && (*argv[1] != '-')) + { + got_pass = True; + strcpy(password,argv[1]); + memset(argv[1],'X',strlen(argv[1])); + argc--; + argv++; + } + } + + while ((opt = + getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF) + switch (opt) + { + case 'm': + max_protocol = interpret_protocol(optarg,max_protocol); + break; + case 'O': + strcpy(user_socket_options,optarg); + break; + case 'S': + strcpy(desthost,optarg); + strupper(desthost); + nt_domain_logon = True; + break; + case 'B': + iface_set_default(NULL,optarg,NULL); + break; + case 'D': + strcpy(base_directory,optarg); + break; + case 'i': + strcpy(scope,optarg); + break; + case 'U': + { + char *lp; + strcpy(username,optarg); + if ((lp=strchr(username,'%'))) + { + *lp = 0; + strcpy(password,lp+1); + got_pass = True; + memset(strchr(optarg,'%')+1,'X',strlen(password)); + } + } + + break; + case 'W': + strcpy(workgroup,optarg); + break; + case 'E': + dbf = stderr; + break; + case 'I': + { + dest_ip = *interpret_addr2(optarg); + if (zero_ip(dest_ip)) exit(1); + have_ip = True; + } + break; + case 'n': + strcpy(myname,optarg); + break; + case 'N': + got_pass = True; + break; + case 'd': + if (*optarg == 'A') + DEBUGLEVEL = 10000; + else + DEBUGLEVEL = atoi(optarg); + break; + case 'l': + sprintf(debugf,"%s.client",optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'c': + cmdstr = optarg; + got_pass = True; + break; + case 'h': + usage(pname); + exit(0); + break; + case 's': + strcpy(servicesf, optarg); + break; + case 't': + strcpy(term_code, optarg); + break; + default: + usage(pname); + exit(1); + } + + if (!*query_host && !*service) + { + usage(pname); + exit(1); + } + + + DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION)); + + if(!get_myname(myhostname,NULL)) + { + DEBUG(0,("Failed to get my hostname.\n")); + } + + if (!lp_load(servicesf,True)) { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); + } + + codepage_initialise(lp_client_code_page()); + + if(lp_client_code_page() == KANJI_CODEPAGE) + { + if (!setup_term_code (term_code)) + { + DEBUG(0, ("%s: unknown terminal code name\n", optarg)); + usage (pname); + exit (1); + } + } + + if (*workgroup == 0) + strcpy(workgroup,lp_workgroup()); + + load_interfaces(); + get_myname((*myname)?NULL:myname,NULL); + strupper(myname); + +#ifdef NTDOMAIN + + if (nt_domain_logon) + { + int ret = 0; + sprintf(service,"\\\\%s\\IPC$",query_host); + strupper(service); + connect_as_ipc = True; + + DEBUG(5,("NT Domain Logon. Service: %s\n", service)); + + if (cli_open_sockets(port)) + { + if (!cli_send_login(NULL,NULL,True,True,NULL)) return(1); + + do_nt_login(desthost, myhostname, Client, cnum); + + cli_send_logout(); + close_sockets(); + } + + return(ret); + } +#endif + + if (cli_open_sockets(port)) + { + if (!process(base_directory)) + { + close_sockets(); + return(1); + } + close_sockets(); + } + else + return(1); + + return(0); +} diff --git a/source3/client/smbumount.c b/source3/client/smbumount.c new file mode 100644 index 0000000000..304da24ff6 --- /dev/null +++ b/source3/client/smbumount.c @@ -0,0 +1,191 @@ +/* + * smbumount.c + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <pwd.h> +#include <grp.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/stat.h> +#include <sys/types.h> +/* #include <sys/wait.h> */ /* generates a warning here */ +extern pid_t waitpid(pid_t, int *, int); +#include <sys/errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> +#include <stdlib.h> +#include <sys/mount.h> +#include <mntent.h> + +#include <sys/ioctl.h> +#include <linux/fs.h> +#include <linux/smb.h> +#include <linux/smb_mount.h> +#include <linux/smb_fs.h> + +static char *progname; + +static void +usage(void) +{ + printf("usage: %s mount-point\n", progname); +} + +static int +umount_ok(const char *mount_point) +{ + int fid = open(mount_point, O_RDONLY, 0); + uid_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_GETMOUNTUID, &mount_uid) != 0) { + fprintf(stderr, "%s probably not smb-filesystem\n", + mount_point); + return -1; + } + + 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. */ +char * +canonicalize (const char *path) +{ + char *canonical = malloc (PATH_MAX + 1); + + 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; + + strcpy (canonical, path); + return canonical; +} + + +int +main(int argc, char *argv[]) +{ + int fd; + + char* mount_point; + + struct mntent *mnt; + FILE* mtab; + FILE* new_mtab; + + progname = argv[0]; + + if (argc != 2) { + usage(); + exit(1); + } + + if (geteuid() != 0) { + fprintf(stderr, "%s must be installed suid root\n", progname); + 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; + } + + return 0; +} |