2 Unix SMB/CIFS implementation.
4 Convert a server info struct into the form for PAC and NETLOGON replies
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "auth/auth.h"
25 #include "libcli/security/security.h"
26 #include "auth/auth_sam_reply.h"
28 NTSTATUS
auth_convert_server_info_sambaseinfo(TALLOC_CTX
*mem_ctx
,
29 struct auth_serversupplied_info
*server_info
,
30 struct netr_SamBaseInfo
**_sam
)
32 struct netr_SamBaseInfo
*sam
= talloc_zero(mem_ctx
, struct netr_SamBaseInfo
);
33 NT_STATUS_HAVE_NO_MEMORY(sam
);
35 sam
->domain_sid
= dom_sid_dup(mem_ctx
, server_info
->account_sid
);
36 NT_STATUS_HAVE_NO_MEMORY(sam
->domain_sid
);
37 sam
->domain_sid
->num_auths
--;
39 sam
->last_logon
= server_info
->last_logon
;
40 sam
->last_logoff
= server_info
->last_logoff
;
41 sam
->acct_expiry
= server_info
->acct_expiry
;
42 sam
->last_password_change
= server_info
->last_password_change
;
43 sam
->allow_password_change
= server_info
->allow_password_change
;
44 sam
->force_password_change
= server_info
->force_password_change
;
46 sam
->account_name
.string
= server_info
->account_name
;
47 sam
->full_name
.string
= server_info
->full_name
;
48 sam
->logon_script
.string
= server_info
->logon_script
;
49 sam
->profile_path
.string
= server_info
->profile_path
;
50 sam
->home_directory
.string
= server_info
->home_directory
;
51 sam
->home_drive
.string
= server_info
->home_drive
;
53 sam
->logon_count
= server_info
->logon_count
;
54 sam
->bad_password_count
= sam
->bad_password_count
;
55 sam
->rid
= server_info
->account_sid
->sub_auths
[server_info
->account_sid
->num_auths
-1];
56 sam
->primary_gid
= server_info
->primary_group_sid
->sub_auths
[server_info
->primary_group_sid
->num_auths
-1];
58 sam
->groups
.count
= 0;
59 sam
->groups
.rids
= NULL
;
61 if (server_info
->n_domain_groups
> 0) {
63 sam
->groups
.rids
= talloc_array(sam
, struct samr_RidWithAttribute
,
64 server_info
->n_domain_groups
);
66 if (sam
->groups
.rids
== NULL
)
67 return NT_STATUS_NO_MEMORY
;
69 for (i
=0; i
<server_info
->n_domain_groups
; i
++) {
70 struct dom_sid
*group_sid
= server_info
->domain_groups
[i
];
71 if (!dom_sid_in_domain(sam
->domain_sid
, group_sid
)) {
72 /* We handle this elsewhere */
75 sam
->groups
.rids
[sam
->groups
.count
].rid
=
76 group_sid
->sub_auths
[group_sid
->num_auths
-1];
78 sam
->groups
.rids
[sam
->groups
.count
].attributes
=
79 SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_ENABLED
;
80 sam
->groups
.count
+= 1;
84 sam
->user_flags
= 0; /* w2k3 uses NETLOGON_EXTRA_SIDS | NETLOGON_NTLMV2_ENABLED */
85 sam
->acct_flags
= server_info
->acct_flags
;
86 sam
->logon_server
.string
= server_info
->logon_server
;
87 sam
->domain
.string
= server_info
->domain_name
;
89 ZERO_STRUCT(sam
->unknown
);
91 ZERO_STRUCT(sam
->key
);
92 if (server_info
->user_session_key
.length
== sizeof(sam
->key
.key
)) {
93 memcpy(sam
->key
.key
, server_info
->user_session_key
.data
, sizeof(sam
->key
.key
));
96 ZERO_STRUCT(sam
->LMSessKey
);
97 if (server_info
->lm_session_key
.length
== sizeof(sam
->LMSessKey
.key
)) {
98 memcpy(sam
->LMSessKey
.key
, server_info
->lm_session_key
.data
,
99 sizeof(sam
->LMSessKey
.key
));
107 /* Note that the validity of the _sam3 structure is only as long as
108 * the server_info it was generated from */
109 NTSTATUS
auth_convert_server_info_saminfo3(TALLOC_CTX
*mem_ctx
,
110 struct auth_serversupplied_info
*server_info
,
111 struct netr_SamInfo3
**_sam3
)
113 struct netr_SamBaseInfo
*sam
;
114 struct netr_SamInfo3
*sam3
= talloc_zero(mem_ctx
, struct netr_SamInfo3
);
117 NT_STATUS_HAVE_NO_MEMORY(sam3
);
119 status
= auth_convert_server_info_sambaseinfo(mem_ctx
, server_info
, &sam
);
120 if (!NT_STATUS_IS_OK(status
)) {
128 sam3
->sids
= talloc_array(sam
, struct netr_SidAttr
,
129 server_info
->n_domain_groups
);
130 NT_STATUS_HAVE_NO_MEMORY(sam3
->sids
);
132 for (i
=0; i
<server_info
->n_domain_groups
; i
++) {
133 if (dom_sid_in_domain(sam
->domain_sid
, server_info
->domain_groups
[i
])) {
136 sam3
->sids
[sam3
->sidcount
].sid
= talloc_reference(sam3
->sids
,server_info
->domain_groups
[i
]);
137 sam3
->sids
[sam3
->sidcount
].attributes
=
138 SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_ENABLED
;
141 if (sam3
->sidcount
) {
142 sam3
->base
.user_flags
|= NETLOGON_EXTRA_SIDS
;
152 * Make a server_info struct from the info3 returned by a domain logon
154 NTSTATUS
make_server_info_netlogon_validation(TALLOC_CTX
*mem_ctx
,
155 const char *account_name
,
156 uint16_t validation_level
,
157 union netr_Validation
*validation
,
158 struct auth_serversupplied_info
**_server_info
)
160 struct auth_serversupplied_info
*server_info
;
161 struct netr_SamBaseInfo
*base
= NULL
;
164 switch (validation_level
) {
166 if (!validation
|| !validation
->sam2
) {
167 return NT_STATUS_INVALID_PARAMETER
;
169 base
= &validation
->sam2
->base
;
172 if (!validation
|| !validation
->sam3
) {
173 return NT_STATUS_INVALID_PARAMETER
;
175 base
= &validation
->sam3
->base
;
178 if (!validation
|| !validation
->sam6
) {
179 return NT_STATUS_INVALID_PARAMETER
;
181 base
= &validation
->sam6
->base
;
184 return NT_STATUS_INVALID_LEVEL
;
187 server_info
= talloc(mem_ctx
, struct auth_serversupplied_info
);
188 NT_STATUS_HAVE_NO_MEMORY(server_info
);
191 Here is where we should check the list of
192 trusted domains, and verify that the SID
195 server_info
->account_sid
= dom_sid_add_rid(server_info
, base
->domain_sid
, base
->rid
);
196 NT_STATUS_HAVE_NO_MEMORY(server_info
->account_sid
);
199 server_info
->primary_group_sid
= dom_sid_add_rid(server_info
, base
->domain_sid
, base
->primary_gid
);
200 NT_STATUS_HAVE_NO_MEMORY(server_info
->primary_group_sid
);
202 server_info
->n_domain_groups
= base
->groups
.count
;
203 if (base
->groups
.count
) {
204 server_info
->domain_groups
= talloc_array(server_info
, struct dom_sid
*, base
->groups
.count
);
205 NT_STATUS_HAVE_NO_MEMORY(server_info
->domain_groups
);
207 server_info
->domain_groups
= NULL
;
210 for (i
= 0; i
< base
->groups
.count
; i
++) {
211 server_info
->domain_groups
[i
] = dom_sid_add_rid(server_info
->domain_groups
, base
->domain_sid
, base
->groups
.rids
[i
].rid
);
212 NT_STATUS_HAVE_NO_MEMORY(server_info
->domain_groups
[i
]);
215 /* Copy 'other' sids. We need to do sid filtering here to
216 prevent possible elevation of privileges. See:
218 http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
221 if (validation_level
== 3) {
222 struct dom_sid
**dgrps
= server_info
->domain_groups
;
223 size_t sidcount
= server_info
->n_domain_groups
+ validation
->sam3
->sidcount
;
224 size_t n_dgrps
= server_info
->n_domain_groups
;
226 if (validation
->sam3
->sidcount
> 0) {
227 dgrps
= talloc_realloc(server_info
, dgrps
, struct dom_sid
*, sidcount
);
228 NT_STATUS_HAVE_NO_MEMORY(dgrps
);
230 for (i
= 0; i
< validation
->sam3
->sidcount
; i
++) {
231 dgrps
[n_dgrps
+ i
] = talloc_reference(dgrps
, validation
->sam3
->sids
[i
].sid
);
235 server_info
->n_domain_groups
= sidcount
;
236 server_info
->domain_groups
= dgrps
;
238 /* Where are the 'global' sids?... */
241 if (base
->account_name
.string
) {
242 server_info
->account_name
= talloc_reference(server_info
, base
->account_name
.string
);
244 server_info
->account_name
= talloc_strdup(server_info
, account_name
);
245 NT_STATUS_HAVE_NO_MEMORY(server_info
->account_name
);
248 server_info
->domain_name
= talloc_reference(server_info
, base
->domain
.string
);
249 server_info
->full_name
= talloc_reference(server_info
, base
->full_name
.string
);
250 server_info
->logon_script
= talloc_reference(server_info
, base
->logon_script
.string
);
251 server_info
->profile_path
= talloc_reference(server_info
, base
->profile_path
.string
);
252 server_info
->home_directory
= talloc_reference(server_info
, base
->home_directory
.string
);
253 server_info
->home_drive
= talloc_reference(server_info
, base
->home_drive
.string
);
254 server_info
->logon_server
= talloc_reference(server_info
, base
->logon_server
.string
);
255 server_info
->last_logon
= base
->last_logon
;
256 server_info
->last_logoff
= base
->last_logoff
;
257 server_info
->acct_expiry
= base
->acct_expiry
;
258 server_info
->last_password_change
= base
->last_password_change
;
259 server_info
->allow_password_change
= base
->allow_password_change
;
260 server_info
->force_password_change
= base
->force_password_change
;
261 server_info
->logon_count
= base
->logon_count
;
262 server_info
->bad_password_count
= base
->bad_password_count
;
263 server_info
->acct_flags
= base
->acct_flags
;
265 server_info
->authenticated
= true;
267 /* ensure we are never given NULL session keys */
269 if (all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
270 server_info
->user_session_key
= data_blob(NULL
, 0);
272 server_info
->user_session_key
= data_blob_talloc(server_info
, base
->key
.key
, sizeof(base
->key
.key
));
273 NT_STATUS_HAVE_NO_MEMORY(server_info
->user_session_key
.data
);
276 if (all_zero(base
->LMSessKey
.key
, sizeof(base
->LMSessKey
.key
))) {
277 server_info
->lm_session_key
= data_blob(NULL
, 0);
279 server_info
->lm_session_key
= data_blob_talloc(server_info
, base
->LMSessKey
.key
, sizeof(base
->LMSessKey
.key
));
280 NT_STATUS_HAVE_NO_MEMORY(server_info
->lm_session_key
.data
);
283 ZERO_STRUCT(server_info
->pac_srv_sig
);
284 ZERO_STRUCT(server_info
->pac_kdc_sig
);
286 *_server_info
= server_info
;
291 * Make a server_info struct from the PAC_LOGON_INFO supplied in the krb5 logon
293 NTSTATUS
make_server_info_pac(TALLOC_CTX
*mem_ctx
,
294 struct PAC_LOGON_INFO
*pac_logon_info
,
295 struct auth_serversupplied_info
**_server_info
)
299 union netr_Validation validation
;
300 struct auth_serversupplied_info
*server_info
;
302 validation
.sam3
= &pac_logon_info
->info3
;
304 nt_status
= make_server_info_netlogon_validation(mem_ctx
, "", 3, &validation
, &server_info
);
305 if (!NT_STATUS_IS_OK(nt_status
)) {
309 if (pac_logon_info
->res_groups
.count
> 0) {
310 struct dom_sid
**rgrps
;
311 size_t sidcount
= server_info
->n_domain_groups
+ pac_logon_info
->res_groups
.count
;
312 server_info
->domain_groups
= rgrps
313 = talloc_realloc(server_info
, server_info
->domain_groups
, struct dom_sid
*, sidcount
);
314 NT_STATUS_HAVE_NO_MEMORY(rgrps
);
316 for (i
= 0; pac_logon_info
->res_group_dom_sid
&& i
< pac_logon_info
->res_groups
.count
; i
++) {
317 size_t sid_idx
= server_info
->n_domain_groups
+ i
;
319 = dom_sid_add_rid(rgrps
, pac_logon_info
->res_group_dom_sid
,
320 pac_logon_info
->res_groups
.rids
[i
].rid
);
321 NT_STATUS_HAVE_NO_MEMORY(rgrps
[server_info
->n_domain_groups
+ sid_idx
]);
324 *_server_info
= server_info
;