mirror of
https://github.com/samba-team/samba.git
synced 2025-03-05 20:58:40 +03:00
fixed nttrans.c
This commit is contained in:
parent
f9f2a04fdb
commit
06cd46b0ec
@ -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 \
|
||||
|
@ -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 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_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,
|
||||
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 */
|
||||
|
@ -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;
|
||||
|
||||
|
679
source/lib/util_unixsd.c
Normal file
679
source/lib/util_unixsd.c
Normal file
@ -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;
|
||||
}
|
@ -1822,47 +1822,6 @@ name = %s\n", fsp->fsp_name ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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.
|
||||
@ -1870,27 +1829,8 @@ static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SI
|
||||
|
||||
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;
|
||||
else
|
||||
{
|
||||
mode = sbuf.st_mode;
|
||||
}
|
||||
}
|
||||
|
||||
*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;
|
||||
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"));
|
||||
/*
|
||||
@ -2066,277 +1943,24 @@ security descriptor.\n"));
|
||||
return(UNIXERROR(ERRDOS,ERRnoaccess));
|
||||
}
|
||||
|
||||
/*
|
||||
* copy the data out of the marshalled structure
|
||||
*/
|
||||
|
||||
prs_give_memory( &pd, data, (uint32)sec_desc_size, False);
|
||||
|
||||
/*
|
||||
* Now we can delete the security descriptor.
|
||||
*/
|
||||
|
||||
free_sec_desc(&psd);
|
||||
prs_mem_free(&pd);
|
||||
free_sec_desc(psd);
|
||||
safe_free(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.
|
||||
*/
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to set a security descriptor. Map to UNIX perms.
|
||||
****************************************************************************/
|
||||
@ -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"));
|
||||
/*
|
||||
@ -2401,6 +2027,12 @@ security descriptor.\n"));
|
||||
return(UNIXERROR(ERRDOS,ERRnoaccess));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user