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 
30 
31 /*****************************************************************
32  Convert a SID to an ascii string.
33 *****************************************************************/
34 
sid_to_fstring(fstring sidstr_out,const struct dom_sid * sid)35 char *sid_to_fstring(fstring sidstr_out, const struct dom_sid *sid)
36 {
37 	struct dom_sid_buf buf;
38 	fstrcpy(sidstr_out, dom_sid_str_buf(sid, &buf));
39 	return sidstr_out;
40 }
41 
42 /*****************************************************************
43  Write a sid out into on-the-wire format.
44 *****************************************************************/
45 
sid_linearize(uint8_t * outbuf,size_t len,const struct dom_sid * sid)46 bool sid_linearize(uint8_t *outbuf, size_t len, const struct dom_sid *sid)
47 {
48 	int8_t i;
49 
50 	if (len < ndr_size_dom_sid(sid, 0))
51 		return False;
52 
53 	SCVAL(outbuf,0,sid->sid_rev_num);
54 	SCVAL(outbuf,1,sid->num_auths);
55 	memcpy(&outbuf[2], sid->id_auth, 6);
56 	for(i = 0; i < sid->num_auths; i++)
57 		SIVAL(outbuf, 8 + (i*4), sid->sub_auths[i]);
58 
59 	return True;
60 }
61 
62 /*****************************************************************
63  Returns true if SID is internal (and non-mappable).
64 *****************************************************************/
65 
non_mappable_sid(struct dom_sid * sid)66 bool non_mappable_sid(struct dom_sid *sid)
67 {
68 	struct dom_sid dom;
69 
70 	sid_copy(&dom, sid);
71 	sid_split_rid(&dom, NULL);
72 
73 	if (dom_sid_equal(&dom, &global_sid_Builtin))
74 		return True;
75 
76 	if (dom_sid_equal(&dom, &global_sid_NT_Authority))
77 		return True;
78 
79 	return False;
80 }
81 
82 /*****************************************************************
83  Return the binary string representation of a struct dom_sid.
84  Caller must free.
85 *****************************************************************/
86 
sid_binstring_hex_talloc(TALLOC_CTX * mem_ctx,const struct dom_sid * sid)87 char *sid_binstring_hex_talloc(TALLOC_CTX *mem_ctx, const struct dom_sid *sid)
88 {
89 	int len = ndr_size_dom_sid(sid, 0);
90 	uint8_t buf[len];
91 	sid_linearize(buf, len, sid);
92 	return hex_encode_talloc(mem_ctx, buf, len);
93 }
94 
sid_array_from_info3(TALLOC_CTX * mem_ctx,const struct netr_SamInfo3 * info3,struct dom_sid ** user_sids,uint32_t * num_user_sids,bool include_user_group_rid)95 NTSTATUS sid_array_from_info3(TALLOC_CTX *mem_ctx,
96 			      const struct netr_SamInfo3 *info3,
97 			      struct dom_sid **user_sids,
98 			      uint32_t *num_user_sids,
99 			      bool include_user_group_rid)
100 {
101 	NTSTATUS status;
102 	struct dom_sid sid;
103 	struct dom_sid *sid_array = NULL;
104 	uint32_t num_sids = 0;
105 	uint32_t i;
106 
107 	if (include_user_group_rid) {
108 		if (!sid_compose(&sid, info3->base.domain_sid, info3->base.rid)) {
109 			DEBUG(3, ("could not compose user SID from rid 0x%x\n",
110 				  info3->base.rid));
111 			return NT_STATUS_INVALID_PARAMETER;
112 		}
113 		status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
114 		if (!NT_STATUS_IS_OK(status)) {
115 			DEBUG(3, ("could not append user SID from rid 0x%x\n",
116 				  info3->base.rid));
117 			return status;
118 		}
119 	}
120 
121 	if (!sid_compose(&sid, info3->base.domain_sid, info3->base.primary_gid)) {
122 		DEBUG(3, ("could not compose group SID from rid 0x%x\n",
123 			  info3->base.primary_gid));
124 		return NT_STATUS_INVALID_PARAMETER;
125 	}
126 	status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
127 	if (!NT_STATUS_IS_OK(status)) {
128 		DEBUG(3, ("could not append group SID from rid 0x%x\n",
129 			  info3->base.rid));
130 		return status;
131 	}
132 
133 	for (i = 0; i < info3->base.groups.count; i++) {
134 		/* Don't add the primary group sid twice. */
135 		if (info3->base.primary_gid == info3->base.groups.rids[i].rid) {
136 			continue;
137 		}
138 		if (!sid_compose(&sid, info3->base.domain_sid,
139 				 info3->base.groups.rids[i].rid)) {
140 			DEBUG(3, ("could not compose SID from additional group "
141 				  "rid 0x%x\n", info3->base.groups.rids[i].rid));
142 			return NT_STATUS_INVALID_PARAMETER;
143 		}
144 		status = add_sid_to_array(mem_ctx, &sid, &sid_array, &num_sids);
145 		if (!NT_STATUS_IS_OK(status)) {
146 			DEBUG(3, ("could not append SID from additional group "
147 				  "rid 0x%x\n", info3->base.groups.rids[i].rid));
148 			return status;
149 		}
150 	}
151 
152 	/* Copy 'other' sids.  We need to do sid filtering here to
153  	   prevent possible elevation of privileges.  See:
154 
155            http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
156          */
157 
158 	for (i = 0; i < info3->sidcount; i++) {
159 
160 		if (sid_check_is_in_asserted_identity(info3->sids[i].sid)) {
161 			continue;
162 		}
163 
164 		status = add_sid_to_array(mem_ctx, info3->sids[i].sid,
165 				      &sid_array, &num_sids);
166 		if (!NT_STATUS_IS_OK(status)) {
167 			struct dom_sid_buf buf;
168 			DEBUG(3, ("could not add SID to array: %s\n",
169 				  dom_sid_str_buf(info3->sids[i].sid, &buf)));
170 			return status;
171 		}
172 	}
173 
174 	*user_sids = sid_array;
175 	*num_user_sids = num_sids;
176 
177 	return NT_STATUS_OK;
178 }
179