~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/client/mount.cifs.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define _GNU_SOURCE
 
2
 
 
3
#include <stdlib.h>
 
4
#include <unistd.h>
 
5
#include <pwd.h>
 
6
#include <sys/types.h>
 
7
#include <sys/mount.h>
 
8
#include <sys/stat.h>
 
9
#include <sys/utsname.h>
 
10
#include <sys/socket.h>
 
11
#include <arpa/inet.h>
 
12
#include <getopt.h>
 
13
#include <errno.h>
 
14
#include <netdb.h>
 
15
#include <string.h>
 
16
#include <mntent.h>
 
17
 
 
18
#define MOUNT_CIFS_VERSION "1"
 
19
 
 
20
extern char *getusername(void);
 
21
 
 
22
char * thisprogram;
 
23
int verboseflag = 0;
 
24
static int got_password = 0;
 
25
static int got_user = 0;
 
26
static int got_domain = 0;
 
27
static int got_ip = 0;
 
28
static int got_unc = 0;
 
29
static int got_uid = 0;
 
30
static int got_gid = 0;
 
31
static char * user_name = NULL;
 
32
char * mountpassword = NULL;
 
33
 
 
34
 
 
35
void mount_cifs_usage()
 
36
{
 
37
        printf("\nUsage:  %s remotetarget dir\n", thisprogram);
 
38
        printf("\nMount the remotetarget, specified as either a UNC name or ");
 
39
        printf(" CIFS URL, to the local directory, dir.\n");
 
40
 
 
41
        exit(1);
 
42
}
 
43
 
 
44
/* caller frees username if necessary */
 
45
char * getusername() {
 
46
        char *username = NULL;
 
47
        struct passwd *password = getpwuid(getuid());
 
48
 
 
49
        if (password) {
 
50
                username = password->pw_name;
 
51
        }
 
52
        return username;
 
53
}
 
54
 
 
55
char * parse_cifs_url(unc_name)
 
56
{
 
57
        printf("\ncifs url %s\n",unc_name);
 
58
}
 
59
 
 
60
int parse_options(char * options)
 
61
{
 
62
        char * data;
 
63
        char * value = 0;
 
64
 
 
65
        if (!options)
 
66
                return 1;
 
67
 
 
68
        while ((data = strsep(&options, ",")) != NULL) {
 
69
                if (!*data)
 
70
                        continue;
 
71
                if ((value = strchr(data, '=')) != NULL) {
 
72
                        *value++ = '\0';
 
73
                }
 
74
                if (strncmp(data, "user", 4) == 0) {
 
75
                        if (!value || !*value) {
 
76
                                printf("invalid or missing username\n");
 
77
                                return 1;       /* needs_arg; */
 
78
                        }
 
79
                        if (strnlen(value, 260) < 260) {
 
80
                                got_user=1;
 
81
                                /* BB add check for format user%pass */
 
82
                                /* if(strchr(username%passw) got_password = 1) */
 
83
                        } else {
 
84
                                printf("username too long\n");
 
85
                                return 1;
 
86
                        }
 
87
        } else if (strncmp(data, "pass", 4) == 0) {
 
88
                if (!value || !*value) {
 
89
                        if(got_password) {
 
90
                                printf("password specified twice, ignoring second\n");
 
91
                        } else
 
92
                                got_password = 1;
 
93
                } else if (strnlen(value, 17) < 17) {
 
94
                        got_password = 1;
 
95
                } else {
 
96
                        printf("password too long\n");
 
97
                        return 1;
 
98
                }
 
99
        } else if (strncmp(data, "ip", 2) == 0) {
 
100
                if (!value || !*value) {
 
101
                        printf("target ip address argument missing");
 
102
                } else if (strnlen(value, 35) < 35) {
 
103
                        got_ip = 1;
 
104
                } else {
 
105
                        printf("ip address too long\n");
 
106
                        return 1;
 
107
                }
 
108
        } else if ((strncmp(data, "unc", 3) == 0)
 
109
                   || (strncmp(data, "target", 6) == 0)
 
110
                   || (strncmp(data, "path", 4) == 0)) {
 
111
                if (!value || !*value) {
 
112
                        printf("invalid path to network resource\n");
 
113
                        return 1;  /* needs_arg; */
 
114
                } else if(strnlen(value,5) < 5) {
 
115
                        printf("UNC name too short");
 
116
                }
 
117
 
 
118
                if (strnlen(value, 300) < 300) {
 
119
                        got_unc = 1;
 
120
                        if (strncmp(value, "//", 2) == 0) {
 
121
                                if(got_unc)
 
122
                                        printf("unc name specified twice, ignoring second\n");
 
123
                                else
 
124
                                        got_unc = 1;
 
125
                        } else if (strncmp(value, "\\\\", 2) != 0) {                       
 
126
                                printf("UNC Path does not begin with // or \\\\ \n");
 
127
                                return 1;
 
128
                        } else {
 
129
                                if(got_unc)
 
130
                                        printf("unc name specified twice, ignoring second\n");
 
131
                                else
 
132
                                        got_unc = 1;
 
133
                        }
 
134
                } else {
 
135
                        printf("CIFS: UNC name too long\n");
 
136
                        return 1;
 
137
                }
 
138
        } else if ((strncmp(data, "domain", 3) == 0)
 
139
                   || (strncmp(data, "workgroup", 5) == 0)) {
 
140
                if (!value || !*value) {
 
141
                        printf("CIFS: invalid domain name\n");
 
142
                        return 1;       /* needs_arg; */
 
143
                }
 
144
                if (strnlen(value, 65) < 65) {
 
145
                        got_domain = 1;
 
146
                } else {
 
147
                        printf("domain name too long\n");
 
148
                        return 1;
 
149
                }
 
150
        } else if (strncmp(data, "uid", 3) == 0) {
 
151
                if (value && *value) {
 
152
                        got_uid = 1;
 
153
                }
 
154
        } else if (strncmp(data, "gid", 3) == 0) {
 
155
                if (value && *value) {
 
156
                        got_gid = 1;
 
157
                }
 
158
        } /* else if (strnicmp(data, "file_mode", 4) == 0) {
 
159
                if (value && *value) {
 
160
                        vol->file_mode =
 
161
                                simple_strtoul(value, &value, 0);
 
162
                }
 
163
        } else if (strnicmp(data, "dir_mode", 3) == 0) {
 
164
                if (value && *value) {
 
165
                        vol->dir_mode =
 
166
                                simple_strtoul(value, &value, 0);
 
167
                }
 
168
        } else if (strnicmp(data, "port", 4) == 0) {
 
169
                if (value && *value) {
 
170
                        vol->port =
 
171
                                simple_strtoul(value, &value, 0);
 
172
                }
 
173
        } else if (strnicmp(data, "rsize", 5) == 0) {
 
174
                if (value && *value) {
 
175
                        vol->rsize =
 
176
                                simple_strtoul(value, &value, 0);
 
177
                }
 
178
        } else if (strnicmp(data, "wsize", 5) == 0) {
 
179
                if (value && *value) {
 
180
                        vol->wsize =
 
181
                                simple_strtoul(value, &value, 0);
 
182
                }
 
183
        } else if (strnicmp(data, "version", 3) == 0) {
 
184
                
 
185
        } else if (strnicmp(data, "rw", 2) == 0) {
 
186
                
 
187
        } else
 
188
                printf("CIFS: Unknown mount option %s\n",data); */
 
189
        }
 
190
        return 0;
 
191
}
 
192
 
 
193
/* Note that caller frees the returned buffer if necessary */
 
194
char * parse_server(char * unc_name)
 
195
{
 
196
        int length = strnlen(unc_name,1024);
 
197
        char * share;
 
198
        char * ipaddress_string = NULL;
 
199
        struct hostent * host_entry;
 
200
        struct in_addr server_ipaddr;
 
201
        int rc,j;
 
202
        char temp[64];
 
203
 
 
204
        if(length > 1023) {
 
205
                printf("mount error: UNC name too long");
 
206
                return 0;
 
207
        }
 
208
        if (strncasecmp("cifs://",unc_name,7) == 0)
 
209
                return parse_cifs_url(unc_name+7);
 
210
        if (strncasecmp("smb://",unc_name,6) == 0) {
 
211
                return parse_cifs_url(unc_name+6);
 
212
        }
 
213
 
 
214
        if(length < 3) {
 
215
                /* BB add code to find DFS root here */
 
216
                printf("\nMounting the DFS root for domain not implemented yet");
 
217
                return 0;
 
218
        } else {
 
219
                /* BB add support for \\\\ not just // */
 
220
                if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
 
221
                        printf("mount error: improperly formatted UNC name.");
 
222
                        printf(" %s does not begin with \\\\ or //\n",unc_name);
 
223
                        return 0;
 
224
                } else {
 
225
                        unc_name[0] = '\\';
 
226
                        unc_name[1] = '\\';
 
227
                        unc_name += 2;
 
228
                        if ((share = strchr(unc_name, '/')) || 
 
229
                                (share = strchr(unc_name,'\\'))) {
 
230
                                *share = 0;  /* temporarily terminate the string */
 
231
                                share += 1;
 
232
                                host_entry = gethostbyname(unc_name);
 
233
                                *(share - 1) = '\\'; /* put the slash back */
 
234
/*                              rc = getipnodebyname(unc_name, AF_INET, AT_ADDRCONFIG ,&rc);*/
 
235
                                if(host_entry == NULL) {
 
236
                                        printf("mount error: could not find target server. TCP name %s not found ", unc_name);
 
237
                                        printf(" rc = %d\n",rc);
 
238
                                        return 0;
 
239
                                }
 
240
                                else {
 
241
                                        /* BB should we pass an alternate version of the share name as Unicode */
 
242
                                        /* BB what about ipv6? BB */
 
243
                                        /* BB add retries with alternate servers in list */
 
244
 
 
245
                                        memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
 
246
 
 
247
                                        ipaddress_string = inet_ntoa(server_ipaddr);                                                                                     
 
248
                                        if(ipaddress_string == NULL) {
 
249
                                                printf("mount error: could not get valid ip address for target server\n");
 
250
                                                return 0;
 
251
                                        }
 
252
                                        return ipaddress_string; 
 
253
                                }
 
254
                        } else {
 
255
                                /* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
 
256
                                printf("Mounting the DFS root for a particular server not implemented yet\n");
 
257
                                return 0;
 
258
                        }
 
259
                }
 
260
        }
 
261
}
 
262
 
 
263
static struct option longopts[] = {
 
264
        { "all", 0, 0, 'a' },
 
265
        { "help", 0, 0, 'h' },
 
266
        { "read-only", 0, 0, 'r' },
 
267
        { "ro", 0, 0, 'r' },
 
268
        { "verbose", 0, 0, 'v' },
 
269
        { "version", 0, 0, 'V' },
 
270
        { "read-write", 0, 0, 'w' },
 
271
        { "rw", 0, 0, 'w' },
 
272
        { "options", 1, 0, 'o' },
 
273
        { "types", 1, 0, 't' },
 
274
        { "replace", 0, 0, 129 },
 
275
        { "after", 0, 0, 130 },
 
276
        { "before", 0, 0, 131 },
 
277
        { "over", 0, 0, 132 },
 
278
        { "move", 0, 0, 133 },
 
279
        { "rsize",1, 0, 136 },
 
280
        { "wsize",1, 0, 137 },
 
281
        { "uid", 1, 0, 138},
 
282
        { "gid", 1, 0, 139},
 
283
        { "uuid",1,0,'U' },
 
284
        { "user",1,0,140},
 
285
        { "username",1,0,140},
 
286
        { "dom",1,0,141},
 
287
        { "domain",1,0,141},
 
288
        { "password",1,0,142},
 
289
        { NULL, 0, 0, 0 }
 
290
};
 
291
 
 
292
int main(int argc, char ** argv)
 
293
{
 
294
        int c;
 
295
        int flags = MS_MANDLOCK | MS_MGC_VAL;
 
296
        char * orgoptions = NULL;
 
297
        char * share_name = NULL;
 
298
        char * domain_name = NULL;
 
299
        char * ipaddr = NULL;
 
300
        char * uuid = NULL;
 
301
        char * mountpoint;
 
302
        char * options;
 
303
        int rc,i;
 
304
        int rsize = 0;
 
305
        int wsize = 0;
 
306
        int nomtab = 0;
 
307
        int uid = 0;
 
308
        int gid = 0;
 
309
        int optlen = 0;
 
310
        struct stat statbuf;
 
311
        struct utsname sysinfo;
 
312
        struct mntent mountent;
 
313
        FILE * pmntfile;
 
314
 
 
315
        /* setlocale(LC_ALL, "");
 
316
#if defined(LOCALEDIR)
 
317
        bindtextdomain(PACKAGE, LOCALEDIR);
 
318
        textdomain(PACKAGE); */
 
319
#endif
 
320
 
 
321
        if(argc && argv) {
 
322
                thisprogram = argv[0];
 
323
        }
 
324
        if(thisprogram == NULL)
 
325
                thisprogram = "mount.cifs";
 
326
 
 
327
        uname(&sysinfo);
 
328
        /* BB add workstation name and domain and pass down */
 
329
/*#ifdef _GNU_SOURCE
 
330
        printf(" node: %s machine: %s\n", sysinfo.nodename,sysinfo.machine);
 
331
#endif*/
 
332
        if(argc < 3)
 
333
                mount_cifs_usage();
 
334
        share_name = argv[1];
 
335
        mountpoint = argv[2];
 
336
        /* add sharename in opts string as unc= parm */
 
337
 
 
338
        while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:",
 
339
                         longopts, NULL)) != -1) {
 
340
                switch (c) {
 
341
/*      case 'a':              
 
342
                ++mount_all;
 
343
                break;
 
344
        case 'f':              
 
345
                ++fake;
 
346
                break;
 
347
        case 'F':
 
348
                ++optfork;
 
349
                break; */
 
350
                case 'h':        /* help */
 
351
                        mount_cifs_usage ();
 
352
                        break;
 
353
/*      case 'i':
 
354
                external_allowed = 0;
 
355
                break;
 
356
        case 'l':
 
357
                list_with_volumelabel = 1;
 
358
                break;
 
359
        case 'L':
 
360
                volumelabel = optarg;
 
361
                break; */
 
362
        case 'n':
 
363
                ++nomtab;
 
364
                break;
 
365
        case 'o':
 
366
                if (orgoptions) {
 
367
                        orgoptions = strcat(orgoptions, ",");
 
368
                        orgoptions = strcat(orgoptions,optarg);
 
369
                } else
 
370
                        orgoptions = strdup(optarg);
 
371
                break;
 
372
 
 
373
/*      case 'O':
 
374
                if (test_opts)
 
375
                        test_opts = xstrconcat3(test_opts, ",", optarg);
 
376
                else
 
377
                        test_opts = xstrdup(optarg);
 
378
                break;*/
 
379
                case 'r':  /* mount readonly */
 
380
                        flags |= MS_RDONLY;;
 
381
                        break;
 
382
                case 'U':
 
383
                        uuid = optarg;
 
384
                        break;
 
385
                case 'v':
 
386
                        ++verboseflag;
 
387
                        break;
 
388
/*      case 'V':          
 
389
                printf ("mount: %s\n", version);
 
390
                exit (0);*/
 
391
                case 'w':
 
392
                        flags &= ~MS_RDONLY;;
 
393
                        break;
 
394
/*      case 0:
 
395
                break;
 
396
 
 
397
        case 128: 
 
398
                mounttype = MS_BIND;
 
399
                break;
 
400
        case 129: 
 
401
                mounttype = MS_REPLACE;
 
402
                break;
 
403
        case 130: 
 
404
                mounttype = MS_AFTER;
 
405
                break;
 
406
        case 131: 
 
407
                mounttype = MS_BEFORE;
 
408
                break;
 
409
        case 132: 
 
410
                mounttype = MS_OVER;
 
411
                break;
 
412
        case 133: 
 
413
                mounttype = MS_MOVE;
 
414
                break;
 
415
        case 135:
 
416
                mounttype = (MS_BIND | MS_REC);
 
417
                break; */
 
418
                case 136:
 
419
                        rsize = atoi(optarg) ;
 
420
                        break;
 
421
                case 137:
 
422
                        wsize = atoi(optarg);
 
423
                        break;
 
424
                case 138:
 
425
                        uid = atoi(optarg);
 
426
                        break;
 
427
                case 139:
 
428
                        gid = atoi(optarg);
 
429
                        break;
 
430
                case 140:
 
431
                        got_user = 1;
 
432
                        user_name = optarg;
 
433
                        break;
 
434
                case 141:
 
435
                        domain_name = optarg;
 
436
                        break;
 
437
                case 142:
 
438
                        got_password = 1;
 
439
                         mountpassword = optarg;
 
440
                        break;
 
441
                case '?':
 
442
                default:
 
443
                        mount_cifs_usage ();
 
444
                }
 
445
        }
 
446
 
 
447
        /* canonicalize the path in argv[1]? */
 
448
 
 
449
        if(stat (mountpoint, &statbuf)) {
 
450
                printf("mount error: mount point %s does not exist\n",mountpoint);
 
451
                return -1;
 
452
        }
 
453
        if (S_ISDIR(statbuf.st_mode) == 0) {
 
454
                printf("mount error: mount point %s is not a directory\n",mountpoint);
 
455
                return -1;
 
456
        }
 
457
 
 
458
        if(geteuid()) {
 
459
                printf("mount error: permission denied, not superuser and cifs.mount not installed SUID\n"); 
 
460
                return -1;
 
461
        }
 
462
 
 
463
        ipaddr = parse_server(share_name);
 
464
/*      if(share_name == NULL)
 
465
                return 1; */
 
466
        if (parse_options(strdup(orgoptions)))
 
467
                return 1;
 
468
 
 
469
        if(got_user == 0)
 
470
                user_name = getusername();
 
471
       
 
472
/*      check username for user%password format */
 
473
 
 
474
        if(got_password == 0) {
 
475
                if (getenv("PASSWD")) {
 
476
                        mountpassword = malloc(33);
 
477
                        if(mountpassword) {
 
478
                                strncpy(mountpassword,getenv("PASSWD"),32);
 
479
                                got_password = 1;
 
480
                        }
 
481
/*              } else if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
 
482
                        get_password_file();
 
483
                        got_password = 1;*/ /* BB add missing function */
 
484
                } else {
 
485
                        mountpassword = getpass("Password: "); /* BB obsolete */
 
486
                        got_password = 1;
 
487
                }
 
488
        }
 
489
        /* FIXME launch daemon (handles dfs name resolution and credential change) 
 
490
           remember to clear parms and overwrite password field before launching */
 
491
        if(orgoptions) {
 
492
                optlen = strlen(orgoptions);
 
493
        } else
 
494
                optlen = 0;
 
495
        if(share_name)
 
496
                optlen += strlen(share_name) + 4;
 
497
        if(user_name)
 
498
                optlen += strlen(user_name) + 6;
 
499
        if(ipaddr)
 
500
                optlen += strlen(ipaddr) + 4;
 
501
        if(mountpassword)
 
502
                optlen += strlen(mountpassword) + 6;
 
503
        options = malloc(optlen + 10);
 
504
 
 
505
    options[0] = 0;
 
506
        strncat(options,"unc=",4);
 
507
        strcat(options,share_name);
 
508
        if(ipaddr) {
 
509
                strncat(options,",ip=",4);
 
510
                strcat(options,ipaddr);
 
511
        } 
 
512
        if(user_name) {
 
513
                strncat(options,",user=",6);
 
514
                strcat(options,user_name);
 
515
        } 
 
516
        if(mountpassword) {
 
517
                strncat(options,",pass=",6);
 
518
                strcat(options,mountpassword);
 
519
        }
 
520
        strncat(options,",ver=",5);
 
521
        strcat(options,MOUNT_CIFS_VERSION);
 
522
 
 
523
        if(orgoptions) {
 
524
                strcat(options,",");
 
525
                strcat(options,orgoptions);
 
526
        }
 
527
        /* printf("\noptions %s \n",options);*/
 
528
        if(mount(share_name, mountpoint, "cifs", flags, options)) {
 
529
        /* remember to kill daemon on error */
 
530
                switch (errno) {
 
531
                case 0:
 
532
                        printf("mount failed but no error number set\n");
 
533
                        return 0;
 
534
                case ENODEV:
 
535
                        printf("mount error: cifs filesystem not supported by the system\n");
 
536
                        break;
 
537
                default:
 
538
                        printf("mount error %d = %s",errno,strerror(errno));
 
539
                }
 
540
                printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
 
541
                return -1;
 
542
        } else {
 
543
                pmntfile = setmntent(MOUNTED, "a+");
 
544
                if(pmntfile) {
 
545
                        mountent.mnt_fsname = share_name;
 
546
                        mountent.mnt_dir = mountpoint; 
 
547
                        mountent.mnt_type = "cifs"; 
 
548
                        mountent.mnt_opts = "";
 
549
                        mountent.mnt_freq = 0;
 
550
                        mountent.mnt_passno = 0;
 
551
                        rc = addmntent(pmntfile,&mountent);
 
552
                        endmntent(pmntfile);
 
553
                } else {
 
554
                    printf("could not update mount table\n");
 
555
                }
 
556
        }
 
557
        return 0;
 
558
}
 
559