diff options
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/include/proto.h | 259 | ||||
-rw-r--r-- | source3/lib/util_sid.c | 2 | ||||
-rw-r--r-- | source3/lib/util_unixsd.c | 679 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 444 |
5 files changed, 832 insertions, 554 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index b0d44e4a29..f3a254667d 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -104,7 +104,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \ lib/signal.o lib/slprintf.o lib/system.o lib/doscalls.o lib/time.o \ lib/ufc.o lib/genrand.o lib/username.o lib/access.o lib/smbrun.o \ lib/bitmap.o lib/crc32.o lib/snprintf.o \ - lib/util_array.o lib/util_str.o lib/util_sid.o \ + lib/util_array.o lib/util_unixsd.o lib/util_str.o lib/util_sid.o \ lib/util_unistr.o lib/util_file.o \ lib/util.o lib/util_sock.o lib/util_sec.o smbd/ssl.o \ lib/talloc.o lib/hash.o lib/substitute.o lib/fsusage.o \ diff --git a/source3/include/proto.h b/source3/include/proto.h index 320e0f1c5f..e6a96dda34 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -554,40 +554,38 @@ DOM_SID* add_sid_to_array(uint32 *len, DOM_SID ***array, const DOM_SID *sid); /*The following definitions come from lib/util.c */ char *tmpdir(void); -BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t * groups); +BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups); char *Atoic(char *p, int *n, char *c); char *get_numlist(char *p, uint32 **num, int *count); -BOOL file_exist(char *fname, SMB_STRUCT_STAT * sbuf); +BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf); int file_rename(char *from, char *to); time_t file_modtime(char *fname); -BOOL directory_exist(char *dname, SMB_STRUCT_STAT * st); +BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st); SMB_OFF_T get_file_size(char *file_name); char *attrib_string(uint16 mode); void show_msg(char *buf); -void smb_setlen(char *buf, int len); -int set_message(char *buf, int num_words, int num_bytes, BOOL zero); +void smb_setlen(char *buf,int len); +int set_message(char *buf,int num_words,int num_bytes,BOOL zero); void dos_clean_name(char *s); void unix_clean_name(char *s); -BOOL reduce_name(char *s, char *dir, BOOL widelinks); -void make_dir_struct(char *buf, char *mask, char *fname, SMB_OFF_T size, - int mode, time_t date); +BOOL reduce_name(char *s,char *dir,BOOL widelinks); +void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date); void close_low_fds(void); int set_blocking(int fd, BOOL set); -SMB_OFF_T transfer_file(int infd, int outfd, SMB_OFF_T n, char *header, - int headlen, int align); +SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align); void msleep(int t); void become_daemon(void); BOOL yesno(char *p); int set_filelen(int fd, SMB_OFF_T len); -void *Realloc(void *p, size_t size); +void *Realloc(void *p,size_t size); void safe_free(void *p); BOOL get_myname(char *my_name); -int interpret_protocol(char *str, int def); +int interpret_protocol(char *str,int def); BOOL is_ipaddress(const char *str); uint32 interpret_addr(char *str); struct in_addr *interpret_addr2(char *str); BOOL zero_ip(struct in_addr ip); -BOOL same_net(struct in_addr ip1, struct in_addr ip2, struct in_addr mask); +BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); struct hostent *Get_Hostbyname(const char *name); BOOL process_exists(pid_t pid); char *uidtoname(uid_t uid); @@ -595,18 +593,18 @@ char *gidtoname(gid_t gid); uid_t nametouid(const char *name); gid_t nametogid(const char *name); void smb_panic(char *why); -char *readdirname(DIR * p); -BOOL is_in_path(char *name, name_compare_entry * namelist); -void set_namearray(name_compare_entry ** ppname_array, char *namelist); -void free_namearray(name_compare_entry * name_array); +char *readdirname(DIR *p); +BOOL is_in_path(char *name, name_compare_entry *namelist); +void set_namearray(name_compare_entry **ppname_array, char *namelist); +void free_namearray(name_compare_entry *name_array); BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); BOOL is_myname(char *s); void set_remote_arch(enum remote_arch_types type); enum remote_arch_types get_remote_arch(void); -void out_ascii(FILE * f, unsigned char *buf, int len); -void out_data(FILE * f, char *buf1, int len, int per_line); -void print_asc(int level, unsigned char *buf, int len); -void dump_data(int level, char *buf1, int len); +void out_ascii(FILE *f, unsigned char *buf,int len); +void out_data(FILE *f,char *buf1,int len, int per_line); +void print_asc(int level, unsigned char *buf,int len); +void dump_data(int level,char *buf1,int len); char *tab_depth(int depth); int str_checksum(const char *s); void zero_free(void *p, size_t size); @@ -665,31 +663,28 @@ BOOL sid_split_rid(DOM_SID *sid, uint32 *rid); void sid_copy(DOM_SID *dst, const DOM_SID *src); DOM_SID *sid_dup(DOM_SID *src); BOOL sid_linearize(char *outbuf, size_t len, DOM_SID *sid); -BOOL sid_equal(DOM_SID *sid1, DOM_SID *sid2); +BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2); size_t sid_size(DOM_SID *sid); /*The following definitions come from lib/util_sock.c */ BOOL is_a_socket(int fd); void set_socket_options(int fd, char *options); -ssize_t read_udp_socket(int fd, char *buf, size_t len); -ssize_t read_with_timeout(int fd, char *buf, size_t mincnt, size_t maxcnt, - unsigned int time_out); +ssize_t read_udp_socket(int fd,char *buf,size_t len); +ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out); BOOL send_keepalive(int client); -ssize_t read_data(int fd, char *buffer, size_t N); -ssize_t write_data(int fd, char *buffer, size_t N); -ssize_t write_socket_data(int fd, char *buffer, size_t N); -ssize_t write_socket(int fd, char *buf, size_t len); -ssize_t read_smb_length(int fd, char *inbuf, unsigned int timeout); -BOOL receive_smb(int fd, char *buffer, unsigned int timeout); -BOOL client_receive_smb(int fd, char *buffer, unsigned int timeout); +ssize_t read_data(int fd,char *buffer,size_t N); +ssize_t write_data(int fd,char *buffer,size_t N); +ssize_t write_socket_data(int fd,char *buffer,size_t N); +ssize_t write_socket(int fd,char *buf,size_t len); +ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout); +BOOL receive_smb(int fd,char *buffer, unsigned int timeout); +BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout); BOOL send_null_session_msg(int fd); -BOOL send_smb(int fd, char *buffer); -BOOL send_one_packet(char *buf, int len, struct in_addr ip, int port, - int type); -int open_socket_in(int type, int port, int dlevel, uint32 socket_addr, - BOOL rebind); -int open_socket_out(int type, struct in_addr *addr, int port, int timeout); +BOOL send_smb(int fd,char *buffer); +BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type); +int open_socket_in(int type, int port, int dlevel,uint32 socket_addr, BOOL rebind); +int open_socket_out(int type, struct in_addr *addr, int port ,int timeout); void reset_globals_after_fork(void); void client_setfd(int fd); char *client_name(void); @@ -697,7 +692,8 @@ char *client_addr(void); char *get_socket_name(int fd); char *get_socket_addr(int fd); int open_pipe_sock(char *path); -int create_pipe_socket(char *dir, int dir_perms, char *path, int path_perms); +int create_pipe_socket(char *dir, int dir_perms, + char *path, int path_perms); /*The following definitions come from lib/util_str.c */ @@ -818,6 +814,16 @@ void split_at_last_component_w(smb_ucs2_t *path, smb_ucs2_t *front, smb_ucs2_t s smb_ucs2_t *octal_string_w(int i); smb_ucs2_t *string_truncate_w(smb_ucs2_t *s, size_t length); +/*The following definitions come from lib/util_unixsd.c */ + +size_t convertperms_unix_to_sd(const SMB_STRUCT_STAT * sbuf, + BOOL is_directory, mode_t mode, + SEC_DESC ** ppdesc); +BOOL convertperms_sd_to_unix(SMB_STRUCT_STAT * psbuf, uid_t * puser, + gid_t * pgrp, mode_t * pmode, + uint32 security_info_sent, SEC_DESC * psd, + BOOL is_directory); + /*The following definitions come from locking/brlock.c */ void brl_init(int read_only); @@ -2910,6 +2916,7 @@ BOOL api_spoolss_rpc(pipes_struct *p, prs_struct *data); /*The following definitions come from rpc_server/srv_spoolss_nt.c */ +#if OLD_NTDOMAIN void init_printer_hnd(void); uint32 _spoolss_open_printer_ex( const UNISTR2 *printername, const PRINTER_DEFAULT *printer_default, @@ -3013,6 +3020,7 @@ uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level, uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level, NEW_BUFFER *buffer, uint32 offered, uint32 *needed); +#endif /*The following definitions come from rpc_server/srv_srvsvc.c */ @@ -3357,114 +3365,73 @@ void smbd_process(void); /*The following definitions come from smbd/reply.c */ #if OLD_NTDOMAIN -int reply_special(char *inbuf, char *outbuf); -int reply_tcon(connection_struct * conn, - char *inbuf, char *outbuf, int dum_size, int dum_buffsize); -int reply_tcon_and_X(connection_struct * conn, char *inbuf, char *outbuf, - int length, int bufsize); -int reply_unknown(char *inbuf, char *outbuf); -int reply_ioctl(connection_struct * conn, - char *inbuf, char *outbuf, int dum_size, int dum_buffsize); -int reply_sesssetup_and_X(connection_struct * conn, char *inbuf, char *outbuf, - int length, int bufsize); -int reply_chkpth(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_getatr(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_setatr(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_dskattr(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_search(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_fclose(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_open(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_open_and_X(connection_struct * conn, char *inbuf, char *outbuf, - int length, int bufsize); -int reply_ulogoffX(connection_struct * conn, char *inbuf, char *outbuf, - int length, int bufsize); -int reply_mknew(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_ctemp(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_unlink(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_readbraw(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_lockread(connection_struct * conn, char *inbuf, char *outbuf, - int length, int dum_buffsiz); -int reply_read(connection_struct * conn, char *inbuf, char *outbuf, int size, - int dum_buffsize); -int reply_read_and_X(connection_struct * conn, char *inbuf, char *outbuf, - int length, int bufsize); -int reply_writebraw(connection_struct * conn, char *inbuf, char *outbuf, - int size, int dum_buffsize); -int reply_writeunlock(connection_struct * conn, char *inbuf, char *outbuf, - int size, int dum_buffsize); -int reply_write(connection_struct * conn, char *inbuf, char *outbuf, int size, - int dum_buffsize); -int reply_write_and_X(connection_struct * conn, char *inbuf, char *outbuf, - int length, int bufsize); -int reply_lseek(connection_struct * conn, char *inbuf, char *outbuf, int size, - int dum_buffsize); -int reply_flush(connection_struct * conn, char *inbuf, char *outbuf, int size, - int dum_buffsize); -int reply_exit(connection_struct * conn, - char *inbuf, char *outbuf, int dum_size, int dum_buffsize); -int reply_close(connection_struct * conn, char *inbuf, char *outbuf, int size, - int dum_buffsize); -int reply_writeclose(connection_struct * conn, - char *inbuf, char *outbuf, int size, int dum_buffsize); -int reply_lock(connection_struct * conn, - char *inbuf, char *outbuf, int length, int dum_buffsize); -int reply_unlock(connection_struct * conn, char *inbuf, char *outbuf, - int size, int dum_buffsize); -int reply_tdis(connection_struct * conn, - char *inbuf, char *outbuf, int dum_size, int dum_buffsize); -int reply_echo(connection_struct * conn, - char *inbuf, char *outbuf, int dum_size, int dum_buffsize); -int reply_printopen(connection_struct * conn, - char *inbuf, char *outbuf, int dum_size, int dum_buffsize); -int reply_printclose(connection_struct * conn, - char *inbuf, char *outbuf, int dum_size, - int dum_buffsize); -int reply_printqueue(connection_struct * conn, - char *inbuf, char *outbuf, int dum_size, - int dum_buffsize); -int reply_printwrite(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_mkdir(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -BOOL rmdir_internals(connection_struct * conn, char *directory); -int reply_rmdir(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int rename_internals(connection_struct * conn, - char *inbuf, char *outbuf, char *name, +int reply_special(char *inbuf,char *outbuf); +int reply_tcon(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_unknown(char *inbuf,char *outbuf); +int reply_ioctl(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize); +int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz); +int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize); +int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_exit(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, + int dum_buffsize); +int reply_writeclose(connection_struct *conn, + char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_lock(connection_struct *conn, + char *inbuf,char *outbuf, int length, int dum_buffsize); +int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_tdis(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_echo(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_printopen(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_printclose(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_printqueue(connection_struct *conn, + char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +BOOL rmdir_internals(connection_struct *conn, char *directory); +int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int rename_internals(connection_struct *conn, + char *inbuf, char *outbuf, char *name, char *newname, BOOL replace_if_exists); -int reply_mv(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_copy(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_setdir(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -SMB_BIG_UINT get_lock_count(char *data, int data_offset, - BOOL large_file_format); -SMB_BIG_UINT get_lock_offset(char *data, int data_offset, - BOOL large_file_format, BOOL *err); -int reply_lockingX(connection_struct * conn, char *inbuf, char *outbuf, - int length, int bufsize); -int reply_readbmpx(connection_struct * conn, char *inbuf, char *outbuf, - int length, int bufsize); -int reply_writebmpx(connection_struct * conn, char *inbuf, char *outbuf, - int size, int dum_buffsize); -int reply_writebs(connection_struct * conn, char *inbuf, char *outbuf, - int dum_size, int dum_buffsize); -int reply_setattrE(connection_struct * conn, char *inbuf, char *outbuf, - int size, int dum_buffsize); -int reply_getattrE(connection_struct * conn, char *inbuf, char *outbuf, - int size, int dum_buffsize); +int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format); +SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err); +int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize); +int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize); +int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); +int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize); #endif /*The following definitions come from smbd/server.c */ diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index 65bc2fe85d..3605dfbf27 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -391,7 +391,7 @@ BOOL sid_linearize(char *outbuf, size_t len, DOM_SID *sid) Compare two sids. *****************************************************************/ -BOOL sid_equal(DOM_SID *sid1, DOM_SID *sid2) +BOOL sid_equal(const DOM_SID *sid1, const DOM_SID *sid2) { int i; diff --git a/source3/lib/util_unixsd.c b/source3/lib/util_unixsd.c new file mode 100644 index 0000000000..1bfc56a2da --- /dev/null +++ b/source3/lib/util_unixsd.c @@ -0,0 +1,679 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB NT Security Descriptor / Unix permission conversion. + Copyright (C) Jeremy Allison 1994-2000 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "rpc_parse.h" +#include "sids.h" + +#ifndef WITH_SURS +extern DOM_SID global_sid_World; +#define global_sid_everyone &global_sid_World +#endif + + +/**************************************************************************** + Map unix perms to NT. +****************************************************************************/ + +static SEC_ACCESS map_unix_perms(int *pacl_type, mode_t perm, int r_mask, + int w_mask, int x_mask, BOOL is_directory) +{ + SEC_ACCESS sa; + uint32 nt_mask = 0; + + *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; + + if ((perm & (r_mask | w_mask | x_mask)) == (r_mask | w_mask | x_mask)) + { + nt_mask = UNIX_ACCESS_RWX; + } + else if ((perm & (r_mask | w_mask | x_mask)) == 0) + { + nt_mask = UNIX_ACCESS_NONE; + } + else + { + nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; + if (is_directory) + nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; + else + nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; + nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; + } + make_sec_access(&sa, nt_mask); + return sa; +} + +/**************************************************************************** + Function to create owner and group SIDs from a SMB_STRUCT_STAT. +****************************************************************************/ + +static BOOL create_file_sids(const SMB_STRUCT_STAT * psbuf, + DOM_SID *powner_sid, DOM_SID *pgroup_sid) +{ + extern DOM_SID global_sam_sid; + + sid_copy(powner_sid, &global_sam_sid); + sid_copy(pgroup_sid, &global_sam_sid); + sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid)); + sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid)); + return True; +} + +#ifdef WITH_SURS +static BOOL create_file_sids(const SMB_STRUCT_STAT * psbuf, + DOM_SID *powner_sid, DOM_SID *pgroup_sid) +{ + SURS_POSIX_ID id; + + ZERO_STRUCTP(powner_sid); + ZERO_STRUCTP(pgroup_sid); + DEBUG(0, ("TODO: create_file_sids: not ok " + "to assume gid is NT group\n")); + + id.type = SURS_POSIX_UID; + id.id = (uint32)psbuf->st_uid; + + if (!surs_unixid_to_sam_sid(&id, powner_sid, False)) + { + DEBUG(3, ("create_file_sids: map uid %d failed\n", + (int)psbuf->st_uid)); + return False; + } + + id.type = SURS_POSIX_GID; + id.id = (uint32)psbuf->st_gid; + + if (!surs_unixid_to_sam_sid(&id, pgroup_sid, False)) + { + DEBUG(3, ("create_file_sids: map gid %d failed\n", + (int)psbuf->st_gid)); + return False; + } + return True; +} +#endif + +/**************************************************************************** + Reply to query a security descriptor from an fsp. If it succeeds it allocates + the space for the return elements and returns True. +****************************************************************************/ + +size_t convertperms_unix_to_sd(const SMB_STRUCT_STAT * sbuf, + BOOL is_directory, mode_t mode, + SEC_DESC ** ppdesc) +{ + SEC_ACE *ace_list = NULL; + DOM_SID owner_sid; + DOM_SID group_sid; + size_t sec_desc_size; + SEC_ACL *psa = NULL; + SEC_ACCESS owner_access; + int owner_acl_type; + SEC_ACCESS group_access; + int grp_acl_type; + SEC_ACCESS other_access; + int other_acl_type; + int num_acls = 0; + + (*ppdesc) = NULL; + + if (!lp_nt_acl_support()) + { + sid_copy(&owner_sid, global_sid_everyone); + sid_copy(&group_sid, global_sid_everyone); + } + else + { + if (!create_file_sids(sbuf, &owner_sid, &group_sid)) + { + DEBUG(3, ("create_file_sids: uid or gid " + "not mapped to SIDS\n")); + return 0; + } + + /* + * Create the generic 3 element UNIX acl. + */ + + owner_access = map_unix_perms(&owner_acl_type, sbuf->st_mode, + S_IRUSR, S_IWUSR, S_IXUSR, + is_directory); + group_access = map_unix_perms(&grp_acl_type, sbuf->st_mode, + S_IRGRP, S_IWGRP, S_IXGRP, + is_directory); + other_access = map_unix_perms(&other_acl_type, sbuf->st_mode, + S_IROTH, S_IWOTH, S_IXOTH, + is_directory); + + if (owner_access.mask) + { + ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1); + if (ace_list == NULL) + { + return 0; + } + make_sec_ace(&ace_list[num_acls++], &owner_sid, + owner_acl_type, owner_access, 0); + } + + if (group_access.mask) + { + ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1); + if (ace_list == NULL) + { + return 0; + } + + make_sec_ace(&ace_list[num_acls++], &group_sid, + grp_acl_type, group_access, 0); + } + + if (other_access.mask) + { + ace_list = g_renew(SEC_ACE, ace_list, num_acls + 1); + if (ace_list == NULL) + { + return 0; + } + + make_sec_ace(&ace_list[num_acls++], + global_sid_everyone, other_acl_type, + other_access, 0); + } + + if (is_directory) + { + /* + * For directory ACLs we also add in the + * inherited permissions ACE entries. These + * are the permissions a file would get when + * being created in the directory. + */ + + owner_access = map_unix_perms(&owner_acl_type, mode, + S_IRUSR, S_IWUSR, + S_IXUSR, is_directory); + group_access = map_unix_perms(&grp_acl_type, + mode, S_IRGRP, + S_IWGRP, S_IXGRP, + is_directory); + other_access = map_unix_perms(&other_acl_type, + mode, S_IROTH, + S_IWOTH, S_IXOTH, + is_directory); + + if (owner_access.mask) + { + ace_list = g_renew(SEC_ACE, ace_list, + num_acls + 1); + if (ace_list == NULL) + { + return 0; + } + + make_sec_ace(&ace_list[num_acls++], + &owner_sid, owner_acl_type, + owner_access, + SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_INHERIT_ONLY); + } + + if (group_access.mask) + { + ace_list = g_renew(SEC_ACE, ace_list, + num_acls + 1); + if (ace_list == NULL) + { + return 0; + } + + make_sec_ace(&ace_list[num_acls++], + &group_sid, grp_acl_type, + group_access, + SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_INHERIT_ONLY); + } + + if (other_access.mask) + { + ace_list = g_renew(SEC_ACE, ace_list, + num_acls + 1); + if (ace_list == NULL) + { + return 0; + } + + make_sec_ace(&ace_list[num_acls++], + global_sid_everyone, + other_acl_type, other_access, + SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_INHERIT_ONLY); + } + } + + if (num_acls) + { + psa = g_new(SEC_ACL, 1); + if (psa == NULL) + { + safe_free(ace_list); + } + if (!make_sec_acl(psa, 2, num_acls, ace_list)) + { + DEBUG(0, ("get_nt_acl: Unable to malloc " + "space for acl.\n")); + safe_free(ace_list); + safe_free(psa); + return 0; + } + } + } + + (*ppdesc) = g_new(SEC_DESC, 1); + + if ((*ppdesc) == NULL) + { + DEBUG(0, ("get_nt_acl: Unable to malloc space " + "for security descriptor.\n")); + sec_desc_size = 0; + free_sec_acl(psa); + safe_free(psa); + return 0; + } + + sec_desc_size = make_sec_desc((*ppdesc), 1, + SEC_DESC_SELF_RELATIVE | + SEC_DESC_DACL_PRESENT, + sid_dup(&owner_sid), + sid_dup(&group_sid), NULL, psa); + + return sec_desc_size; +} + +/**************************************************************************** + Map NT perms to UNIX. +****************************************************************************/ + +#define FILE_SPECIFIC_READ_BITS \ + (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) +#define FILE_SPECIFIC_WRITE_BITS \ + (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) +#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) + +#define PRINT_SPECIFIC_READ_BITS (PRINTER_READ) +#define PRINT_SPECIFIC_WRITE_BITS (PRINTER_READ) +#define PRINT_SPECIFIC_EXECUTE_BITS (PRINTER_ALL_ACCESS) + +static mode_t map_nt_perms(SEC_ACCESS sec_access, int type) +{ + uint32 write_bits; + uint32 read_bits; + uint32 execute_bits; + mode_t mode = 0; + + write_bits = FILE_SPECIFIC_WRITE_BITS; + read_bits = FILE_SPECIFIC_READ_BITS; + execute_bits = FILE_SPECIFIC_EXECUTE_BITS; + + switch (type) + { + case S_IRUSR: + if (sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRUSR | S_IWUSR | S_IXUSR; + else + { + mode |= + (sec_access.mask & + (GENERIC_READ_ACCESS | + read_bits)) ? S_IRUSR : 0; + mode |= + (sec_access.mask & + (GENERIC_WRITE_ACCESS | + write_bits)) ? S_IWUSR : 0; + mode |= + (sec_access.mask & + (GENERIC_EXECUTE_ACCESS | + execute_bits)) ? S_IXUSR : 0; + } + break; + case S_IRGRP: + if (sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IRGRP | S_IWGRP | S_IXGRP; + else + { + mode |= + (sec_access.mask & + (GENERIC_READ_ACCESS | + read_bits)) ? S_IRGRP : 0; + mode |= + (sec_access.mask & + (GENERIC_WRITE_ACCESS | + write_bits)) ? S_IWGRP : 0; + mode |= + (sec_access.mask & + (GENERIC_EXECUTE_ACCESS | + execute_bits)) ? S_IXGRP : 0; + } + break; + case S_IROTH: + if (sec_access.mask & GENERIC_ALL_ACCESS) + mode = S_IROTH | S_IWOTH | S_IXOTH; + else + { + mode |= + (sec_access.mask & + (GENERIC_READ_ACCESS | + read_bits)) ? S_IROTH : 0; + mode |= + (sec_access.mask & + (GENERIC_WRITE_ACCESS | + write_bits)) ? S_IWOTH : 0; + mode |= + (sec_access.mask & + (GENERIC_EXECUTE_ACCESS | + execute_bits)) ? S_IXOTH : 0; + } + break; + } + + return mode; +} + +#ifndef WITH_SURS +/**************************************************************************** + Validate a SID. +****************************************************************************/ +static BOOL validate_unix_sid(DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) +{ + extern DOM_SID global_sam_sid; + DOM_SID sid; + + if (!sd_sid) + { + DEBUG(5, ("validate_unix_sid: sid missing.\n")); + return False; + } + + sid_copy(psid, sd_sid); + sid_copy(&sid, sd_sid); + + if (!sid_split_rid(&sid, prid)) + { + DEBUG(5, ("validate_unix_sid: cannot get RID from sid.\n")); + return False; + } + + if (!sid_equal(&sid, &global_sam_sid)) + { + DEBUG(5, ("validate_unix_sid: sid is not ours.\n")); + return False; + } + + return True; +} +#endif + +/**************************************************************************** + Unpack a SEC_DESC into a owner, group and set of UNIX permissions. +****************************************************************************/ + +BOOL convertperms_sd_to_unix(SMB_STRUCT_STAT * psbuf, uid_t * puser, + gid_t * pgrp, mode_t * pmode, + uint32 security_info_sent, SEC_DESC * psd, + BOOL is_directory) +{ + DOM_SID file_owner_sid; + DOM_SID file_grp_sid; + SEC_ACL *dacl = psd->dacl; + BOOL all_aces_are_inherit_only = (is_directory ? True : False); + int i; +#ifdef WITH_SURS + SURS_POSIX_ID id; +#else + DOM_SID owner_sid; + DOM_SID grp_sid; + uint32 owner_rid; + uint32 grp_rid; +#endif + + *pmode = 0; + *puser = (uid_t) - 1; + *pgrp = (gid_t) - 1; + + if (security_info_sent == 0) + { + DEBUG(0, ("unpack_nt_permissions: " + "no security info sent !\n")); + return False; + } + + /* + * Windows 2000 sends the owner and group SIDs as the logged in + * user, not the connected user. But it still sends the file + * owner SIDs on an ACL set. So we need to check for the file + * owner and group SIDs as well as the owner SIDs. JRA. + */ + + if (!create_file_sids(psbuf, &file_owner_sid, &file_grp_sid)) + { + DEBUG(3, ("create_file_sids: uid or gid " + "not mapped to SIDS\n")); + return 0; + } + + /* + * Don't immediately fail if the owner sid cannot be validated. + * This may be a group chown only set. + */ + + DEBUG(0, ("TODO: LsaLookupSids to find type of owner_sid\n")); + +#ifdef WITH_SURS + if (security_info_sent & OWNER_SECURITY_INFORMATION && + surs_sam_sid_to_unixid(psd->owner_sid, &id, False) && + id.type == SURS_POSIX_UID) + { + *puser = (uid_t) id.id; + } + +#else + if (!validate_unix_sid(&owner_sid, &owner_rid, psd->owner_sid)) + DEBUG(3, + ("unpack_nt_permissions: unable to validate owner sid.\n")); + else if (security_info_sent & OWNER_SECURITY_INFORMATION) + *puser = pdb_user_rid_to_uid(owner_rid); + + if (security_info_sent & OWNER_SECURITY_INFORMATION) + { + *puser = pdb_user_rid_to_uid(owner_rid); + } + +#endif + /* + * Don't immediately fail if the group sid cannot be validated. + * This may be an owner chown only set. + */ + +#ifdef WITH_SURS + if (security_info_sent & GROUP_SECURITY_INFORMATION && + surs_sam_sid_to_unixid(psd->grp_sid, &id, False) && + (id.type == SURS_POSIX_GID)) + { + *pgrp = (gid_t) id.id; + } +#else + if (!validate_unix_sid(&grp_sid, &grp_rid, psd->grp_sid)) + DEBUG(3, + ("unpack_nt_permissions: unable to validate group sid.\n")); + else if (security_info_sent & GROUP_SECURITY_INFORMATION) + *pgrp = pdb_user_rid_to_gid(grp_rid); + +#endif + /* + * If no DACL then this is a chown only security descriptor. + */ + + if (!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) + { + *pmode = 0; + return True; + } + + /* + * Now go through the DACL and ensure that + * any owner/group sids match. + */ + + for (i = 0; i < dacl->num_aces; i++) + { + DOM_SID ace_sid; + SEC_ACE *psa = &dacl->ace[i]; + + if ((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && + (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) + { + DEBUG(3, ("unpack_nt_permissions: " + "unable to set anything but an " + "ALLOW or DENY ACE.\n")); + return False; + } + + /* + * Ignore or remove bits we don't care about on a directory ACE. + */ + + if (is_directory) + { + if (psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) + { + DEBUG(3, ("unpack_nt_permissions: " + "ignoring inherit only ACE.\n")); + continue; + } + + /* + * At least one of the ACE entries wasn't inherit only. + * Flag this so we know the returned mode is valid. + */ + + all_aces_are_inherit_only = False; + } + + /* + * Windows 2000 sets these flags even on *file* ACE's. + * This is wrong but we can ignore them for now. + * Revisit this when we go to POSIX ACLs on directories. + */ + + psa->flags &= + ~(SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_CONTAINER_INHERIT); + + if (psa->flags != 0) + { + DEBUG(1, + ("unpack_nt_permissions: unable to set ACE flags (%x).\n", + (unsigned int)psa->flags)); + return False; + } + + /* + * The security mask may be UNIX_ACCESS_NONE which + * should map into no permissions (we overload the + * WRITE_OWNER bit for this) or it should be one of + * the ALL/EXECUTE/READ/WRITE bits. Arrange for this + * to be so. Any other bits override the + * UNIX_ACCESS_NONE bit. + */ + + psa->info.mask &= + (GENERIC_ALL_ACCESS | GENERIC_EXECUTE_ACCESS | + GENERIC_WRITE_ACCESS | GENERIC_READ_ACCESS | + UNIX_ACCESS_NONE | FILE_ALL_ATTRIBUTES); + + if (psa->info.mask != UNIX_ACCESS_NONE) + psa->info.mask &= ~UNIX_ACCESS_NONE; + + sid_copy(&ace_sid, &psa->sid); + + if (sid_equal(&ace_sid, &file_owner_sid)) + { + /* + * Map the desired permissions into owner perms. + */ + + if (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms(psa->info, S_IRUSR); + else + *pmode &= ~(map_nt_perms(psa->info, S_IRUSR)); + + } + else if (sid_equal(&ace_sid, &file_grp_sid)) + { + /* + * Map the desired permissions into group perms. + */ + + if (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms(psa->info, S_IRGRP); + else + *pmode &= ~(map_nt_perms(psa->info, S_IRGRP)); + + } + else if (sid_equal(&ace_sid, global_sid_everyone)) + { + /* + * Map the desired permissions into other perms. + */ + + if (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) + *pmode |= map_nt_perms(psa->info, S_IROTH); + else + *pmode &= ~(map_nt_perms(psa->info, S_IROTH)); + + } + else + { + DEBUG(0, ("unpack_nt_permissions: " + "unknown SID used in ACL.\n")); + return False; + } + } + + if (is_directory && all_aces_are_inherit_only) + { + /* + * Windows 2000 is doing one of these weird 'inherit acl' + * traverses to conserve NTFS ACL resources. Just pretend + * there was no DACL sent. JRA. + */ + + DEBUG(10, ("unpack_nt_permissions: " + "Win2k inherit acl traverse. " + "Ignoring DACL.\n")); + free_sec_acl(psd->dacl); + safe_free(psd->dacl); + psd->dacl = NULL; + } + + return True; +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f64ca386f8..a149374114 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1823,74 +1823,14 @@ name = %s\n", fsp->fsp_name )); } /**************************************************************************** - Map unix perms to NT. -****************************************************************************/ - -static SEC_ACCESS map_unix_perms( int *pacl_type, mode_t perm, int r_mask, int w_mask, int x_mask, BOOL is_directory) -{ - SEC_ACCESS sa; - uint32 nt_mask = 0; - - *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED; - - if((perm & (r_mask|w_mask|x_mask)) == (r_mask|w_mask|x_mask)) { - nt_mask = UNIX_ACCESS_RWX; - } else if((perm & (r_mask|w_mask|x_mask)) == 0) { - nt_mask = UNIX_ACCESS_NONE; - } else { - nt_mask |= (perm & r_mask) ? UNIX_ACCESS_R : 0; - if(is_directory) - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - else - nt_mask |= (perm & w_mask) ? UNIX_ACCESS_W : 0; - nt_mask |= (perm & x_mask) ? UNIX_ACCESS_X : 0; - } - init_sec_access(&sa,nt_mask); - return sa; -} - -/**************************************************************************** - Function to create owner and group SIDs from a SMB_STRUCT_STAT. -****************************************************************************/ - -static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid) -{ - extern DOM_SID global_sam_sid; - - sid_copy(powner_sid, &global_sam_sid); - sid_copy(pgroup_sid, &global_sam_sid); - sid_append_rid(powner_sid, pdb_uid_to_user_rid(psbuf->st_uid)); - sid_append_rid(pgroup_sid, pdb_gid_to_group_rid(psbuf->st_gid)); -} - -/**************************************************************************** Reply to query a security descriptor from an fsp. If it succeeds it allocates the space for the return elements and returns True. ****************************************************************************/ static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) { - extern DOM_SID global_sid_World; SMB_STRUCT_STAT sbuf; - SEC_ACE ace_list[6]; - DOM_SID owner_sid; - DOM_SID group_sid; - size_t sec_desc_size; - SEC_ACL *psa = NULL; - SEC_ACCESS owner_access; - int owner_acl_type; - SEC_ACCESS group_access; - int grp_acl_type; - SEC_ACCESS other_access; - int other_acl_type; - int num_acls = 0; - - *ppdesc = NULL; - - if(!lp_nt_acl_support()) { - sid_copy( &owner_sid, &global_sid_World); - sid_copy( &group_sid, &global_sid_World); - } else { + mode_t mode; if(fsp->is_directory || fsp->fd == -1) { if(dos_stat(fsp->fsp_name, &sbuf) != 0) { @@ -1902,80 +1842,19 @@ static size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) } } - /* - * Get the owner, group and world SIDs. - */ - - create_file_sids(&sbuf, &owner_sid, &group_sid); - - /* - * Create the generic 3 element UNIX acl. - */ - - owner_access = map_unix_perms(&owner_acl_type, sbuf.st_mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, sbuf.st_mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, sbuf.st_mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); - - if(owner_access.mask) - init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, - owner_access, 0); - - if(group_access.mask) - init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, - group_access, 0); - - if(other_access.mask) - init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, - other_access, 0); - if(fsp->is_directory) { /* * For directory ACLs we also add in the inherited permissions * ACE entries. These are the permissions a file would get when * being created in the directory. */ - mode_t mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); - - owner_access = map_unix_perms(&owner_acl_type, mode, - S_IRUSR, S_IWUSR, S_IXUSR, fsp->is_directory); - group_access = map_unix_perms(&grp_acl_type, mode, - S_IRGRP, S_IWGRP, S_IXGRP, fsp->is_directory); - other_access = map_unix_perms(&other_acl_type, mode, - S_IROTH, S_IWOTH, S_IXOTH, fsp->is_directory); - - if(owner_access.mask) - init_sec_ace(&ace_list[num_acls++], &owner_sid, owner_acl_type, - owner_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - - if(group_access.mask) - init_sec_ace(&ace_list[num_acls++], &group_sid, grp_acl_type, - group_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - - if(other_access.mask) - init_sec_ace(&ace_list[num_acls++], &global_sid_World, other_acl_type, - other_access, SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); + mode = unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name); } - - if(num_acls) - if((psa = make_sec_acl( 3, num_acls, ace_list)) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); - return 0; - } - } - - *ppdesc = make_standard_sec_desc( &owner_sid, &group_sid, psa, &sec_desc_size); - - if(!*ppdesc) { - DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); - sec_desc_size = 0; - } - - free_sec_acl(&psa); - - return sec_desc_size; + else + { + mode = sbuf.st_mode; + } + return convertperms_unix_to_sd(&sbuf, fsp->is_directory, mode, ppdesc); } /**************************************************************************** @@ -1993,7 +1872,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *params = *ppparams; char *data = *ppdata; prs_struct pd; - SEC_DESC *psd; + SEC_DESC *psd = NULL; size_t sec_desc_size; files_struct *fsp = file_fsp(params,0); @@ -2020,7 +1899,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if(max_data_count < sec_desc_size) { - free_sec_desc(&psd); + free_sec_desc(psd); + safe_free(psd); send_nt_replies(inbuf, outbuf, bufsize, 0xC0000000|NT_STATUS_BUFFER_TOO_SMALL, params, 4, *ppdata, 0); @@ -2033,7 +1913,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, data = *ppdata = Realloc(*ppdata, sec_desc_size); if(data == NULL) { - free_sec_desc(&psd); + free_sec_desc(psd); + safe_free(psd); return(ERROR(ERRDOS,ERRnomem)); } @@ -2043,21 +1924,17 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Init the parse struct we will marshall into. */ - prs_init(&pd, 0, 4, MARSHALL); - - /* - * Setup the prs_struct to point at the memory we just - * allocated. - */ - - prs_give_memory( &pd, data, (uint32)sec_desc_size, False); + prs_init(&pd, sec_desc_size, 4, MARSHALL); /* * Finally, linearize into the outgoing buffer. */ - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { - free_sec_desc(&psd); + if(!sec_io_desc( "sd data", psd, &pd, 1)) + { + free_sec_desc(psd); + safe_free(psd); + prs_mem_free(&pd); DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \ security descriptor.\n")); /* @@ -2067,274 +1944,21 @@ security descriptor.\n")); } /* - * Now we can delete the security descriptor. - */ - - free_sec_desc(&psd); - - send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sec_desc_size); - return -1; -} - -/**************************************************************************** - Validate a SID. -****************************************************************************/ - -static BOOL validate_unix_sid( DOM_SID *psid, uint32 *prid, DOM_SID *sd_sid) -{ - extern DOM_SID global_sam_sid; - DOM_SID sid; - - if(!sd_sid) { - DEBUG(5,("validate_unix_sid: sid missing.\n")); - return False; - } - - sid_copy(psid, sd_sid); - sid_copy(&sid, sd_sid); - - if(!sid_split_rid(&sid, prid)) { - DEBUG(5,("validate_unix_sid: cannot get RID from sid.\n")); - return False; - } - - if(!sid_equal( &sid, &global_sam_sid)) { - DEBUG(5,("validate_unix_sid: sid is not ours.\n")); - return False; - } - - return True; -} - -/**************************************************************************** - Map NT perms to UNIX. -****************************************************************************/ - -#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES) -#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES) -#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE) - -static mode_t map_nt_perms( SEC_ACCESS sec_access, int type) -{ - mode_t mode = 0; - - switch(type) { - case S_IRUSR: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRUSR|S_IWUSR|S_IXUSR; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0; - } - break; - case S_IRGRP: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IRGRP|S_IWGRP|S_IXGRP; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0; - } - break; - case S_IROTH: - if(sec_access.mask & GENERIC_ALL_ACCESS) - mode = S_IROTH|S_IWOTH|S_IXOTH; - else { - mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0; - mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0; - mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0; - } - break; - } - - return mode; -} - -/**************************************************************************** - Unpack a SEC_DESC into a owner, group and set of UNIX permissions. -****************************************************************************/ - -static BOOL unpack_nt_permissions(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, mode_t *pmode, - uint32 security_info_sent, SEC_DESC *psd, BOOL is_directory) -{ - extern DOM_SID global_sid_World; - DOM_SID owner_sid; - DOM_SID grp_sid; - DOM_SID file_owner_sid; - DOM_SID file_grp_sid; - uint32 owner_rid; - uint32 grp_rid; - SEC_ACL *dacl = psd->dacl; - BOOL all_aces_are_inherit_only = (is_directory ? True : False); - int i; - - *pmode = 0; - *puser = (uid_t)-1; - *pgrp = (gid_t)-1; - - if(security_info_sent == 0) { - DEBUG(0,("unpack_nt_permissions: no security info sent !\n")); - return False; - } - - /* - * Windows 2000 sends the owner and group SIDs as the logged in - * user, not the connected user. But it still sends the file - * owner SIDs on an ACL set. So we need to check for the file - * owner and group SIDs as well as the owner SIDs. JRA. - */ - - create_file_sids(psbuf, &file_owner_sid, &file_grp_sid); - - /* - * Validate the owner and group SID's. - */ - - memset(&owner_sid, '\0', sizeof(owner_sid)); - memset(&grp_sid, '\0', sizeof(grp_sid)); - - DEBUG(5,("unpack_nt_permissions: validating owner_sid.\n")); - - /* - * Don't immediately fail if the owner sid cannot be validated. - * This may be a group chown only set. - */ - - if(!validate_unix_sid( &owner_sid, &owner_rid, psd->owner_sid)) - DEBUG(3,("unpack_nt_permissions: unable to validate owner sid.\n")); - else if(security_info_sent & OWNER_SECURITY_INFORMATION) - *puser = pdb_user_rid_to_uid(owner_rid); - - /* - * Don't immediately fail if the group sid cannot be validated. - * This may be an owner chown only set. - */ - - if(!validate_unix_sid( &grp_sid, &grp_rid, psd->grp_sid)) - DEBUG(3,("unpack_nt_permissions: unable to validate group sid.\n")); - else if(security_info_sent & GROUP_SECURITY_INFORMATION) - *pgrp = pdb_user_rid_to_gid(grp_rid); - - /* - * If no DACL then this is a chown only security descriptor. + * copy the data out of the marshalled structure */ - if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !dacl) { - *pmode = 0; - return True; - } + prs_give_memory( &pd, data, (uint32)sec_desc_size, False); /* - * Now go through the DACL and ensure that - * any owner/group sids match. + * Now we can delete the security descriptor. */ - for(i = 0; i < dacl->num_aces; i++) { - DOM_SID ace_sid; - SEC_ACE *psa = &dacl->ace[i]; - - if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && - (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) { - DEBUG(3,("unpack_nt_permissions: unable to set anything but an ALLOW or DENY ACE.\n")); - return False; - } - - /* - * Ignore or remove bits we don't care about on a directory ACE. - */ - - if(is_directory) { - if(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - DEBUG(3,("unpack_nt_permissions: ignoring inherit only ACE.\n")); - continue; - } - - /* - * At least one of the ACE entries wasn't inherit only. - * Flag this so we know the returned mode is valid. - */ + prs_mem_free(&pd); + free_sec_desc(psd); + safe_free(psd); - all_aces_are_inherit_only = False; - } - - /* - * Windows 2000 sets these flags even on *file* ACE's. This is wrong - * but we can ignore them for now. Revisit this when we go to POSIX - * ACLs on directories. - */ - - psa->flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT); - - if(psa->flags != 0) { - DEBUG(1,("unpack_nt_permissions: unable to set ACE flags (%x).\n", - (unsigned int)psa->flags)); - return False; - } - - /* - * The security mask may be UNIX_ACCESS_NONE which should map into - * no permissions (we overload the WRITE_OWNER bit for this) or it - * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this - * to be so. Any other bits override the UNIX_ACCESS_NONE bit. - */ - - psa->info.mask &= (GENERIC_ALL_ACCESS|GENERIC_EXECUTE_ACCESS|GENERIC_WRITE_ACCESS| - GENERIC_READ_ACCESS|UNIX_ACCESS_NONE|FILE_ALL_ATTRIBUTES); - - if(psa->info.mask != UNIX_ACCESS_NONE) - psa->info.mask &= ~UNIX_ACCESS_NONE; - - sid_copy(&ace_sid, &psa->sid); - - if(sid_equal(&ace_sid, &file_owner_sid)) { - /* - * Map the desired permissions into owner perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IRUSR); - else - *pmode &= ~(map_nt_perms( psa->info, S_IRUSR)); - - } else if( sid_equal(&ace_sid, &file_grp_sid)) { - /* - * Map the desired permissions into group perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IRGRP); - else - *pmode &= ~(map_nt_perms( psa->info, S_IRGRP)); - - } else if( sid_equal(&ace_sid, &global_sid_World)) { - /* - * Map the desired permissions into other perms. - */ - - if(psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - *pmode |= map_nt_perms( psa->info, S_IROTH); - else - *pmode &= ~(map_nt_perms( psa->info, S_IROTH)); - - } else { - DEBUG(0,("unpack_nt_permissions: unknown SID used in ACL.\n")); - return False; - } - } - - if (is_directory && all_aces_are_inherit_only) { - /* - * Windows 2000 is doing one of these weird 'inherit acl' - * traverses to conserve NTFS ACL resources. Just pretend - * there was no DACL sent. JRA. - */ - - DEBUG(10,("unpack_nt_permissions: Win2k inherit acl traverse. Ignoring DACL.\n")); - free_sec_acl(&psd->dacl); - } - - return True; + send_nt_replies(inbuf, outbuf, bufsize, 0, params, 4, data, (int)sec_desc_size); + return -1; } /**************************************************************************** @@ -2350,7 +1974,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *params= *ppparams; char *data = *ppdata; prs_struct pd; - SEC_DESC *psd = NULL; + SEC_DESC psd; uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); uid_t user = (uid_t)-1; gid_t grp = (gid_t)-1; @@ -2391,8 +2015,10 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, * Finally, unmarshall from the data buffer. */ - if(!sec_io_desc( "sd data", &psd, &pd, 1)) { + if(!sec_io_desc( "sd data", &psd, &pd, 1)) + { free_sec_desc(&psd); + prs_mem_free(&pd); DEBUG(0,("call_nt_transact_set_security_desc: Error in unmarshalling \ security descriptor.\n")); /* @@ -2402,6 +2028,12 @@ security descriptor.\n")); } /* + * finished with the marshalling structure, already + */ + + prs_mem_free(&pd); + + /* * Get the current state of the file. */ @@ -2429,12 +2061,12 @@ security descriptor.\n")); * Unpack the user/group/world id's and permissions. */ - if(!unpack_nt_permissions( &sbuf, &user, &grp, &perms, security_info_sent, psd, fsp->is_directory)) { + if(!convertperms_sd_to_unix( &sbuf, &user, &grp, &perms, security_info_sent, &psd, fsp->is_directory)) { free_sec_desc(&psd); return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (psd->dacl != NULL) + if (psd.dacl != NULL) got_dacl = True; free_sec_desc(&psd); |