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 "librpc/gen_ndr/ndr_netlogon.h"
27 #include "auth/auth_sam_reply.h"
29 NTSTATUS
auth_convert_server_info_sambaseinfo(TALLOC_CTX
*mem_ctx
,
30 struct auth_serversupplied_info
*server_info
,
31 struct netr_SamBaseInfo
**_sam
)
33 struct netr_SamBaseInfo
*sam
= talloc_zero(mem_ctx
, struct netr_SamBaseInfo
);
34 NT_STATUS_HAVE_NO_MEMORY(sam
);
36 sam
->domain_sid
= dom_sid_dup(mem_ctx
, server_info
->account_sid
);
37 NT_STATUS_HAVE_NO_MEMORY(sam
->domain_sid
);
38 sam
->domain_sid
->num_auths
--;
40 sam
->last_logon
= server_info
->last_logon
;
41 sam
->last_logoff
= server_info
->last_logoff
;
42 sam
->acct_expiry
= server_info
->acct_expiry
;
43 sam
->last_password_change
= server_info
->last_password_change
;
44 sam
->allow_password_change
= server_info
->allow_password_change
;
45 sam
->force_password_change
= server_info
->force_password_change
;
47 sam
->account_name
.string
= server_info
->account_name
;
48 sam
->full_name
.string
= server_info
->full_name
;
49 sam
->logon_script
.string
= server_info
->logon_script
;
50 sam
->profile_path
.string
= server_info
->profile_path
;
51 sam
->home_directory
.string
= server_info
->home_directory
;
52 sam
->home_drive
.string
= server_info
->home_drive
;
54 sam
->logon_count
= server_info
->logon_count
;
55 sam
->bad_password_count
= sam
->bad_password_count
;
56 sam
->rid
= server_info
->account_sid
->sub_auths
[server_info
->account_sid
->num_auths
-1];
57 sam
->primary_gid
= server_info
->primary_group_sid
->sub_auths
[server_info
->primary_group_sid
->num_auths
-1];
59 sam
->groups
.count
= 0;
60 sam
->groups
.rids
= NULL
;
62 if (server_info
->n_domain_groups
> 0) {
64 sam
->groups
.rids
= talloc_array(sam
, struct samr_RidWithAttribute
,
65 server_info
->n_domain_groups
);
67 if (sam
->groups
.rids
== NULL
)
68 return NT_STATUS_NO_MEMORY
;
70 for (i
=0; i
<server_info
->n_domain_groups
; i
++) {
71 struct dom_sid
*group_sid
= server_info
->domain_groups
[i
];
72 if (!dom_sid_in_domain(sam
->domain_sid
, group_sid
)) {
73 /* We handle this elsewhere */
76 sam
->groups
.rids
[sam
->groups
.count
].rid
=
77 group_sid
->sub_auths
[group_sid
->num_auths
-1];
79 sam
->groups
.rids
[sam
->groups
.count
].attributes
=
80 SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_ENABLED
;
81 sam
->groups
.count
+= 1;
85 sam
->user_flags
= 0; /* w2k3 uses NETLOGON_EXTRA_SIDS | NETLOGON_NTLMV2_ENABLED */
86 sam
->acct_flags
= server_info
->acct_flags
;
87 sam
->logon_server
.string
= server_info
->logon_server
;
88 sam
->domain
.string
= server_info
->domain_name
;
90 ZERO_STRUCT(sam
->unknown
);
92 ZERO_STRUCT(sam
->key
);
93 if (server_info
->user_session_key
.length
== sizeof(sam
->key
.key
)) {
94 memcpy(sam
->key
.key
, server_info
->user_session_key
.data
, sizeof(sam
->key
.key
));
97 ZERO_STRUCT(sam
->LMSessKey
);
98 if (server_info
->lm_session_key
.length
== sizeof(sam
->LMSessKey
.key
)) {
99 memcpy(sam
->LMSessKey
.key
, server_info
->lm_session_key
.data
,
100 sizeof(sam
->LMSessKey
.key
));
108 NTSTATUS
auth_convert_server_info_saminfo3(TALLOC_CTX
*mem_ctx
,
109 struct auth_serversupplied_info
*server_info
,
110 struct netr_SamInfo3
**_sam3
)
112 struct netr_SamBaseInfo
*sam
;
113 struct netr_SamInfo3
*sam3
= talloc_zero(mem_ctx
, struct netr_SamInfo3
);
116 NT_STATUS_HAVE_NO_MEMORY(sam3
);
118 status
= auth_convert_server_info_sambaseinfo(mem_ctx
, server_info
, &sam
);
119 if (!NT_STATUS_IS_OK(status
)) {
127 sam3
->sids
= talloc_array(sam
, struct netr_SidAttr
,
128 server_info
->n_domain_groups
);
129 NT_STATUS_HAVE_NO_MEMORY(sam3
->sids
);
131 for (i
=0; i
<server_info
->n_domain_groups
; i
++) {
132 if (dom_sid_in_domain(sam
->domain_sid
, server_info
->domain_groups
[i
])) {
135 sam3
->sids
[sam3
->sidcount
].sid
= talloc_reference(sam3
->sids
,server_info
->domain_groups
[i
]);
136 sam3
->sids
[sam3
->sidcount
].attributes
=
137 SE_GROUP_MANDATORY
| SE_GROUP_ENABLED_BY_DEFAULT
| SE_GROUP_ENABLED
;
140 if (sam3
->sidcount
) {
141 sam3
->base
.user_flags
|= NETLOGON_EXTRA_SIDS
;
151 * Make a server_info struct from the info3 returned by a domain logon
153 NTSTATUS
make_server_info_netlogon_validation(TALLOC_CTX
*mem_ctx
,
154 const char *account_name
,
155 uint16_t validation_level
,
156 union netr_Validation
*validation
,
157 struct auth_serversupplied_info
**_server_info
)
159 struct auth_serversupplied_info
*server_info
;
160 struct netr_SamBaseInfo
*base
= NULL
;
163 switch (validation_level
) {
165 if (!validation
|| !validation
->sam2
) {
166 return NT_STATUS_INVALID_PARAMETER
;
168 base
= &validation
->sam2
->base
;
171 if (!validation
|| !validation
->sam3
) {
172 return NT_STATUS_INVALID_PARAMETER
;
174 base
= &validation
->sam3
->base
;
177 if (!validation
|| !validation
->sam6
) {
178 return NT_STATUS_INVALID_PARAMETER
;
180 base
= &validation
->sam6
->base
;
183 return NT_STATUS_INVALID_LEVEL
;
186 server_info
= talloc(mem_ctx
, struct auth_serversupplied_info
);
187 NT_STATUS_HAVE_NO_MEMORY(server_info
);
190 Here is where we should check the list of
191 trusted domains, and verify that the SID
194 server_info
->account_sid
= dom_sid_add_rid(server_info
, base
->domain_sid
, base
->rid
);
195 NT_STATUS_HAVE_NO_MEMORY(server_info
->account_sid
);
198 server_info
->primary_group_sid
= dom_sid_add_rid(server_info
, base
->domain_sid
, base
->primary_gid
);
199 NT_STATUS_HAVE_NO_MEMORY(server_info
->primary_group_sid
);
201 server_info
->n_domain_groups
= base
->groups
.count
;
202 if (base
->groups
.count
) {
203 server_info
->domain_groups
= talloc_array(server_info
, struct dom_sid
*, base
->groups
.count
);
204 NT_STATUS_HAVE_NO_MEMORY(server_info
->domain_groups
);
206 server_info
->domain_groups
= NULL
;
209 for (i
= 0; i
< base
->groups
.count
; i
++) {
210 server_info
->domain_groups
[i
] = dom_sid_add_rid(server_info
, base
->domain_sid
, base
->groups
.rids
[i
].rid
);
211 NT_STATUS_HAVE_NO_MEMORY(server_info
->domain_groups
[i
]);
214 /* Copy 'other' sids. We need to do sid filtering here to
215 prevent possible elevation of privileges. See:
217 http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
220 if (validation_level
== 3) {
221 struct dom_sid
**dgrps
= server_info
->domain_groups
;
222 size_t sidcount
= server_info
->n_domain_groups
+ validation
->sam3
->sidcount
;
223 size_t n_dgrps
= server_info
->n_domain_groups
;
225 if (validation
->sam3
->sidcount
> 0) {
226 dgrps
= talloc_realloc(server_info
, dgrps
, struct dom_sid
*, sidcount
);
227 NT_STATUS_HAVE_NO_MEMORY(dgrps
);
229 for (i
= 0; i
< validation
->sam3
->sidcount
; i
++) {
230 dgrps
[n_dgrps
+ i
] = talloc_reference(dgrps
, validation
->sam3
->sids
[i
].sid
);
234 server_info
->n_domain_groups
= sidcount
;
235 server_info
->domain_groups
= dgrps
;
237 /* Where are the 'global' sids?... */
240 if (base
->account_name
.string
) {
241 server_info
->account_name
= talloc_reference(server_info
, base
->account_name
.string
);
243 server_info
->account_name
= talloc_strdup(server_info
, account_name
);
244 NT_STATUS_HAVE_NO_MEMORY(server_info
->account_name
);
247 server_info
->domain_name
= talloc_reference(server_info
, base
->domain
.string
);
248 server_info
->full_name
= talloc_reference(server_info
, base
->full_name
.string
);
249 server_info
->logon_script
= talloc_reference(server_info
, base
->logon_script
.string
);
250 server_info
->profile_path
= talloc_reference(server_info
, base
->profile_path
.string
);
251 server_info
->home_directory
= talloc_reference(server_info
, base
->home_directory
.string
);
252 server_info
->home_drive
= talloc_reference(server_info
, base
->home_drive
.string
);
253 server_info
->logon_server
= talloc_reference(server_info
, base
->logon_server
.string
);
254 server_info
->last_logon
= base
->last_logon
;
255 server_info
->last_logoff
= base
->last_logoff
;
256 server_info
->acct_expiry
= base
->acct_expiry
;
257 server_info
->last_password_change
= base
->last_password_change
;
258 server_info
->allow_password_change
= base
->allow_password_change
;
259 server_info
->force_password_change
= base
->force_password_change
;
260 server_info
->logon_count
= base
->logon_count
;
261 server_info
->bad_password_count
= base
->bad_password_count
;
262 server_info
->acct_flags
= base
->acct_flags
;
264 server_info
->authenticated
= true;
266 /* ensure we are never given NULL session keys */
268 if (all_zero(base
->key
.key
, sizeof(base
->key
.key
))) {
269 server_info
->user_session_key
= data_blob(NULL
, 0);
271 server_info
->user_session_key
= data_blob_talloc(server_info
, base
->key
.key
, sizeof(base
->key
.key
));
272 NT_STATUS_HAVE_NO_MEMORY(server_info
->user_session_key
.data
);
275 if (all_zero(base
->LMSessKey
.key
, sizeof(base
->LMSessKey
.key
))) {
276 server_info
->lm_session_key
= data_blob(NULL
, 0);
278 server_info
->lm_session_key
= data_blob_talloc(server_info
, base
->LMSessKey
.key
, sizeof(base
->LMSessKey
.key
));
279 NT_STATUS_HAVE_NO_MEMORY(server_info
->lm_session_key
.data
);
282 ZERO_STRUCT(server_info
->pac_srv_sig
);
283 ZERO_STRUCT(server_info
->pac_kdc_sig
);
285 *_server_info
= server_info
;