@@ -42,6 +42,35 @@ static const struct cifs_sid sid_authusers = {
4242/* group users */
4343static const struct cifs_sid sid_user = {1 , 2 , {0 , 0 , 0 , 0 , 0 , 5 }, {} };
4444
45+ /* S-1-22-1 Unmapped Unix users */
46+ static const struct cifs_sid sid_unix_users = {1 , 1 , {0 , 0 , 0 , 0 , 0 , 22 },
47+ {cpu_to_le32 (1 ), 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } };
48+
49+ /* S-1-22-2 Unmapped Unix groups */
50+ static const struct cifs_sid sid_unix_groups = { 1 , 1 , {0 , 0 , 0 , 0 , 0 , 22 },
51+ {cpu_to_le32 (2 ), 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } };
52+
53+ /*
54+ * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
55+ */
56+
57+ /* S-1-5-88 MS NFS and Apple style UID/GID/mode */
58+
59+ /* S-1-5-88-1 Unix uid */
60+ static const struct cifs_sid sid_unix_NFS_users = { 1 , 2 , {0 , 0 , 0 , 0 , 0 , 5 },
61+ {cpu_to_le32 (88 ),
62+ cpu_to_le32 (1 ), 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } };
63+
64+ /* S-1-5-88-2 Unix gid */
65+ static const struct cifs_sid sid_unix_NFS_groups = { 1 , 2 , {0 , 0 , 0 , 0 , 0 , 5 },
66+ {cpu_to_le32 (88 ),
67+ cpu_to_le32 (2 ), 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } };
68+
69+ /* S-1-5-88-3 Unix mode */
70+ static const struct cifs_sid sid_unix_NFS_mode = { 1 , 2 , {0 , 0 , 0 , 0 , 0 , 5 },
71+ {cpu_to_le32 (88 ),
72+ cpu_to_le32 (3 ), 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } };
73+
4574static const struct cred * root_cred ;
4675
4776static int
@@ -183,6 +212,62 @@ compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
183212 return 0 ; /* sids compare/match */
184213}
185214
215+ static bool
216+ is_well_known_sid (const struct cifs_sid * psid , uint32_t * puid , bool is_group )
217+ {
218+ int i ;
219+ int num_subauth ;
220+ const struct cifs_sid * pwell_known_sid ;
221+
222+ if (!psid || (puid == NULL ))
223+ return false;
224+
225+ num_subauth = psid -> num_subauth ;
226+
227+ /* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
228+ if (num_subauth == 2 ) {
229+ if (is_group )
230+ pwell_known_sid = & sid_unix_groups ;
231+ else
232+ pwell_known_sid = & sid_unix_users ;
233+ } else if (num_subauth == 3 ) {
234+ if (is_group )
235+ pwell_known_sid = & sid_unix_NFS_groups ;
236+ else
237+ pwell_known_sid = & sid_unix_NFS_users ;
238+ } else
239+ return false;
240+
241+ /* compare the revision */
242+ if (psid -> revision != pwell_known_sid -> revision )
243+ return false;
244+
245+ /* compare all of the six auth values */
246+ for (i = 0 ; i < NUM_AUTHS ; ++ i ) {
247+ if (psid -> authority [i ] != pwell_known_sid -> authority [i ]) {
248+ cifs_dbg (FYI , "auth %d did not match\n" , i );
249+ return false;
250+ }
251+ }
252+
253+ if (num_subauth == 2 ) {
254+ if (psid -> sub_auth [0 ] != pwell_known_sid -> sub_auth [0 ])
255+ return false;
256+
257+ * puid = le32_to_cpu (psid -> sub_auth [1 ]);
258+ } else /* 3 subauths, ie Windows/Mac style */ {
259+ * puid = le32_to_cpu (psid -> sub_auth [0 ]);
260+ if ((psid -> sub_auth [0 ] != pwell_known_sid -> sub_auth [0 ]) ||
261+ (psid -> sub_auth [1 ] != pwell_known_sid -> sub_auth [1 ]))
262+ return false;
263+
264+ * puid = le32_to_cpu (psid -> sub_auth [2 ]);
265+ }
266+
267+ cifs_dbg (FYI , "Unix UID %d returned from SID\n" , * puid );
268+ return true; /* well known sid found, uid returned */
269+ }
270+
186271static void
187272cifs_copy_sid (struct cifs_sid * dst , const struct cifs_sid * src )
188273{
@@ -276,6 +361,43 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
276361 return - EIO ;
277362 }
278363
364+ if (cifs_sb -> mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL ) {
365+ uint32_t unix_id ;
366+ bool is_group ;
367+
368+ if (sidtype != SIDOWNER )
369+ is_group = true;
370+ else
371+ is_group = false;
372+
373+ if (is_well_known_sid (psid , & unix_id , is_group ) == false)
374+ goto try_upcall_to_get_id ;
375+
376+ if (is_group ) {
377+ kgid_t gid ;
378+ gid_t id ;
379+
380+ id = (gid_t )unix_id ;
381+ gid = make_kgid (& init_user_ns , id );
382+ if (gid_valid (gid )) {
383+ fgid = gid ;
384+ goto got_valid_id ;
385+ }
386+ } else {
387+ kuid_t uid ;
388+ uid_t id ;
389+
390+ id = (uid_t )unix_id ;
391+ uid = make_kuid (& init_user_ns , id );
392+ if (uid_valid (uid )) {
393+ fuid = uid ;
394+ goto got_valid_id ;
395+ }
396+ }
397+ /* If unable to find uid/gid easily from SID try via upcall */
398+ }
399+
400+ try_upcall_to_get_id :
279401 sidstr = sid_to_key_str (psid , sidtype );
280402 if (!sidstr )
281403 return - ENOMEM ;
@@ -329,6 +451,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
329451 * Note that we return 0 here unconditionally. If the mapping
330452 * fails then we just fall back to using the mnt_uid/mnt_gid.
331453 */
454+ got_valid_id :
332455 if (sidtype == SIDOWNER )
333456 fattr -> cf_uid = fuid ;
334457 else
0 commit comments