1 | /*
|
---|
2 | * Unix SMB/CIFS implementation.
|
---|
3 | * RPC Pipe client / server routines
|
---|
4 | * Copyright (C) Guenther Deschner 2008.
|
---|
5 | *
|
---|
6 | * This program is free software; you can redistribute it and/or modify
|
---|
7 | * it under the terms of the GNU General Public License as published by
|
---|
8 | * the Free Software Foundation; either version 3 of the License, or
|
---|
9 | * (at your option) any later version.
|
---|
10 | *
|
---|
11 | * This program is distributed in the hope that it will be useful,
|
---|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | * GNU General Public License for more details.
|
---|
15 | *
|
---|
16 | * You should have received a copy of the GNU General Public License
|
---|
17 | * along with this program; if not, see <http://www.gnu.org/licenses/>.
|
---|
18 | */
|
---|
19 |
|
---|
20 | #include "includes.h"
|
---|
21 |
|
---|
22 | /*******************************************************************
|
---|
23 | inits a structure.
|
---|
24 | ********************************************************************/
|
---|
25 |
|
---|
26 | void init_netr_SamBaseInfo(struct netr_SamBaseInfo *r,
|
---|
27 | NTTIME last_logon,
|
---|
28 | NTTIME last_logoff,
|
---|
29 | NTTIME acct_expiry,
|
---|
30 | NTTIME last_password_change,
|
---|
31 | NTTIME allow_password_change,
|
---|
32 | NTTIME force_password_change,
|
---|
33 | const char *account_name,
|
---|
34 | const char *full_name,
|
---|
35 | const char *logon_script,
|
---|
36 | const char *profile_path,
|
---|
37 | const char *home_directory,
|
---|
38 | const char *home_drive,
|
---|
39 | uint16_t logon_count,
|
---|
40 | uint16_t bad_password_count,
|
---|
41 | uint32_t rid,
|
---|
42 | uint32_t primary_gid,
|
---|
43 | struct samr_RidWithAttributeArray groups,
|
---|
44 | uint32_t user_flags,
|
---|
45 | struct netr_UserSessionKey key,
|
---|
46 | const char *logon_server,
|
---|
47 | const char *domain,
|
---|
48 | struct dom_sid2 *domain_sid,
|
---|
49 | struct netr_LMSessionKey LMSessKey,
|
---|
50 | uint32_t acct_flags)
|
---|
51 | {
|
---|
52 | r->last_logon = last_logon;
|
---|
53 | r->last_logoff = last_logoff;
|
---|
54 | r->acct_expiry = acct_expiry;
|
---|
55 | r->last_password_change = last_password_change;
|
---|
56 | r->allow_password_change = allow_password_change;
|
---|
57 | r->force_password_change = force_password_change;
|
---|
58 | init_lsa_String(&r->account_name, account_name);
|
---|
59 | init_lsa_String(&r->full_name, full_name);
|
---|
60 | init_lsa_String(&r->logon_script, logon_script);
|
---|
61 | init_lsa_String(&r->profile_path, profile_path);
|
---|
62 | init_lsa_String(&r->home_directory, home_directory);
|
---|
63 | init_lsa_String(&r->home_drive, home_drive);
|
---|
64 | r->logon_count = logon_count;
|
---|
65 | r->bad_password_count = bad_password_count;
|
---|
66 | r->rid = rid;
|
---|
67 | r->primary_gid = primary_gid;
|
---|
68 | r->groups = groups;
|
---|
69 | r->user_flags = user_flags;
|
---|
70 | r->key = key;
|
---|
71 | init_lsa_StringLarge(&r->logon_server, logon_server);
|
---|
72 | init_lsa_StringLarge(&r->domain, domain);
|
---|
73 | r->domain_sid = domain_sid;
|
---|
74 | r->LMSessKey = LMSessKey;
|
---|
75 | r->acct_flags = acct_flags;
|
---|
76 | }
|
---|
77 |
|
---|
78 | /*******************************************************************
|
---|
79 | inits a structure.
|
---|
80 | ********************************************************************/
|
---|
81 |
|
---|
82 | void init_netr_SamInfo3(struct netr_SamInfo3 *r,
|
---|
83 | NTTIME last_logon,
|
---|
84 | NTTIME last_logoff,
|
---|
85 | NTTIME acct_expiry,
|
---|
86 | NTTIME last_password_change,
|
---|
87 | NTTIME allow_password_change,
|
---|
88 | NTTIME force_password_change,
|
---|
89 | const char *account_name,
|
---|
90 | const char *full_name,
|
---|
91 | const char *logon_script,
|
---|
92 | const char *profile_path,
|
---|
93 | const char *home_directory,
|
---|
94 | const char *home_drive,
|
---|
95 | uint16_t logon_count,
|
---|
96 | uint16_t bad_password_count,
|
---|
97 | uint32_t rid,
|
---|
98 | uint32_t primary_gid,
|
---|
99 | struct samr_RidWithAttributeArray groups,
|
---|
100 | uint32_t user_flags,
|
---|
101 | struct netr_UserSessionKey key,
|
---|
102 | const char *logon_server,
|
---|
103 | const char *domain,
|
---|
104 | struct dom_sid2 *domain_sid,
|
---|
105 | struct netr_LMSessionKey LMSessKey,
|
---|
106 | uint32_t acct_flags,
|
---|
107 | uint32_t sidcount,
|
---|
108 | struct netr_SidAttr *sids)
|
---|
109 | {
|
---|
110 | init_netr_SamBaseInfo(&r->base,
|
---|
111 | last_logon,
|
---|
112 | last_logoff,
|
---|
113 | acct_expiry,
|
---|
114 | last_password_change,
|
---|
115 | allow_password_change,
|
---|
116 | force_password_change,
|
---|
117 | account_name,
|
---|
118 | full_name,
|
---|
119 | logon_script,
|
---|
120 | profile_path,
|
---|
121 | home_directory,
|
---|
122 | home_drive,
|
---|
123 | logon_count,
|
---|
124 | bad_password_count,
|
---|
125 | rid,
|
---|
126 | primary_gid,
|
---|
127 | groups,
|
---|
128 | user_flags,
|
---|
129 | key,
|
---|
130 | logon_server,
|
---|
131 | domain,
|
---|
132 | domain_sid,
|
---|
133 | LMSessKey,
|
---|
134 | acct_flags);
|
---|
135 | r->sidcount = sidcount;
|
---|
136 | r->sids = sids;
|
---|
137 | }
|
---|
138 |
|
---|
139 | /*******************************************************************
|
---|
140 | gets a domain user's groups from their already-calculated NT_USER_TOKEN
|
---|
141 | ********************************************************************/
|
---|
142 |
|
---|
143 | static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx,
|
---|
144 | const DOM_SID *domain_sid,
|
---|
145 | size_t num_sids,
|
---|
146 | const DOM_SID *sids,
|
---|
147 | int *numgroups, DOM_GID **pgids)
|
---|
148 | {
|
---|
149 | int i;
|
---|
150 |
|
---|
151 | *numgroups=0;
|
---|
152 | *pgids = NULL;
|
---|
153 |
|
---|
154 | for (i=0; i<num_sids; i++) {
|
---|
155 | DOM_GID gid;
|
---|
156 | if (!sid_peek_check_rid(domain_sid, &sids[i], &gid.g_rid)) {
|
---|
157 | continue;
|
---|
158 | }
|
---|
159 | gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|
|
---|
160 | SE_GROUP_ENABLED);
|
---|
161 | ADD_TO_ARRAY(mem_ctx, DOM_GID, gid, pgids, numgroups);
|
---|
162 | if (*pgids == NULL) {
|
---|
163 | return NT_STATUS_NO_MEMORY;
|
---|
164 | }
|
---|
165 | }
|
---|
166 | return NT_STATUS_OK;
|
---|
167 | }
|
---|
168 |
|
---|
169 | /****************************************************************************
|
---|
170 | inits a netr_SamInfo3 structure from an auth_serversupplied_info. sam3 must
|
---|
171 | already be initialized and is used as the talloc parent for its members.
|
---|
172 | *****************************************************************************/
|
---|
173 |
|
---|
174 | NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info,
|
---|
175 | uint8_t pipe_session_key[16],
|
---|
176 | struct netr_SamInfo3 *sam3)
|
---|
177 | {
|
---|
178 | struct samu *sampw;
|
---|
179 | DOM_GID *gids = NULL;
|
---|
180 | const DOM_SID *user_sid = NULL;
|
---|
181 | const DOM_SID *group_sid = NULL;
|
---|
182 | DOM_SID domain_sid;
|
---|
183 | uint32 user_rid, group_rid;
|
---|
184 | NTSTATUS status;
|
---|
185 |
|
---|
186 | int num_gids = 0;
|
---|
187 | const char *my_name;
|
---|
188 |
|
---|
189 | struct netr_UserSessionKey user_session_key;
|
---|
190 | struct netr_LMSessionKey lm_session_key;
|
---|
191 |
|
---|
192 | NTTIME last_logon, last_logoff, acct_expiry, last_password_change;
|
---|
193 | NTTIME allow_password_change, force_password_change;
|
---|
194 | struct samr_RidWithAttributeArray groups;
|
---|
195 | int i;
|
---|
196 | struct dom_sid2 *sid = NULL;
|
---|
197 |
|
---|
198 | ZERO_STRUCT(user_session_key);
|
---|
199 | ZERO_STRUCT(lm_session_key);
|
---|
200 |
|
---|
201 | sampw = server_info->sam_account;
|
---|
202 |
|
---|
203 | user_sid = pdb_get_user_sid(sampw);
|
---|
204 | group_sid = pdb_get_group_sid(sampw);
|
---|
205 |
|
---|
206 | if ((user_sid == NULL) || (group_sid == NULL)) {
|
---|
207 | DEBUG(1, ("_netr_LogonSamLogon: User without group or user SID\n"));
|
---|
208 | return NT_STATUS_UNSUCCESSFUL;
|
---|
209 | }
|
---|
210 |
|
---|
211 | sid_copy(&domain_sid, user_sid);
|
---|
212 | sid_split_rid(&domain_sid, &user_rid);
|
---|
213 |
|
---|
214 | sid = sid_dup_talloc(sam3, &domain_sid);
|
---|
215 | if (!sid) {
|
---|
216 | return NT_STATUS_NO_MEMORY;
|
---|
217 | }
|
---|
218 |
|
---|
219 | if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
|
---|
220 | DEBUG(1, ("_netr_LogonSamLogon: user %s\\%s has user sid "
|
---|
221 | "%s\n but group sid %s.\n"
|
---|
222 | "The conflicting domain portions are not "
|
---|
223 | "supported for NETLOGON calls\n",
|
---|
224 | pdb_get_domain(sampw),
|
---|
225 | pdb_get_username(sampw),
|
---|
226 | sid_string_dbg(user_sid),
|
---|
227 | sid_string_dbg(group_sid)));
|
---|
228 | return NT_STATUS_UNSUCCESSFUL;
|
---|
229 | }
|
---|
230 |
|
---|
231 | if(server_info->login_server) {
|
---|
232 | my_name = server_info->login_server;
|
---|
233 | } else {
|
---|
234 | my_name = global_myname();
|
---|
235 | }
|
---|
236 |
|
---|
237 | status = nt_token_to_group_list(sam3, &domain_sid,
|
---|
238 | server_info->num_sids,
|
---|
239 | server_info->sids,
|
---|
240 | &num_gids, &gids);
|
---|
241 |
|
---|
242 | if (!NT_STATUS_IS_OK(status)) {
|
---|
243 | return status;
|
---|
244 | }
|
---|
245 |
|
---|
246 | if (server_info->user_session_key.length) {
|
---|
247 | memcpy(user_session_key.key,
|
---|
248 | server_info->user_session_key.data,
|
---|
249 | MIN(sizeof(user_session_key.key),
|
---|
250 | server_info->user_session_key.length));
|
---|
251 | SamOEMhash(user_session_key.key, pipe_session_key, 16);
|
---|
252 | }
|
---|
253 | if (server_info->lm_session_key.length) {
|
---|
254 | memcpy(lm_session_key.key,
|
---|
255 | server_info->lm_session_key.data,
|
---|
256 | MIN(sizeof(lm_session_key.key),
|
---|
257 | server_info->lm_session_key.length));
|
---|
258 | SamOEMhash(lm_session_key.key, pipe_session_key, 8);
|
---|
259 | }
|
---|
260 |
|
---|
261 | groups.count = num_gids;
|
---|
262 | groups.rids = TALLOC_ARRAY(sam3, struct samr_RidWithAttribute, groups.count);
|
---|
263 | if (!groups.rids) {
|
---|
264 | return NT_STATUS_NO_MEMORY;
|
---|
265 | }
|
---|
266 |
|
---|
267 | for (i=0; i < groups.count; i++) {
|
---|
268 | groups.rids[i].rid = gids[i].g_rid;
|
---|
269 | groups.rids[i].attributes = gids[i].attr;
|
---|
270 | }
|
---|
271 |
|
---|
272 | unix_to_nt_time(&last_logon, pdb_get_logon_time(sampw));
|
---|
273 | unix_to_nt_time(&last_logoff, get_time_t_max());
|
---|
274 | unix_to_nt_time(&acct_expiry, get_time_t_max());
|
---|
275 | unix_to_nt_time(&last_password_change, pdb_get_pass_last_set_time(sampw));
|
---|
276 | unix_to_nt_time(&allow_password_change, pdb_get_pass_can_change_time(sampw));
|
---|
277 | unix_to_nt_time(&force_password_change, pdb_get_pass_must_change_time(sampw));
|
---|
278 |
|
---|
279 | init_netr_SamInfo3(sam3,
|
---|
280 | last_logon,
|
---|
281 | last_logoff,
|
---|
282 | acct_expiry,
|
---|
283 | last_password_change,
|
---|
284 | allow_password_change,
|
---|
285 | force_password_change,
|
---|
286 | talloc_strdup(sam3, pdb_get_username(sampw)),
|
---|
287 | talloc_strdup(sam3, pdb_get_fullname(sampw)),
|
---|
288 | talloc_strdup(sam3, pdb_get_logon_script(sampw)),
|
---|
289 | talloc_strdup(sam3, pdb_get_profile_path(sampw)),
|
---|
290 | talloc_strdup(sam3, pdb_get_homedir(sampw)),
|
---|
291 | talloc_strdup(sam3, pdb_get_dir_drive(sampw)),
|
---|
292 | 0, /* logon_count */
|
---|
293 | 0, /* bad_password_count */
|
---|
294 | user_rid,
|
---|
295 | group_rid,
|
---|
296 | groups,
|
---|
297 | NETLOGON_EXTRA_SIDS,
|
---|
298 | user_session_key,
|
---|
299 | talloc_strdup(sam3, my_name),
|
---|
300 | talloc_strdup(sam3, pdb_get_domain(sampw)),
|
---|
301 | sid,
|
---|
302 | lm_session_key,
|
---|
303 | pdb_get_acct_ctrl(sampw),
|
---|
304 | 0, /* sidcount */
|
---|
305 | NULL); /* struct netr_SidAttr *sids */
|
---|
306 | ZERO_STRUCT(user_session_key);
|
---|
307 | ZERO_STRUCT(lm_session_key);
|
---|
308 |
|
---|
309 | return NT_STATUS_OK;
|
---|
310 | }
|
---|
311 |
|
---|
312 | /*******************************************************************
|
---|
313 | inits a structure.
|
---|
314 | ********************************************************************/
|
---|
315 |
|
---|
316 | void init_netr_IdentityInfo(struct netr_IdentityInfo *r,
|
---|
317 | const char *domain_name,
|
---|
318 | uint32_t parameter_control,
|
---|
319 | uint32_t logon_id_low,
|
---|
320 | uint32_t logon_id_high,
|
---|
321 | const char *account_name,
|
---|
322 | const char *workstation)
|
---|
323 | {
|
---|
324 | init_lsa_String(&r->domain_name, domain_name);
|
---|
325 | r->parameter_control = parameter_control;
|
---|
326 | r->logon_id_low = logon_id_low;
|
---|
327 | r->logon_id_high = logon_id_high;
|
---|
328 | init_lsa_String(&r->account_name, account_name);
|
---|
329 | init_lsa_String(&r->workstation, workstation);
|
---|
330 | }
|
---|
331 |
|
---|
332 | /*******************************************************************
|
---|
333 | inits a structure.
|
---|
334 | This is a network logon packet. The log_id parameters
|
---|
335 | are what an NT server would generate for LUID once the
|
---|
336 | user is logged on. I don't think we care about them.
|
---|
337 |
|
---|
338 | Note that this has no access to the NT and LM hashed passwords,
|
---|
339 | so it forwards the challenge, and the NT and LM responses (24
|
---|
340 | bytes each) over the secure channel to the Domain controller
|
---|
341 | for it to say yea or nay. This is the preferred method of
|
---|
342 | checking for a logon as it doesn't export the password
|
---|
343 | hashes to anyone who has compromised the secure channel. JRA.
|
---|
344 |
|
---|
345 | ********************************************************************/
|
---|
346 |
|
---|
347 | void init_netr_NetworkInfo(struct netr_NetworkInfo *r,
|
---|
348 | const char *domain_name,
|
---|
349 | uint32_t parameter_control,
|
---|
350 | uint32_t logon_id_low,
|
---|
351 | uint32_t logon_id_high,
|
---|
352 | const char *account_name,
|
---|
353 | const char *workstation,
|
---|
354 | uint8_t challenge[8],
|
---|
355 | struct netr_ChallengeResponse nt,
|
---|
356 | struct netr_ChallengeResponse lm)
|
---|
357 | {
|
---|
358 | init_netr_IdentityInfo(&r->identity_info,
|
---|
359 | domain_name,
|
---|
360 | parameter_control,
|
---|
361 | logon_id_low,
|
---|
362 | logon_id_high,
|
---|
363 | account_name,
|
---|
364 | workstation);
|
---|
365 | memcpy(r->challenge, challenge, 8);
|
---|
366 | r->nt = nt;
|
---|
367 | r->lm = lm;
|
---|
368 | }
|
---|
369 |
|
---|
370 | /*******************************************************************
|
---|
371 | inits a structure.
|
---|
372 | ********************************************************************/
|
---|
373 |
|
---|
374 | void init_netr_PasswordInfo(struct netr_PasswordInfo *r,
|
---|
375 | const char *domain_name,
|
---|
376 | uint32_t parameter_control,
|
---|
377 | uint32_t logon_id_low,
|
---|
378 | uint32_t logon_id_high,
|
---|
379 | const char *account_name,
|
---|
380 | const char *workstation,
|
---|
381 | struct samr_Password lmpassword,
|
---|
382 | struct samr_Password ntpassword)
|
---|
383 | {
|
---|
384 | init_netr_IdentityInfo(&r->identity_info,
|
---|
385 | domain_name,
|
---|
386 | parameter_control,
|
---|
387 | logon_id_low,
|
---|
388 | logon_id_high,
|
---|
389 | account_name,
|
---|
390 | workstation);
|
---|
391 | r->lmpassword = lmpassword;
|
---|
392 | r->ntpassword = ntpassword;
|
---|
393 | }
|
---|
394 |
|
---|
395 | /*************************************************************************
|
---|
396 | inits a netr_CryptPassword structure
|
---|
397 | *************************************************************************/
|
---|
398 |
|
---|
399 | void init_netr_CryptPassword(const char *pwd,
|
---|
400 | unsigned char session_key[16],
|
---|
401 | struct netr_CryptPassword *pwd_buf)
|
---|
402 | {
|
---|
403 | struct samr_CryptPassword password_buf;
|
---|
404 |
|
---|
405 | encode_pw_buffer(password_buf.data, pwd, STR_UNICODE);
|
---|
406 |
|
---|
407 | SamOEMhash(password_buf.data, session_key, 516);
|
---|
408 | memcpy(pwd_buf->data, password_buf.data, 512);
|
---|
409 | pwd_buf->length = IVAL(password_buf.data, 512);
|
---|
410 | }
|
---|