samba: fix some security problems
[openwrt.git] / package / network / services / samba36 / patches / 015-patch-cve-2015-7560.patch
1 From eb27f9b7bf9c1dc902d9545eecf805831bd4e46c Mon Sep 17 00:00:00 2001
2 From: Jeremy Allison <jra@samba.org>
3 Date: Tue, 5 Jan 2016 11:18:12 -0800
4 Subject: [PATCH 1/8] CVE-2015-7560: s3: smbd: Add refuse_symlink() function
5  that can be used to prevent operations on a symlink.
6
7 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11648
8
9 Signed-off-by: Jeremy Allison <jra@samba.org>
10 Reviewed-by: Michael Adam <obnox@samba.org>
11 ---
12  source3/smbd/trans2.c | 28 ++++++++++++++++++++++++++++
13  1 file changed, 28 insertions(+)
14
15 --- a/source3/smbd/trans2.c
16 +++ b/source3/smbd/trans2.c
17 @@ -51,6 +51,34 @@ static char *store_file_unix_basic_info2
18                                 files_struct *fsp,
19                                 const SMB_STRUCT_STAT *psbuf);
20  
21 +/****************************************************************************
22 + Check if an open file handle or pathname is a symlink.
23 +****************************************************************************/
24 +
25 +static NTSTATUS refuse_symlink(connection_struct *conn,
26 +                       const files_struct *fsp,
27 +                       const char *name)
28 +{
29 +       SMB_STRUCT_STAT sbuf;
30 +       const SMB_STRUCT_STAT *pst = NULL;
31 +
32 +       if (fsp) {
33 +               pst = &fsp->fsp_name->st;
34 +       } else {
35 +               int ret = vfs_stat_smb_fname(conn,
36 +                               name,
37 +                               &sbuf);
38 +               if (ret == -1) {
39 +                       return map_nt_error_from_unix(errno);
40 +               }
41 +               pst = &sbuf;
42 +       }
43 +       if (S_ISLNK(pst->st_ex_mode)) {
44 +               return NT_STATUS_ACCESS_DENIED;
45 +       }
46 +       return NT_STATUS_OK;
47 +}
48 +
49  /********************************************************************
50   Roundup a value to the nearest allocation roundup size boundary.
51   Only do this for Windows clients.
52 @@ -181,12 +209,22 @@ NTSTATUS get_ea_names_from_file(TALLOC_C
53         char **names, **tmp;
54         size_t num_names;
55         ssize_t sizeret = -1;
56 +       NTSTATUS status;
57 +
58 +       if (pnames) {
59 +               *pnames = NULL;
60 +       }
61 +       *pnum_names = 0;
62  
63         if (!lp_ea_support(SNUM(conn))) {
64 -               if (pnames) {
65 -                       *pnames = NULL;
66 -               }
67 -               *pnum_names = 0;
68 +               return NT_STATUS_OK;
69 +       }
70 +
71 +       status = refuse_symlink(conn, fsp, fname);
72 +       if (!NT_STATUS_IS_OK(status)) {
73 +               /*
74 +                * Just return no EA's on a symlink.
75 +                */
76                 return NT_STATUS_OK;
77         }
78  
79 @@ -236,10 +274,6 @@ NTSTATUS get_ea_names_from_file(TALLOC_C
80  
81         if (sizeret == 0) {
82                 TALLOC_FREE(names);
83 -               if (pnames) {
84 -                       *pnames = NULL;
85 -               }
86 -               *pnum_names = 0;
87                 return NT_STATUS_OK;
88         }
89  
90 @@ -550,6 +584,7 @@ NTSTATUS set_ea(connection_struct *conn,
91                 const struct smb_filename *smb_fname, struct ea_list *ea_list)
92  {
93         char *fname = NULL;
94 +       NTSTATUS status;
95  
96         if (!lp_ea_support(SNUM(conn))) {
97                 return NT_STATUS_EAS_NOT_SUPPORTED;
98 @@ -559,6 +594,12 @@ NTSTATUS set_ea(connection_struct *conn,
99                 return NT_STATUS_ACCESS_DENIED;
100         }
101  
102 +       status = refuse_symlink(conn, fsp, smb_fname->base_name);
103 +       if (!NT_STATUS_IS_OK(status)) {
104 +               return status;
105 +       }
106 +
107 +
108         /* For now setting EAs on streams isn't supported. */
109         fname = smb_fname->base_name;
110  
111 @@ -4931,6 +4972,13 @@ NTSTATUS smbd_do_qfilepathinfo(connectio
112                                 uint16 num_file_acls = 0;
113                                 uint16 num_def_acls = 0;
114  
115 +                               status = refuse_symlink(conn,
116 +                                               fsp,
117 +                                               smb_fname->base_name);
118 +                               if (!NT_STATUS_IS_OK(status)) {
119 +                                       return status;
120 +                               }
121 +
122                                 if (fsp && fsp->fh->fd != -1) {
123                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
124                                 } else {
125 @@ -6452,6 +6500,7 @@ static NTSTATUS smb_set_posix_acl(connec
126         uint16 num_def_acls;
127         bool valid_file_acls = True;
128         bool valid_def_acls = True;
129 +       NTSTATUS status;
130  
131         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
132                 return NT_STATUS_INVALID_PARAMETER;
133 @@ -6479,6 +6528,11 @@ static NTSTATUS smb_set_posix_acl(connec
134                 return NT_STATUS_INVALID_PARAMETER;
135         }
136  
137 +       status = refuse_symlink(conn, fsp, smb_fname->base_name);
138 +       if (!NT_STATUS_IS_OK(status)) {
139 +               return status;
140 +       }
141 +
142         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
143                 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
144                 (unsigned int)num_file_acls,
145 --- a/source3/smbd/nttrans.c
146 +++ b/source3/smbd/nttrans.c
147 @@ -877,6 +877,12 @@ NTSTATUS set_sd(files_struct *fsp, struc
148                 return NT_STATUS_OK;
149         }
150  
151 +       if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
152 +               DEBUG(10, ("ACL set on symlink %s denied.\n",
153 +                       fsp_str_dbg(fsp)));
154 +               return NT_STATUS_ACCESS_DENIED;
155 +       }
156 +
157         if (psd->owner_sid == NULL) {
158                 security_info_sent &= ~SECINFO_OWNER;
159         }
160 @@ -1925,6 +1931,12 @@ NTSTATUS smbd_do_query_security_desc(con
161                 return NT_STATUS_ACCESS_DENIED;
162         }
163  
164 +       if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
165 +               DEBUG(10, ("ACL get on symlink %s denied.\n",
166 +                       fsp_str_dbg(fsp)));
167 +               return NT_STATUS_ACCESS_DENIED;
168 +       }
169 +
170         if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|
171                         SECINFO_GROUP|SECINFO_SACL)) {
172                 /* Don't return SECINFO_LABEL if anything else was