r26228: Store loadparm context in auth context, move more loadparm_contexts up the...
[bbaumbach/samba-autobuild/.git] / source4 / ntvfs / unixuid / vfs_unixuid.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    a pass-thru NTVFS module to setup a security context using unix
5    uid/gid
6
7    Copyright (C) Andrew Tridgell 2004
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "system/filesys.h"
25 #include "system/passwd.h"
26 #include "auth/auth.h"
27 #include "ntvfs/ntvfs.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "param/param.h"
30
31 struct unixuid_private {
32         struct sidmap_context *sidmap;
33         struct unix_sec_ctx *last_sec_ctx;
34         struct security_token *last_token;
35 };
36
37
38
39 struct unix_sec_ctx {
40         uid_t uid;
41         gid_t gid;
42         uint_t ngroups;
43         gid_t *groups;
44 };
45
46 /*
47   pull the current security context into a unix_sec_ctx
48 */
49 static struct unix_sec_ctx *save_unix_security(TALLOC_CTX *mem_ctx)
50 {
51         struct unix_sec_ctx *sec = talloc(mem_ctx, struct unix_sec_ctx);
52         if (sec == NULL) {
53                 return NULL;
54         }
55         sec->uid = geteuid();
56         sec->gid = getegid();
57         sec->ngroups = getgroups(0, NULL);
58         if (sec->ngroups == -1) {
59                 talloc_free(sec);
60                 return NULL;
61         }
62         sec->groups = talloc_array(sec, gid_t, sec->ngroups);
63         if (sec->groups == NULL) {
64                 talloc_free(sec);
65                 return NULL;
66         }
67
68         if (getgroups(sec->ngroups, sec->groups) != sec->ngroups) {
69                 talloc_free(sec);
70                 return NULL;
71         }
72
73         return sec;
74 }
75
76 /*
77   set the current security context from a unix_sec_ctx
78 */
79 static NTSTATUS set_unix_security(struct unix_sec_ctx *sec)
80 {
81         seteuid(0);
82
83         if (setgroups(sec->ngroups, sec->groups) != 0) {
84                 return NT_STATUS_ACCESS_DENIED;
85         }
86         if (setegid(sec->gid) != 0) {
87                 return NT_STATUS_ACCESS_DENIED;
88         }
89         if (seteuid(sec->uid) != 0) {
90                 return NT_STATUS_ACCESS_DENIED;
91         }
92         return NT_STATUS_OK;
93 }
94
95 /*
96   form a unix_sec_ctx from the current security_token
97 */
98 static NTSTATUS nt_token_to_unix_security(struct ntvfs_module_context *ntvfs,
99                                           struct ntvfs_request *req,
100                                           struct security_token *token,
101                                           struct unix_sec_ctx **sec)
102 {
103         struct unixuid_private *private = ntvfs->private_data;
104         int i;
105         NTSTATUS status;
106         *sec = talloc(req, struct unix_sec_ctx);
107
108         /* we can't do unix security without a user and group */
109         if (token->num_sids < 2) {
110                 return NT_STATUS_ACCESS_DENIED;
111         }
112
113         status = sidmap_sid_to_unixuid(private->sidmap, 
114                                        token->user_sid, &(*sec)->uid);
115         if (!NT_STATUS_IS_OK(status)) {
116                 return status;
117         }
118
119         status = sidmap_sid_to_unixgid(private->sidmap, 
120                                        token->group_sid, &(*sec)->gid);
121         if (!NT_STATUS_IS_OK(status)) {
122                 return status;
123         }
124
125         (*sec)->ngroups = token->num_sids - 2;
126         (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups);
127         if ((*sec)->groups == NULL) {
128                 return NT_STATUS_NO_MEMORY;
129         }
130
131         for (i=0;i<(*sec)->ngroups;i++) {
132                 status = sidmap_sid_to_unixgid(private->sidmap, 
133                                                token->sids[i+2], &(*sec)->groups[i]);
134                 if (!NT_STATUS_IS_OK(status)) {
135                         return status;
136                 }
137         }
138
139         return NT_STATUS_OK;
140 }
141
142 /*
143   setup our unix security context according to the session authentication info
144 */
145 static NTSTATUS unixuid_setup_security(struct ntvfs_module_context *ntvfs,
146                                        struct ntvfs_request *req, struct unix_sec_ctx **sec)
147 {
148         struct unixuid_private *private = ntvfs->private_data;
149         struct security_token *token;
150         struct unix_sec_ctx *newsec;
151         NTSTATUS status;
152
153         if (req->session_info == NULL) {
154                 return NT_STATUS_ACCESS_DENIED;
155         }
156
157         token = req->session_info->security_token;
158
159         *sec = save_unix_security(ntvfs);
160         if (*sec == NULL) {
161                 return NT_STATUS_NO_MEMORY;
162         }
163
164         if (token == private->last_token) {
165                 newsec = private->last_sec_ctx;
166         } else {
167                 status = nt_token_to_unix_security(ntvfs, req, token, &newsec);
168                 if (!NT_STATUS_IS_OK(status)) {
169                         talloc_free(*sec);
170                         return status;
171                 }
172                 if (private->last_sec_ctx) {
173                         talloc_free(private->last_sec_ctx);
174                 }
175                 private->last_sec_ctx = newsec;
176                 private->last_token = token;
177                 talloc_steal(private, newsec);
178         }
179
180         status = set_unix_security(newsec);
181         if (!NT_STATUS_IS_OK(status)) {
182                 talloc_free(*sec);
183                 return status;
184         }
185
186         return NT_STATUS_OK;
187 }
188
189 /*
190   this pass through macro operates on request contexts
191 */
192 #define PASS_THRU_REQ(ntvfs, req, op, args) do { \
193         NTSTATUS status2; \
194         struct unix_sec_ctx *sec; \
195         status = unixuid_setup_security(ntvfs, req, &sec); \
196         NT_STATUS_NOT_OK_RETURN(status); \
197         status = ntvfs_next_##op args; \
198         status2 = set_unix_security(sec); \
199         talloc_free(sec); \
200         if (!NT_STATUS_IS_OK(status2)) smb_panic("Unable to reset security context"); \
201 } while (0)
202
203
204
205 /*
206   connect to a share - used when a tree_connect operation comes in.
207 */
208 static NTSTATUS unixuid_connect(struct ntvfs_module_context *ntvfs,
209                                 struct ntvfs_request *req, const char *sharename)
210 {
211         struct unixuid_private *private;
212         NTSTATUS status;
213
214         private = talloc(ntvfs, struct unixuid_private);
215         if (!private) {
216                 return NT_STATUS_NO_MEMORY;
217         }
218
219         private->sidmap = sidmap_open(private, global_loadparm);
220         if (private->sidmap == NULL) {
221                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
222         }
223
224         ntvfs->private_data = private;
225         private->last_sec_ctx = NULL;
226         private->last_token = NULL;
227
228         /* we don't use PASS_THRU_REQ here, as the connect operation runs with 
229            root privileges. This allows the backends to setup any database
230            links they might need during the connect. */
231         status = ntvfs_next_connect(ntvfs, req, sharename);
232
233         return status;
234 }
235
236 /*
237   disconnect from a share
238 */
239 static NTSTATUS unixuid_disconnect(struct ntvfs_module_context *ntvfs)
240 {
241         struct unixuid_private *private = ntvfs->private_data;
242         NTSTATUS status;
243
244         talloc_free(private);
245         ntvfs->private_data = NULL;
246
247         status = ntvfs_next_disconnect(ntvfs);
248  
249         return status;
250 }
251
252
253 /*
254   delete a file
255 */
256 static NTSTATUS unixuid_unlink(struct ntvfs_module_context *ntvfs,
257                               struct ntvfs_request *req,
258                               union smb_unlink *unl)
259 {
260         NTSTATUS status;
261
262         PASS_THRU_REQ(ntvfs, req, unlink, (ntvfs, req, unl));
263
264         return status;
265 }
266
267 /*
268   ioctl interface
269 */
270 static NTSTATUS unixuid_ioctl(struct ntvfs_module_context *ntvfs,
271                              struct ntvfs_request *req, union smb_ioctl *io)
272 {
273         NTSTATUS status;
274
275         PASS_THRU_REQ(ntvfs, req, ioctl, (ntvfs, req, io));
276
277         return status;
278 }
279
280 /*
281   check if a directory exists
282 */
283 static NTSTATUS unixuid_chkpath(struct ntvfs_module_context *ntvfs,
284                                 struct ntvfs_request *req,
285                                 union smb_chkpath *cp)
286 {
287         NTSTATUS status;
288
289         PASS_THRU_REQ(ntvfs, req, chkpath, (ntvfs, req, cp));
290
291         return status;
292 }
293
294 /*
295   return info on a pathname
296 */
297 static NTSTATUS unixuid_qpathinfo(struct ntvfs_module_context *ntvfs,
298                                  struct ntvfs_request *req, union smb_fileinfo *info)
299 {
300         NTSTATUS status;
301
302         PASS_THRU_REQ(ntvfs, req, qpathinfo, (ntvfs, req, info));
303
304         return status;
305 }
306
307 /*
308   query info on a open file
309 */
310 static NTSTATUS unixuid_qfileinfo(struct ntvfs_module_context *ntvfs,
311                                  struct ntvfs_request *req, union smb_fileinfo *info)
312 {
313         NTSTATUS status;
314
315         PASS_THRU_REQ(ntvfs, req, qfileinfo, (ntvfs, req, info));
316
317         return status;
318 }
319
320
321 /*
322   set info on a pathname
323 */
324 static NTSTATUS unixuid_setpathinfo(struct ntvfs_module_context *ntvfs,
325                                    struct ntvfs_request *req, union smb_setfileinfo *st)
326 {
327         NTSTATUS status;
328
329         PASS_THRU_REQ(ntvfs, req, setpathinfo, (ntvfs, req, st));
330
331         return status;
332 }
333
334 /*
335   open a file
336 */
337 static NTSTATUS unixuid_open(struct ntvfs_module_context *ntvfs,
338                              struct ntvfs_request *req, union smb_open *io)
339 {
340         NTSTATUS status;
341
342         PASS_THRU_REQ(ntvfs, req, open, (ntvfs, req, io));
343
344         return status;
345 }
346
347 /*
348   create a directory
349 */
350 static NTSTATUS unixuid_mkdir(struct ntvfs_module_context *ntvfs,
351                              struct ntvfs_request *req, union smb_mkdir *md)
352 {
353         NTSTATUS status;
354
355         PASS_THRU_REQ(ntvfs, req, mkdir, (ntvfs, req, md));
356
357         return status;
358 }
359
360 /*
361   remove a directory
362 */
363 static NTSTATUS unixuid_rmdir(struct ntvfs_module_context *ntvfs,
364                              struct ntvfs_request *req, struct smb_rmdir *rd)
365 {
366         NTSTATUS status;
367
368         PASS_THRU_REQ(ntvfs, req, rmdir, (ntvfs, req, rd));
369
370         return status;
371 }
372
373 /*
374   rename a set of files
375 */
376 static NTSTATUS unixuid_rename(struct ntvfs_module_context *ntvfs,
377                               struct ntvfs_request *req, union smb_rename *ren)
378 {
379         NTSTATUS status;
380
381         PASS_THRU_REQ(ntvfs, req, rename, (ntvfs, req, ren));
382
383         return status;
384 }
385
386 /*
387   copy a set of files
388 */
389 static NTSTATUS unixuid_copy(struct ntvfs_module_context *ntvfs,
390                             struct ntvfs_request *req, struct smb_copy *cp)
391 {
392         NTSTATUS status;
393
394         PASS_THRU_REQ(ntvfs, req, copy, (ntvfs, req, cp));
395
396         return status;
397 }
398
399 /*
400   read from a file
401 */
402 static NTSTATUS unixuid_read(struct ntvfs_module_context *ntvfs,
403                             struct ntvfs_request *req, union smb_read *rd)
404 {
405         NTSTATUS status;
406
407         PASS_THRU_REQ(ntvfs, req, read, (ntvfs, req, rd));
408
409         return status;
410 }
411
412 /*
413   write to a file
414 */
415 static NTSTATUS unixuid_write(struct ntvfs_module_context *ntvfs,
416                              struct ntvfs_request *req, union smb_write *wr)
417 {
418         NTSTATUS status;
419
420         PASS_THRU_REQ(ntvfs, req, write, (ntvfs, req, wr));
421
422         return status;
423 }
424
425 /*
426   seek in a file
427 */
428 static NTSTATUS unixuid_seek(struct ntvfs_module_context *ntvfs,
429                              struct ntvfs_request *req,
430                              union smb_seek *io)
431 {
432         NTSTATUS status;
433
434         PASS_THRU_REQ(ntvfs, req, seek, (ntvfs, req, io));
435
436         return status;
437 }
438
439 /*
440   flush a file
441 */
442 static NTSTATUS unixuid_flush(struct ntvfs_module_context *ntvfs,
443                               struct ntvfs_request *req,
444                               union smb_flush *io)
445 {
446         NTSTATUS status;
447
448         PASS_THRU_REQ(ntvfs, req, flush, (ntvfs, req, io));
449
450         return status;
451 }
452
453 /*
454   close a file
455 */
456 static NTSTATUS unixuid_close(struct ntvfs_module_context *ntvfs,
457                              struct ntvfs_request *req, union smb_close *io)
458 {
459         NTSTATUS status;
460
461         PASS_THRU_REQ(ntvfs, req, close, (ntvfs, req, io));
462
463         return status;
464 }
465
466 /*
467   exit - closing files
468 */
469 static NTSTATUS unixuid_exit(struct ntvfs_module_context *ntvfs,
470                             struct ntvfs_request *req)
471 {
472         NTSTATUS status;
473
474         PASS_THRU_REQ(ntvfs, req, exit, (ntvfs, req));
475
476         return status;
477 }
478
479 /*
480   logoff - closing files
481 */
482 static NTSTATUS unixuid_logoff(struct ntvfs_module_context *ntvfs,
483                               struct ntvfs_request *req)
484 {
485         struct unixuid_private *private = ntvfs->private_data;
486         NTSTATUS status;
487
488         PASS_THRU_REQ(ntvfs, req, logoff, (ntvfs, req));
489
490         private->last_token = NULL;
491
492         return status;
493 }
494
495 /*
496   async setup
497 */
498 static NTSTATUS unixuid_async_setup(struct ntvfs_module_context *ntvfs,
499                                     struct ntvfs_request *req, 
500                                     void *private)
501 {
502         NTSTATUS status;
503
504         PASS_THRU_REQ(ntvfs, req, async_setup, (ntvfs, req, private));
505
506         return status;
507 }
508
509 /*
510   cancel an async request
511 */
512 static NTSTATUS unixuid_cancel(struct ntvfs_module_context *ntvfs,
513                                struct ntvfs_request *req)
514 {
515         NTSTATUS status;
516
517         PASS_THRU_REQ(ntvfs, req, cancel, (ntvfs, req));
518
519         return status;
520 }
521
522 /*
523   change notify
524 */
525 static NTSTATUS unixuid_notify(struct ntvfs_module_context *ntvfs,
526                                struct ntvfs_request *req, union smb_notify *info)
527 {
528         NTSTATUS status;
529
530         PASS_THRU_REQ(ntvfs, req, notify, (ntvfs, req, info));
531
532         return status;
533 }
534
535 /*
536   lock a byte range
537 */
538 static NTSTATUS unixuid_lock(struct ntvfs_module_context *ntvfs,
539                             struct ntvfs_request *req, union smb_lock *lck)
540 {
541         NTSTATUS status;
542
543         PASS_THRU_REQ(ntvfs, req, lock, (ntvfs, req, lck));
544
545         return status;
546 }
547
548 /*
549   set info on a open file
550 */
551 static NTSTATUS unixuid_setfileinfo(struct ntvfs_module_context *ntvfs,
552                                    struct ntvfs_request *req, 
553                                    union smb_setfileinfo *info)
554 {
555         NTSTATUS status;
556
557         PASS_THRU_REQ(ntvfs, req, setfileinfo, (ntvfs, req, info));
558
559         return status;
560 }
561
562
563 /*
564   return filesystem space info
565 */
566 static NTSTATUS unixuid_fsinfo(struct ntvfs_module_context *ntvfs,
567                               struct ntvfs_request *req, union smb_fsinfo *fs)
568 {
569         NTSTATUS status;
570
571         PASS_THRU_REQ(ntvfs, req, fsinfo, (ntvfs, req, fs));
572
573         return status;
574 }
575
576 /*
577   return print queue info
578 */
579 static NTSTATUS unixuid_lpq(struct ntvfs_module_context *ntvfs,
580                            struct ntvfs_request *req, union smb_lpq *lpq)
581 {
582         NTSTATUS status;
583
584         PASS_THRU_REQ(ntvfs, req, lpq, (ntvfs, req, lpq));
585
586         return status;
587 }
588
589 /* 
590    list files in a directory matching a wildcard pattern
591 */
592 static NTSTATUS unixuid_search_first(struct ntvfs_module_context *ntvfs,
593                                     struct ntvfs_request *req, union smb_search_first *io, 
594                                     void *search_private, 
595                                     bool (*callback)(void *, const union smb_search_data *))
596 {
597         NTSTATUS status;
598
599         PASS_THRU_REQ(ntvfs, req, search_first, (ntvfs, req, io, search_private, callback));
600
601         return status;
602 }
603
604 /* continue a search */
605 static NTSTATUS unixuid_search_next(struct ntvfs_module_context *ntvfs,
606                                    struct ntvfs_request *req, union smb_search_next *io, 
607                                    void *search_private, 
608                                    bool (*callback)(void *, const union smb_search_data *))
609 {
610         NTSTATUS status;
611
612         PASS_THRU_REQ(ntvfs, req, search_next, (ntvfs, req, io, search_private, callback));
613
614         return status;
615 }
616
617 /* close a search */
618 static NTSTATUS unixuid_search_close(struct ntvfs_module_context *ntvfs,
619                                     struct ntvfs_request *req, union smb_search_close *io)
620 {
621         NTSTATUS status;
622
623         PASS_THRU_REQ(ntvfs, req, search_close, (ntvfs, req, io));
624
625         return status;
626 }
627
628 /* SMBtrans - not used on file shares */
629 static NTSTATUS unixuid_trans(struct ntvfs_module_context *ntvfs,
630                              struct ntvfs_request *req, struct smb_trans2 *trans2)
631 {
632         NTSTATUS status;
633
634         PASS_THRU_REQ(ntvfs, req, trans, (ntvfs, req, trans2));
635
636         return status;
637 }
638
639 /*
640   initialise the unixuid backend, registering ourselves with the ntvfs subsystem
641  */
642 NTSTATUS ntvfs_unixuid_init(void)
643 {
644         NTSTATUS ret;
645         struct ntvfs_ops ops;
646         NTVFS_CURRENT_CRITICAL_SIZES(vers);
647
648         ZERO_STRUCT(ops);
649
650         /* fill in all the operations */
651         ops.connect = unixuid_connect;
652         ops.disconnect = unixuid_disconnect;
653         ops.unlink = unixuid_unlink;
654         ops.chkpath = unixuid_chkpath;
655         ops.qpathinfo = unixuid_qpathinfo;
656         ops.setpathinfo = unixuid_setpathinfo;
657         ops.open = unixuid_open;
658         ops.mkdir = unixuid_mkdir;
659         ops.rmdir = unixuid_rmdir;
660         ops.rename = unixuid_rename;
661         ops.copy = unixuid_copy;
662         ops.ioctl = unixuid_ioctl;
663         ops.read = unixuid_read;
664         ops.write = unixuid_write;
665         ops.seek = unixuid_seek;
666         ops.flush = unixuid_flush;      
667         ops.close = unixuid_close;
668         ops.exit = unixuid_exit;
669         ops.lock = unixuid_lock;
670         ops.setfileinfo = unixuid_setfileinfo;
671         ops.qfileinfo = unixuid_qfileinfo;
672         ops.fsinfo = unixuid_fsinfo;
673         ops.lpq = unixuid_lpq;
674         ops.search_first = unixuid_search_first;
675         ops.search_next = unixuid_search_next;
676         ops.search_close = unixuid_search_close;
677         ops.trans = unixuid_trans;
678         ops.logoff = unixuid_logoff;
679         ops.async_setup = unixuid_async_setup;
680         ops.cancel = unixuid_cancel;
681         ops.notify = unixuid_notify;
682
683         ops.name = "unixuid";
684
685         /* we register under all 3 backend types, as we are not type specific */
686         ops.type = NTVFS_DISK;  
687         ret = ntvfs_register(&ops, &vers);
688         if (!NT_STATUS_IS_OK(ret)) goto failed;
689
690         ops.type = NTVFS_PRINT; 
691         ret = ntvfs_register(&ops, &vers);
692         if (!NT_STATUS_IS_OK(ret)) goto failed;
693
694         ops.type = NTVFS_IPC;   
695         ret = ntvfs_register(&ops, &vers);
696         if (!NT_STATUS_IS_OK(ret)) goto failed;
697         
698 failed:
699         return ret;
700 }