~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/client/smbmnt.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  smbmnt.c
3
 
 *
4
 
 *  Copyright (C) 1995-1998 by Paal-Kr. Engstad and Volker Lendecke
5
 
 *  extensively modified by Tridge
6
 
 *
7
 
 *  This program is free software; you can redistribute it and/or modify
8
 
 *  it under the terms of the GNU General Public License as published by
9
 
 *  the Free Software Foundation; either version 2 of the License, or
10
 
 *  (at your option) any later version.
11
 
 *  
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *  
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 
 *
21
 
 */
22
 
 
23
 
#define SMBMOUNT_MALLOC 1
24
 
 
25
 
#include "includes.h"
26
 
 
27
 
#include <mntent.h>
28
 
#include <sys/utsname.h>
29
 
 
30
 
#include <asm/types.h>
31
 
#include <asm/posix_types.h>
32
 
#include <linux/smb.h>
33
 
#include <linux/smb_mount.h>
34
 
#include <asm/unistd.h>
35
 
 
36
 
#ifndef MS_MGC_VAL
37
 
/* This may look strange but MS_MGC_VAL is what we are looking for and
38
 
        is what we need from <linux/fs.h> under libc systems and is
39
 
        provided in standard includes on glibc systems.  So...  We
40
 
        switch on what we need...  */
41
 
#include <linux/fs.h>
42
 
#endif
43
 
 
44
 
static uid_t mount_uid;
45
 
static gid_t mount_gid;
46
 
static int mount_ro;
47
 
static unsigned mount_fmask;
48
 
static unsigned mount_dmask;
49
 
static int user_mount;
50
 
static char *options;
51
 
 
52
 
static void
53
 
help(void)
54
 
{
55
 
        printf("\n");
56
 
        printf("Usage: smbmnt mount-point [options]\n");
57
 
        printf("Version %s\n\n",SAMBA_VERSION_STRING);
58
 
        printf("-s share       share name on server\n"
59
 
               "-r             mount read-only\n"
60
 
               "-u uid         mount as uid\n"
61
 
               "-g gid         mount as gid\n"
62
 
               "-f mask        permission mask for files\n"
63
 
               "-d mask        permission mask for directories\n"
64
 
               "-o options     name=value, list of options\n"
65
 
               "-h             print this help text\n");
66
 
}
67
 
 
68
 
static int
69
 
parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share)
70
 
{
71
 
        int opt;
72
 
 
73
 
        while ((opt = getopt (argc, argv, "s:u:g:rf:d:o:")) != EOF)
74
 
        {
75
 
                switch (opt)
76
 
                {
77
 
                case 's':
78
 
                        *share = optarg;
79
 
                        break;
80
 
                case 'u':
81
 
                        if (!user_mount) {
82
 
                                mount_uid = strtol(optarg, NULL, 0);
83
 
                        }
84
 
                        break;
85
 
                case 'g':
86
 
                        if (!user_mount) {
87
 
                                mount_gid = strtol(optarg, NULL, 0);
88
 
                        }
89
 
                        break;
90
 
                case 'r':
91
 
                        mount_ro = 1;
92
 
                        break;
93
 
                case 'f':
94
 
                        mount_fmask = strtol(optarg, NULL, 8);
95
 
                        break;
96
 
                case 'd':
97
 
                        mount_dmask = strtol(optarg, NULL, 8);
98
 
                        break;
99
 
                case 'o':
100
 
                        options = optarg;
101
 
                        break;
102
 
                default:
103
 
                        return -1;
104
 
                }
105
 
        }
106
 
        return 0;
107
 
        
108
 
}
109
 
 
110
 
static char *
111
 
fullpath(const char *p)
112
 
{
113
 
        char path[PATH_MAX+1];
114
 
 
115
 
        if (strlen(p) > PATH_MAX) {
116
 
                return NULL;
117
 
        }
118
 
 
119
 
        if (realpath(p, path) == NULL) {
120
 
                fprintf(stderr,"Failed to find real path for mount point %s: %s\n",
121
 
                        p, strerror(errno));
122
 
                exit(1);
123
 
        }
124
 
        return strdup(path);
125
 
}
126
 
 
127
 
/* Check whether user is allowed to mount on the specified mount point. If it's
128
 
   OK then we change into that directory - this prevents race conditions */
129
 
static int mount_ok(char *mount_point)
130
 
{
131
 
        struct stat st;
132
 
 
133
 
        if (chdir(mount_point) != 0) {
134
 
                return -1;
135
 
        }
136
 
 
137
 
        if (stat(".", &st) != 0) {
138
 
                return -1;
139
 
        }
140
 
 
141
 
        if (!S_ISDIR(st.st_mode)) {
142
 
                errno = ENOTDIR;
143
 
                return -1;
144
 
        }
145
 
 
146
 
        if ((getuid() != 0) && 
147
 
            ((getuid() != st.st_uid) || 
148
 
             ((st.st_mode & S_IRWXU) != S_IRWXU))) {
149
 
                errno = EPERM;
150
 
                return -1;
151
 
        }
152
 
 
153
 
        return 0;
154
 
}
155
 
 
156
 
/* Tries to mount using the appropriate format. For 2.2 the struct,
157
 
   for 2.4 the ascii version. */
158
 
static int
159
 
do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
160
 
{
161
 
        pstring opts;
162
 
        struct utsname uts;
163
 
        char *release, *major, *minor;
164
 
        char *data1, *data2;
165
 
 
166
 
        uname(&uts);
167
 
        release = uts.release;
168
 
        major = strtok(release, ".");
169
 
        minor = strtok(NULL, ".");
170
 
        if (major && minor && atoi(major) == 2 && atoi(minor) < 4) {
171
 
                /* < 2.4, assume struct */
172
 
                data1 = (char *) data;
173
 
                data2 = opts;
174
 
        } else {
175
 
                /* >= 2.4, assume ascii but fall back on struct */
176
 
                data1 = opts;
177
 
                data2 = (char *) data;
178
 
        }
179
 
 
180
 
        slprintf(opts, sizeof(opts)-1,
181
 
                 "version=7,uid=%d,gid=%d,file_mode=0%o,dir_mode=0%o,%s",
182
 
                 mount_uid, mount_gid, data->file_mode, data->dir_mode,options);
183
 
        if (mount(share_name, ".", "smbfs", flags, data1) == 0)
184
 
                return 0;
185
 
        return mount(share_name, ".", "smbfs", flags, data2);
186
 
}
187
 
 
188
 
 int main(int argc, char *argv[])
189
 
{
190
 
        char *mount_point, *share_name = NULL;
191
 
        FILE *mtab;
192
 
        int fd;
193
 
        unsigned int flags;
194
 
        struct smb_mount_data data;
195
 
        struct mntent ment;
196
 
 
197
 
        memset(&data, 0, sizeof(struct smb_mount_data));
198
 
 
199
 
        if (argc < 2) {
200
 
                help();
201
 
                exit(1);
202
 
        }
203
 
 
204
 
        if (argv[1][0] == '-') {
205
 
                help();
206
 
                exit(1);
207
 
        }
208
 
 
209
 
        if (getuid() != 0) {
210
 
                user_mount = 1;
211
 
        }
212
 
 
213
 
        if (geteuid() != 0) {
214
 
                fprintf(stderr, "smbmnt must be installed suid root for direct user mounts (%d,%d)\n", getuid(), geteuid());
215
 
                exit(1);
216
 
        }
217
 
 
218
 
        mount_uid = getuid();
219
 
        mount_gid = getgid();
220
 
        mount_fmask = umask(0);
221
 
        umask(mount_fmask);
222
 
        mount_fmask = ~mount_fmask;
223
 
 
224
 
        mount_point = fullpath(argv[1]);
225
 
 
226
 
        argv += 1;
227
 
        argc -= 1;
228
 
 
229
 
        if (mount_ok(mount_point) != 0) {
230
 
                fprintf(stderr, "cannot mount on %s: %s\n",
231
 
                        mount_point, strerror(errno));
232
 
                exit(1);
233
 
        }
234
 
 
235
 
        data.version = SMB_MOUNT_VERSION;
236
 
 
237
 
        /* getuid() gives us the real uid, who may umount the fs */
238
 
        data.mounted_uid = getuid();
239
 
 
240
 
        if (parse_args(argc, argv, &data, &share_name) != 0) {
241
 
                help();
242
 
                return -1;
243
 
        }
244
 
 
245
 
        data.uid = mount_uid;    // truncates to 16-bits here!!!
246
 
        data.gid = mount_gid;
247
 
        data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_fmask;
248
 
        data.dir_mode  = (S_IRWXU|S_IRWXG|S_IRWXO) & mount_dmask;
249
 
 
250
 
        if (mount_dmask == 0) {
251
 
                data.dir_mode = data.file_mode;
252
 
                if ((data.dir_mode & S_IRUSR) != 0)
253
 
                        data.dir_mode |= S_IXUSR;
254
 
                if ((data.dir_mode & S_IRGRP) != 0)
255
 
                        data.dir_mode |= S_IXGRP;
256
 
                if ((data.dir_mode & S_IROTH) != 0)
257
 
                        data.dir_mode |= S_IXOTH;
258
 
        }
259
 
 
260
 
        flags = MS_MGC_VAL | MS_NOSUID | MS_NODEV;
261
 
 
262
 
        if (mount_ro) flags |= MS_RDONLY;
263
 
 
264
 
        if (do_mount(share_name, flags, &data) < 0) {
265
 
                switch (errno) {
266
 
                case ENODEV:
267
 
                        fprintf(stderr, "ERROR: smbfs filesystem not supported by the kernel\n");
268
 
                        break;
269
 
                default:
270
 
                        perror("mount error");
271
 
                }
272
 
                fprintf(stderr, "Please refer to the smbmnt(8) manual page\n");
273
 
                return -1;
274
 
        }
275
 
 
276
 
        ment.mnt_fsname = share_name ? share_name : "none";
277
 
        ment.mnt_dir = mount_point;
278
 
        ment.mnt_type = "smbfs";
279
 
        ment.mnt_opts = "";
280
 
        ment.mnt_freq = 0;
281
 
        ment.mnt_passno= 0;
282
 
 
283
 
        mount_point = ment.mnt_dir;
284
 
 
285
 
        if (mount_point == NULL)
286
 
        {
287
 
                fprintf(stderr, "Mount point too long\n");
288
 
                return -1;
289
 
        }
290
 
        
291
 
        if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
292
 
        {
293
 
                fprintf(stderr, "Can't get "MOUNTED"~ lock file");
294
 
                return 1;
295
 
        }
296
 
        close(fd);
297
 
        
298
 
        if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
299
 
        {
300
 
                fprintf(stderr, "Can't open " MOUNTED);
301
 
                return 1;
302
 
        }
303
 
 
304
 
        if (addmntent(mtab, &ment) == 1)
305
 
        {
306
 
                fprintf(stderr, "Can't write mount entry");
307
 
                return 1;
308
 
        }
309
 
        if (fchmod(fileno(mtab), 0644) == -1)
310
 
        {
311
 
                fprintf(stderr, "Can't set perms on "MOUNTED);
312
 
                return 1;
313
 
        }
314
 
        endmntent(mtab);
315
 
 
316
 
        if (unlink(MOUNTED"~") == -1)
317
 
        {
318
 
                fprintf(stderr, "Can't remove "MOUNTED"~");
319
 
                return 1;
320
 
        }
321
 
 
322
 
        return 0;
323
 
}