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