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