system.c: fix fake directory create times
[samba.git] / source3 / lib / util_sid.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell                1992-1998
5    Copyright (C) Luke Kenneth Caseson Leighton  1998-1999
6    Copyright (C) Jeremy Allison                 1999
7    Copyright (C) Stefan (metze) Metzmacher      2002
8    Copyright (C) Simo Sorce                     2002
9    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "../librpc/gen_ndr/ndr_security.h"
27 #include "../librpc/gen_ndr/netlogon.h"
28 #include "../libcli/security/security.h"
29 #include "lib/util/string_wrappers.h"
30 #include "source3/lib/util_specialsids.h"
31
32
33 /*****************************************************************
34  Convert a SID to an ascii string.
35 *****************************************************************/
36
37 char *sid_to_fstring(fstring sidstr_out, const struct dom_sid *sid)
38 {
39         struct dom_sid_buf buf;
40         fstrcpy(sidstr_out, dom_sid_str_buf(sid, &buf));
41         return sidstr_out;
42 }
43
44 /*****************************************************************
45  Write a sid out into on-the-wire format.
46 *****************************************************************/  
47
48 bool sid_linearize(uint8_t *outbuf, size_t len, const struct dom_sid *sid)
49 {
50         struct ndr_push ndr = {
51                 .data = outbuf, .alloc_size = len, .fixed_buf_size = true,
52         };
53         enum ndr_err_code ndr_err;
54
55         ndr_err = ndr_push_dom_sid(&ndr, NDR_SCALARS|NDR_BUFFERS, sid);
56         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
57 }
58
59 /*****************************************************************
60  Returns true if SID is internal (and non-mappable).
61 *****************************************************************/
62
63 bool non_mappable_sid(struct dom_sid *sid)
64 {
65         struct dom_sid dom;
66
67         sid_copy(&dom, sid);
68         sid_split_rid(&dom, NULL);
69
70         if (dom_sid_equal(&dom, &global_sid_Builtin))
71                 return True;
72
73         if (dom_sid_equal(&dom, &global_sid_NT_Authority))
74                 return True;
75
76         return False;
77 }
78
79 /*****************************************************************
80  Return the binary string representation of a struct dom_sid.
81  Caller must free.
82 *****************************************************************/
83
84 char *sid_binstring_hex_talloc(TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
85 {
86         int len = ndr_size_dom_sid(sid, 0);
87         uint8_t buf[len];
88         sid_linearize(buf, len, sid);
89         return hex_encode_talloc(mem_ctx, buf, len);
90 }
91
92 NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx,
93                               const struct netr_SamInfo3 *info3,
94                               struct dom_sid **user_sids,
95                               uint32_t *num_user_sids,
96                               bool include_user_group_rid)
97 {
98         NTSTATUS status;
99         struct dom_sid sid;
100         struct dom_sid *sid_array = NULL;
101         uint32_t num_sids = 0;
102         uint32_t i;
103
104         if (include_user_group_rid) {
105                 if (!sid_compose(&sid, info3->base.domain_sid, info3->base.rid)) {
106                         DEBUG(3, ("could not compose user SID from rid 0x%x\n",
107                                   info3->base.rid));
108                         return NT_STATUS_INVALID_PARAMETER;
109                 }
110                 status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
111                 if (!NT_STATUS_IS_OK(status)) {
112                         DEBUG(3, ("could not append user SID from rid 0x%x\n",
113                                   info3->base.rid));
114                         return status;
115                 }
116         }
117
118         if (!sid_compose(&sid, info3->base.domain_sid, info3->base.primary_gid)) {
119                 DEBUG(3, ("could not compose group SID from rid 0x%x\n",
120                           info3->base.primary_gid));
121                 return NT_STATUS_INVALID_PARAMETER;
122         }
123         status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
124         if (!NT_STATUS_IS_OK(status)) {
125                 DEBUG(3, ("could not append group SID from rid 0x%x\n",
126                           info3->base.rid));
127                 return status;
128         }
129
130         for (i = 0; i < info3->base.groups.count; i++) {
131                 /* Don't add the primary group sid twice. */
132                 if (!sid_compose(&sid, info3->base.domain_sid,
133                                  info3->base.groups.rids[i].rid)) {
134                         DEBUG(3, ("could not compose SID from additional group "
135                                   "rid 0x%x\n", info3->base.groups.rids[i].rid));
136                         return NT_STATUS_INVALID_PARAMETER;
137                 }
138                 status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
139                 if (!NT_STATUS_IS_OK(status)) {
140                         DEBUG(3, ("could not append SID from additional group "
141                                   "rid 0x%x\n", info3->base.groups.rids[i].rid));
142                         return status;
143                 }
144         }
145
146         /* Copy 'other' sids.  We need to do sid filtering here to
147            prevent possible elevation of privileges.  See:
148
149            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
150          */
151
152         for (i = 0; i < info3->sidcount; i++) {
153
154                 if (sid_check_is_in_asserted_identity(info3->sids[i].sid)) {
155                         continue;
156                 }
157
158                 status = add_sid_to_array(mem_ctx, info3->sids[i].sid,
159                                       &sid_array, &num_sids);
160                 if (!NT_STATUS_IS_OK(status)) {
161                         struct dom_sid_buf buf;
162                         DEBUG(3, ("could not add SID to array: %s\n",
163                                   dom_sid_str_buf(info3->sids[i].sid, &buf)));
164                         return status;
165                 }
166         }
167
168         *user_sids = sid_array;
169         *num_user_sids = num_sids;
170
171         return NT_STATUS_OK;
172 }
173
174 bool security_token_find_npa_flags(const struct security_token *token,
175                                    uint32_t *_flags)
176 {
177         const struct dom_sid *npa_flags_sid = NULL;
178         size_t num_npa_sids;
179
180         num_npa_sids =
181                 security_token_count_flag_sids(token,
182                                                &global_sid_Samba_NPA_Flags,
183                                                1,
184                                                &npa_flags_sid);
185         if (num_npa_sids != 1) {
186                 return false;
187         }
188
189         sid_peek_rid(npa_flags_sid, _flags);
190         return true;
191 }
192
193 void security_token_del_npa_flags(struct security_token *token)
194 {
195         const struct dom_sid *npa_flags_sid = NULL;
196         size_t num_npa_sids;
197
198         num_npa_sids =
199                 security_token_count_flag_sids(token,
200                                                &global_sid_Samba_NPA_Flags,
201                                                1,
202                                                &npa_flags_sid);
203         SMB_ASSERT(num_npa_sids == 1);
204
205         del_sid_from_array(npa_flags_sid, &token->sids, &token->num_sids);
206 }