2 Unix SMB/Netbios implementation.
4 Pipe SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997,
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
7 Copyright (C) Paul Ashton 1997.
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles reply_ calls on named pipes that the server
25 makes to handle specific protocols
33 extern int DEBUGLEVEL
;
35 extern BOOL sam_logon_in_ssb
;
36 extern pstring samlogon_user
;
40 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL
*r_c
,
41 DOM_CHAL
*srv_chal
, int status
)
43 DEBUG(6,("make_lsa_r_req_chal: %d\n", __LINE__
));
44 memcpy(r_c
->srv_chal
.data
, srv_chal
->data
, sizeof(srv_chal
->data
));
48 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL
*q_c
, char *q
, char *base
,
49 DOM_CHAL
*srv_chal
, uint32 srv_time
)
53 DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__
));
55 /* set up the LSA REQUEST CHALLENGE response */
56 make_lsa_r_req_chal(&r_c
, srv_chal
, srv_time
);
58 /* store the response in the SMB stream */
59 q
= lsa_io_r_req_chal(False
, &r_c
, q
, base
, 4, 0);
61 DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__
));
63 /* return length of SMB data stored */
64 return PTR_DIFF(q
, base
);
67 static void make_lsa_r_auth_2(LSA_R_AUTH_2
*r_a
,
68 DOM_CHAL
*resp_cred
, NEG_FLAGS
*flgs
, int status
)
70 memcpy( r_a
->srv_chal
.data
, resp_cred
->data
, sizeof(resp_cred
->data
));
71 memcpy(&(r_a
->srv_flgs
) , flgs
, sizeof(r_a
->srv_flgs
));
75 static int lsa_reply_auth_2(LSA_Q_AUTH_2
*q_a
, char *q
, char *base
,
76 DOM_CHAL
*resp_cred
, int status
)
80 /* set up the LSA AUTH 2 response */
82 make_lsa_r_auth_2(&r_a
, resp_cred
, &(q_a
->clnt_flgs
), status
);
84 /* store the response in the SMB stream */
85 q
= lsa_io_r_auth_2(False
, &r_a
, q
, base
, 4, 0);
87 /* return length of SMB data stored */
88 return PTR_DIFF(q
, base
);
91 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET
*r_s
,
92 DOM_CRED
*srv_cred
, int status
)
94 DEBUG(5,("make_lsa_r_srv_pwset: %d\n", __LINE__
));
96 memcpy(&(r_s
->srv_cred
), srv_cred
, sizeof(r_s
->srv_cred
));
99 DEBUG(5,("make_lsa_r_srv_pwset: %d\n", __LINE__
));
102 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET
*q_s
, char *q
, char *base
,
103 DOM_CRED
*srv_cred
, int status
)
107 DEBUG(5,("lsa_srv_pwset: %d\n", __LINE__
));
109 /* set up the LSA Server Password Set response */
110 make_lsa_r_srv_pwset(&r_s
, srv_cred
, status
);
112 /* store the response in the SMB stream */
113 q
= lsa_io_r_srv_pwset(False
, &r_s
, q
, base
, 4, 0);
115 DEBUG(5,("lsa_srv_pwset: %d\n", __LINE__
));
117 /* return length of SMB data stored */
118 return PTR_DIFF(q
, base
);
121 static void make_lsa_user_info(LSA_USER_INFO
*usr
,
125 NTTIME
*kickoff_time
,
126 NTTIME
*pass_last_set_time
,
127 NTTIME
*pass_can_change_time
,
128 NTTIME
*pass_must_change_time
,
152 char *other_sids
) /* space-delimited set of SIDs */
154 /* only cope with one "other" sid, right now. */
155 /* need to count the number of space-delimited sids */
157 int num_other_sids
= 0;
159 int len_user_name
= strlen(user_name
);
160 int len_full_name
= strlen(full_name
);
161 int len_logon_script
= strlen(logon_script
);
162 int len_profile_path
= strlen(profile_path
);
163 int len_home_dir
= strlen(home_dir
);
164 int len_dir_drive
= strlen(dir_drive
);
166 int len_logon_srv
= strlen(logon_srv
);
167 int len_logon_dom
= strlen(logon_dom
);
169 usr
->ptr_user_info
= 1; /* yes, we're bothering to put USER_INFO data here */
171 usr
->logon_time
= *logon_time
;
172 usr
->logoff_time
= *logoff_time
;
173 usr
->kickoff_time
= *kickoff_time
;
174 usr
->pass_last_set_time
= *pass_last_set_time
;
175 usr
->pass_can_change_time
= *pass_can_change_time
;
176 usr
->pass_must_change_time
= *pass_must_change_time
;
178 make_uni_hdr(&(usr
->hdr_user_name
), len_user_name
, len_user_name
, 4);
179 make_uni_hdr(&(usr
->hdr_full_name
), len_full_name
, len_full_name
, 4);
180 make_uni_hdr(&(usr
->hdr_logon_script
), len_logon_script
, len_logon_script
, 4);
181 make_uni_hdr(&(usr
->hdr_profile_path
), len_profile_path
, len_profile_path
, 4);
182 make_uni_hdr(&(usr
->hdr_home_dir
), len_home_dir
, len_home_dir
, 4);
183 make_uni_hdr(&(usr
->hdr_dir_drive
), len_dir_drive
, len_dir_drive
, 4);
185 usr
->logon_count
= logon_count
;
186 usr
->bad_pw_count
= bad_pw_count
;
188 usr
->user_id
= user_id
;
189 usr
->group_id
= group_id
;
190 usr
->num_groups
= num_groups
;
191 usr
->buffer_groups
= 1; /* indicates fill in groups, below, even if there are none */
192 usr
->user_flgs
= user_flgs
;
194 if (sess_key
!= NULL
)
196 memcpy(usr
->user_sess_key
, sess_key
, sizeof(usr
->user_sess_key
));
200 bzero(usr
->user_sess_key
, sizeof(usr
->user_sess_key
));
203 make_uni_hdr(&(usr
->hdr_logon_srv
), len_logon_srv
, len_logon_srv
, 4);
204 make_uni_hdr(&(usr
->hdr_logon_dom
), len_logon_dom
, len_logon_dom
, 4);
206 usr
->buffer_dom_id
= dom_sid
? 1 : 0; /* yes, we're bothering to put a domain SID in */
208 bzero(usr
->padding
, sizeof(usr
->padding
));
210 num_other_sids
= make_dom_sids(other_sids
, usr
->other_sids
, LSA_MAX_SIDS
);
212 usr
->num_other_sids
= num_other_sids
;
213 usr
->buffer_other_sids
= num_other_sids
!= 0 ? 1 : 0;
215 make_unistr2(&(usr
->uni_user_name
), user_name
, len_user_name
);
216 make_unistr2(&(usr
->uni_full_name
), full_name
, len_full_name
);
217 make_unistr2(&(usr
->uni_logon_script
), logon_script
, len_logon_script
);
218 make_unistr2(&(usr
->uni_profile_path
), profile_path
, len_profile_path
);
219 make_unistr2(&(usr
->uni_home_dir
), home_dir
, len_home_dir
);
220 make_unistr2(&(usr
->uni_dir_drive
), dir_drive
, len_dir_drive
);
222 usr
->num_groups2
= num_groups
;
223 for (i
= 0; i
< num_groups
; i
++)
225 usr
->gids
[i
] = gids
[i
];
228 make_unistr2(&(usr
->uni_logon_srv
), logon_srv
, len_logon_srv
);
229 make_unistr2(&(usr
->uni_logon_dom
), logon_dom
, len_logon_dom
);
231 make_dom_sid(&(usr
->dom_sid
), dom_sid
);
232 /* "other" sids are set up above */
236 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON
*q_s
, char *q
, char *base
,
237 DOM_CRED
*srv_cred
, LSA_USER_INFO
*user_info
)
241 /* XXXX maybe we want to say 'no', reject the client's credentials */
242 r_s
.buffer_creds
= 1; /* yes, we have valid server credentials */
243 memcpy(&(r_s
.srv_creds
), srv_cred
, sizeof(r_s
.srv_creds
));
245 /* store the user information, if there is any. */
246 r_s
.user
= user_info
;
247 if (user_info
!= NULL
&& user_info
->ptr_user_info
!= 0)
249 r_s
.switch_value
= 3; /* indicates type of validation user info */
254 r_s
.switch_value
= 0; /* don't know what this value is supposed to be */
255 r_s
.status
= 0xC000000|NT_STATUS_NO_SUCH_USER
;
258 r_s
.auth_resp
= 1; /* authoritative response */
260 /* store the response in the SMB stream */
261 q
= lsa_io_r_sam_logon(False
, &r_s
, q
, base
, 4, 0);
263 /* return length of SMB data stored */
264 return PTR_DIFF(q
, base
);
268 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF
*q_s
, char *q
, char *base
,
272 LSA_R_SAM_LOGOFF r_s
;
274 /* XXXX maybe we want to say 'no', reject the client's credentials */
275 r_s
.buffer_creds
= 1; /* yes, we have valid server credentials */
276 memcpy(&(r_s
.srv_creds
), srv_cred
, sizeof(r_s
.srv_creds
));
280 /* store the response in the SMB stream */
281 q
= lsa_io_r_sam_logoff(False
, &r_s
, q
, base
, 4, 0);
283 /* return length of SMB data stored */
284 return PTR_DIFF(q
, base
);
287 /****************************************************************************
288 gets a machine password entry
289 ****************************************************************************/
290 BOOL
get_md4pw(char *md4pw
, char *mach_acct
)
292 struct smb_passwd
*smb_pass
;
295 smb_pass
= get_smbpwnam(mach_acct
);
298 if (smb_pass
!= NULL
)
300 memcpy(md4pw
, smb_pass
->smb_nt_passwd
, 16);
301 dump_data(5, md4pw
, 16);
307 /* No such machine account. Should error out here, but we'll
308 print and carry on */
309 DEBUG(1,("No account in domain for %s\n", mach_acct
));
314 static void api_lsa_req_chal( int cnum
, uint16 vuid
,
316 char *param
, char *data
,
317 char **rdata
, int *rdata_len
)
323 /* grab the challenge... */
324 lsa_io_q_req_chal(True
, &q_r
, data
+ 0x18, data
, 4, 0);
326 fstrcpy(mach_acct
, unistrn2(q_r
.uni_logon_clnt
.buffer
,
327 q_r
.uni_logon_clnt
.uni_str_len
));
329 strcat(mach_acct
, "$");
331 DEBUG(6,("q_r.clnt_chal.data: %lx %lx\n",
332 q_r
.clnt_chal
.data
[0], q_r
.clnt_chal
.data
[1]));
334 if (get_md4pw(vuser
->dc
.md4pw
, mach_acct
))
336 /* copy the client credentials */
337 memcpy(vuser
->dc
.clnt_chal
.data
, q_r
.clnt_chal
.data
, sizeof(q_r
.clnt_chal
.data
));
338 memcpy(vuser
->dc
.clnt_cred
.challenge
.data
, q_r
.clnt_chal
.data
, sizeof(q_r
.clnt_chal
.data
));
340 /* create a server challenge for the client */
341 /* PAXX: set these to random values. */
342 /* lkcl: paul, you mentioned that it doesn't really matter much */
343 vuser
->dc
.srv_chal
.data
[0] = 0x11111111;
344 vuser
->dc
.srv_chal
.data
[1] = 0x11111111;
345 vuser
->dc
.srv_cred
.challenge
.data
[0] = vuser
->dc
.srv_chal
.data
[0];
346 vuser
->dc
.srv_cred
.challenge
.data
[1] = vuser
->dc
.srv_chal
.data
[1];
348 /* from client / server challenges and md4 password, generate sess key */
349 cred_session_key(&(vuser
->dc
.clnt_chal
), &(vuser
->dc
.srv_chal
),
350 vuser
->dc
.md4pw
, vuser
->dc
.sess_key
);
353 /* construct reply. return status is always 0x0 */
354 *rdata_len
= lsa_reply_req_chal(&q_r
, *rdata
+ 0x18, *rdata
,
355 &(vuser
->dc
.srv_chal
), 0);
359 static void api_lsa_auth_2( user_struct
*vuser
,
360 char *param
, char *data
,
361 char **rdata
, int *rdata_len
)
370 /* grab the challenge... */
371 lsa_io_q_auth_2(True
, &q_a
, data
+ 0x18, data
, 4, 0);
373 /* check that the client credentials are valid */
374 cred_assert(&(q_a
.clnt_chal
), vuser
->dc
.sess_key
,
375 &(vuser
->dc
.clnt_cred
.challenge
), srv_time
);
377 /* create server challenge for inclusion in the reply */
378 cred_create(vuser
->dc
.sess_key
, &(vuser
->dc
.srv_cred
.challenge
), srv_time
, &srv_cred
);
380 /* copy the received client credentials for use next time */
381 memcpy(vuser
->dc
.clnt_cred
.challenge
.data
, &(q_a
.clnt_chal
.data
), sizeof(q_a
.clnt_chal
.data
));
382 memcpy(vuser
->dc
.srv_cred
.challenge
.data
, &(q_a
.clnt_chal
.data
), sizeof(q_a
.clnt_chal
.data
));
384 /* construct reply. */
385 *rdata_len
= lsa_reply_auth_2(&q_a
, *rdata
+ 0x18, *rdata
,
390 static void api_lsa_srv_pwset( user_struct
*vuser
,
391 char *param
, char *data
,
392 char **rdata
, int *rdata_len
)
398 /* grab the challenge and encrypted password ... */
399 lsa_io_q_srv_pwset(True
, &q_a
, data
+ 0x18, data
, 4, 0);
401 /* checks and updates credentials. creates reply credentials */
402 deal_with_creds(vuser
->dc
.sess_key
, &(vuser
->dc
.clnt_cred
),
403 &(q_a
.clnt_id
.cred
), &srv_cred
);
404 memcpy(&(vuser
->dc
.srv_cred
), &(vuser
->dc
.clnt_cred
), sizeof(vuser
->dc
.clnt_cred
));
406 DEBUG(5,("api_lsa_srv_pwset: %d\n", __LINE__
));
408 /* construct reply. always indicate failure. nt keeps going... */
409 *rdata_len
= lsa_reply_srv_pwset(&q_a
, *rdata
+ 0x18, *rdata
,
411 NT_STATUS_WRONG_PASSWORD
|0xC0000000);
415 static void api_lsa_sam_logoff( user_struct
*vuser
,
416 char *param
, char *data
,
417 char **rdata
, int *rdata_len
)
419 LSA_Q_SAM_LOGOFF q_l
;
424 /* the DOM_ID_INFO_1 structure is a bit big. plus we might want to
425 dynamically allocate it inside lsa_io_q_sam_logon, at some point */
426 q_l
.sam_id
.auth
.id1
= &id1
;
428 /* grab the challenge... */
429 lsa_io_q_sam_logoff(True
, &q_l
, data
+ 0x18, data
, 4, 0);
431 /* checks and updates credentials. creates reply credentials */
432 deal_with_creds(vuser
->dc
.sess_key
, &(vuser
->dc
.clnt_cred
),
433 &(q_l
.sam_id
.client
.cred
), &srv_cred
);
434 memcpy(&(vuser
->dc
.srv_cred
), &(vuser
->dc
.clnt_cred
), sizeof(vuser
->dc
.clnt_cred
));
436 /* construct reply. always indicate success */
437 *rdata_len
= lsa_reply_sam_logoff(&q_l
, *rdata
+ 0x18, *rdata
,
443 static void api_lsa_sam_logon( user_struct
*vuser
,
444 char *param
, char *data
,
445 char **rdata
, int *rdata_len
)
449 LSA_USER_INFO usr_info
;
453 /* the DOM_ID_INFO_1 structure is a bit big. plus we might want to
454 dynamically allocate it inside lsa_io_q_sam_logon, at some point */
455 q_l
.sam_id
.auth
.id1
= &id1
;
457 lsa_io_q_sam_logon(True
, &q_l
, data
+ 0x18, data
, 4, 0);
459 /* checks and updates credentials. creates reply credentials */
460 deal_with_creds(vuser
->dc
.sess_key
, &(vuser
->dc
.clnt_cred
),
461 &(q_l
.sam_id
.client
.cred
), &srv_cred
);
462 memcpy(&(vuser
->dc
.srv_cred
), &(vuser
->dc
.clnt_cred
), sizeof(vuser
->dc
.clnt_cred
));
464 usr_info
.ptr_user_info
= 0;
468 DOM_GID gids
[LSA_MAX_GROUPS
];
471 pstring logon_script
;
472 pstring profile_path
;
476 pstring my_workgroup
;
477 pstring domain_groups
;
481 extern pstring myname
;
484 UNISTR2
*uni_samlogon_user
= &(q_l
.sam_id
.auth
.id1
->uni_user_name
);
486 dummy_time
.low
= 0xffffffff;
487 dummy_time
.high
= 0x7fffffff;
489 get_myname(myname
, NULL
);
491 pstrcpy(samlogon_user
, unistrn2(uni_samlogon_user
->buffer
,
492 uni_samlogon_user
->uni_str_len
));
494 DEBUG(3,("SAM Logon. Domain:[%s]. User:[%s]\n",
495 lp_workgroup(), samlogon_user
));
497 /* hack to get standard_sub_basic() to use the sam logon username */
498 sam_logon_in_ssb
= True
;
500 pstrcpy(logon_script
, lp_logon_script ());
501 pstrcpy(profile_path
, lp_logon_path ());
502 pstrcpy(dom_sid
, lp_domain_sid ());
503 pstrcpy(other_sids
, lp_domain_other_sids());
504 pstrcpy(my_workgroup
, lp_workgroup ());
506 pstrcpy(home_drive
, lp_logon_drive ());
507 pstrcpy(home_dir
, lp_logon_home ());
509 /* any additional groups this user is in. e.g power users */
510 pstrcpy(domain_groups
, lp_domain_groups());
512 /* can only be a user or a guest. cannot be guest _and_ admin */
513 if (user_in_list(samlogon_user
, lp_domain_guest_users()))
515 sprintf(tmp
, " %ld/7 ", DOMAIN_GROUP_RID_GUESTS
);
516 strcat(domain_groups
, tmp
);
518 DEBUG(3,("domain guest access %s granted\n", tmp
));
522 sprintf(tmp
, " %ld/7 ", DOMAIN_GROUP_RID_USERS
);
523 strcat(domain_groups
, tmp
);
525 DEBUG(3,("domain user access %s granted\n", tmp
));
527 if (user_in_list(samlogon_user
, lp_domain_admin_users()))
529 sprintf(tmp
, " %ld/7 ", DOMAIN_GROUP_RID_ADMINS
);
530 strcat(domain_groups
, tmp
);
532 DEBUG(3,("domain admin access %s granted\n", tmp
));
536 num_gids
= make_dom_gids(domain_groups
, gids
);
538 sam_logon_in_ssb
= False
;
540 pstrcpy(my_name
, myname
);
543 if (name_to_rid(samlogon_user
, &r_uid
, &r_gid
))
545 make_lsa_user_info(&usr_info
,
547 &dummy_time
, /* logon_time */
548 &dummy_time
, /* logoff_time */
549 &dummy_time
, /* kickoff_time */
550 &dummy_time
, /* pass_last_set_time */
551 &dummy_time
, /* pass_can_change_time */
552 &dummy_time
, /* pass_must_change_time */
554 samlogon_user
, /* user_name */
555 vuser
->real_name
, /* full_name */
556 logon_script
, /* logon_script */
557 profile_path
, /* profile_path */
558 home_dir
, /* home_dir */
559 home_drive
, /* dir_drive */
562 0, /* bad_pw_count */
564 r_uid
, /* RID user_id */
565 r_gid
, /* RID group_id */
566 num_gids
, /* uint32 num_groups */
567 gids
, /* DOM_GID *gids */
568 0x20, /* uint32 user_flgs */
570 NULL
, /* char sess_key[16] */
572 my_name
, /* char *logon_srv */
573 my_workgroup
, /* char *logon_dom */
575 dom_sid
, /* char *dom_sid */
576 other_sids
); /* char *other_sids */
580 *rdata_len
= lsa_reply_sam_logon(&q_l
, *rdata
+ 0x18, *rdata
,
581 &srv_cred
, &usr_info
);
585 BOOL
api_netlogrpcTNP(int cnum
,int uid
, char *param
,char *data
,
586 int mdrcnt
,int mprcnt
,
587 char **rdata
,char **rparam
,
588 int *rdata_len
,int *rparam_len
)
596 DEBUG(2,("api_netlogrpcTNP: NULL data received\n"));
600 smb_io_rpc_hdr(True
, &hdr
, data
, data
, 4, 0);
602 if (hdr
.pkt_type
== RPC_BIND
) /* RPC BIND */
604 DEBUG(4,("netlogon rpc bind %x\n",hdr
.pkt_type
));
605 LsarpcTNP1(data
,rdata
,rdata_len
);
609 DEBUG(4,("netlogon TransactNamedPipe op %x\n",hdr
.opnum
));
611 if ((vuser
= get_valid_user_struct(uid
)) == NULL
) return False
;
613 DEBUG(3,("Username of UID %d is %s\n", vuser
->uid
, vuser
->name
));
619 DEBUG(3,("LSA_REQCHAL\n"));
620 api_lsa_req_chal(cnum
, uid
, vuser
, param
, data
, rdata
, rdata_len
);
621 create_rpc_reply(hdr
.call_id
, *rdata
, *rdata_len
);
627 DEBUG(3,("LSA_AUTH2\n"));
628 api_lsa_auth_2(vuser
, param
, data
, rdata
, rdata_len
);
629 create_rpc_reply(hdr
.call_id
, *rdata
, *rdata_len
);
635 DEBUG(3,("LSA_SRVPWSET\n"));
636 api_lsa_srv_pwset(vuser
, param
, data
, rdata
, rdata_len
);
637 create_rpc_reply(hdr
.call_id
, *rdata
, *rdata_len
);
643 DEBUG(3,("LSA_SAMLOGON\n"));
644 api_lsa_sam_logon(vuser
, param
, data
, rdata
, rdata_len
);
645 create_rpc_reply(hdr
.call_id
, *rdata
, *rdata_len
);
651 DEBUG(3,("LSA_SAMLOGOFF\n"));
652 api_lsa_sam_logoff(vuser
, param
, data
, rdata
, rdata_len
);
653 create_rpc_reply(hdr
.call_id
, *rdata
, *rdata_len
);
659 DEBUG(4, ("**** netlogon, unknown code: %lx\n", hdr
.opnum
));
667 #endif /* NTDOMAIN */