2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-1997,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
7 * Copyright (C) Paul Ashton 1997.
8 * Copyright (C) Jeremy Allison 1998-2001.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* This is the implementation of the netlogon pipe. */
29 extern int DEBUGLEVEL
;
31 extern BOOL sam_logon_in_ssb
;
32 extern pstring samlogon_user
;
33 extern pstring global_myname
;
34 extern DOM_SID global_sam_sid
;
36 /*************************************************************************
38 *************************************************************************/
40 static void init_net_r_req_chal(NET_R_REQ_CHAL
*r_c
,
41 DOM_CHAL
*srv_chal
, int status
)
43 DEBUG(6,("init_net_r_req_chal: %d\n", __LINE__
));
44 memcpy(r_c
->srv_chal
.data
, srv_chal
->data
, sizeof(srv_chal
->data
));
48 /*************************************************************************
49 error messages cropping up when using nltest.exe...
50 *************************************************************************/
52 #define ERROR_NO_SUCH_DOMAIN 0x54b
53 #define ERROR_NO_LOGON_SERVERS 0x51f
55 /*************************************************************************
56 net_reply_logon_ctrl2:
57 *************************************************************************/
59 uint32
_net_logon_ctrl2(pipes_struct
*p
, NET_Q_LOGON_CTRL2
*q_u
, NET_R_LOGON_CTRL2
*r_u
)
61 /* lkclXXXX - guess what - absolutely no idea what these are! */
63 uint32 pdc_connection_status
= 0x0;
64 uint32 logon_attempts
= 0x0;
65 uint32 tc_status
= ERROR_NO_LOGON_SERVERS
;
66 char *trusted_domain
= "test_domain";
68 DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__
));
70 /* set up the Logon Control2 response */
71 init_r_logon_ctrl2(r_u
, q_u
->query_level
,
72 flags
, pdc_connection_status
, logon_attempts
,
73 tc_status
, trusted_domain
);
75 DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__
));
80 /*************************************************************************
81 net_reply_trust_dom_list:
82 *************************************************************************/
84 uint32
_net_trust_dom_list(pipes_struct
*p
, NET_Q_TRUST_DOM_LIST
*q_u
, NET_R_TRUST_DOM_LIST
*r_u
)
86 char *trusted_domain
= "test_domain";
87 uint32 num_trust_domains
= 1;
89 DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__
));
91 /* set up the Trusted Domain List response */
92 init_r_trust_dom(r_u
, num_trust_domains
, trusted_domain
);
94 DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__
));
99 /***********************************************************************************
100 init_net_r_srv_pwset:
101 ***********************************************************************************/
103 static void init_net_r_srv_pwset(NET_R_SRV_PWSET
*r_s
,
104 DOM_CRED
*srv_cred
, int status
)
106 DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__
));
108 memcpy(&r_s
->srv_cred
, srv_cred
, sizeof(r_s
->srv_cred
));
109 r_s
->status
= status
;
111 DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__
));
114 /******************************************************************
115 gets a machine password entry. checks access rights of the host.
116 ******************************************************************/
118 static BOOL
get_md4pw(char *md4pw
, char *mach_acct
)
120 struct smb_passwd
*smb_pass
;
124 * Currently this code is redundent as we already have a filter
125 * by hostname list. What this code really needs to do is to
126 * get a hosts allowed/hosts denied list from the SAM database
127 * on a per user basis, and make the access decision there.
128 * I will leave this code here for now as a reminder to implement
129 * this at a later date. JRA.
132 if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
133 client_name(), client_addr()))
135 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct
));
140 /* JRA. This is ok as it is only used for generating the challenge. */
143 smb_pass
= getsmbpwnam(mach_acct
);
146 if ((smb_pass
) != NULL
&& !(smb_pass
->acct_ctrl
& ACB_DISABLED
) &&
147 (smb_pass
->smb_nt_passwd
!= NULL
))
149 memcpy(md4pw
, smb_pass
->smb_nt_passwd
, 16);
150 dump_data(5, md4pw
, 16);
154 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct
));
158 /*************************************************************************
160 *************************************************************************/
162 uint32
_net_req_chal(pipes_struct
*p
, NET_Q_REQ_CHAL
*q_u
, NET_R_REQ_CHAL
*r_u
)
164 uint32 status
= NT_STATUS_NOPROBLEMO
;
167 if (!get_valid_user_struct(p
->vuid
))
168 return NT_STATUS_NO_SUCH_USER
;
170 fstrcpy(mach_acct
, dos_unistrn2(q_u
->uni_logon_clnt
.buffer
,
171 q_u
->uni_logon_clnt
.uni_str_len
));
174 fstrcat(mach_acct
, "$");
176 if (get_md4pw((char *)p
->dc
.md4pw
, mach_acct
)) {
177 /* copy the client credentials */
178 memcpy(p
->dc
.clnt_chal
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
179 memcpy(p
->dc
.clnt_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
181 /* create a server challenge for the client */
182 /* Set these to random values. */
183 generate_random_buffer(p
->dc
.srv_chal
.data
, 8, False
);
185 memcpy(p
->dc
.srv_cred
.challenge
.data
, p
->dc
.srv_chal
.data
, 8);
187 memset((char *)p
->dc
.sess_key
, '\0', sizeof(p
->dc
.sess_key
));
189 /* from client / server challenges and md4 password, generate sess key */
190 cred_session_key(&p
->dc
.clnt_chal
, &p
->dc
.srv_chal
,
191 (char *)p
->dc
.md4pw
, p
->dc
.sess_key
);
193 /* Save the machine account name. */
194 fstrcpy(p
->dc
.mach_acct
, mach_acct
);
197 /* lkclXXXX take a guess at a good error message to return :-) */
198 status
= NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
;
201 /* set up the LSA REQUEST CHALLENGE response */
202 init_net_r_req_chal(r_u
, &p
->dc
.srv_chal
, status
);
207 /*************************************************************************
209 *************************************************************************/
211 static void init_net_r_auth(NET_R_AUTH
*r_a
, DOM_CHAL
*resp_cred
, int status
)
213 memcpy(r_a
->srv_chal
.data
, resp_cred
->data
, sizeof(resp_cred
->data
));
214 r_a
->status
= status
;
217 /*************************************************************************
219 *************************************************************************/
221 uint32
_net_auth(pipes_struct
*p
, NET_Q_AUTH
*q_u
, NET_R_AUTH
*r_u
)
223 uint32 status
= NT_STATUS_NOPROBLEMO
;
227 if (!get_valid_user_struct(p
->vuid
))
228 return NT_STATUS_NO_SUCH_USER
;
232 /* check that the client credentials are valid */
233 if (cred_assert(&q_u
->clnt_chal
, p
->dc
.sess_key
, &p
->dc
.clnt_cred
.challenge
, srv_time
)) {
235 /* create server challenge for inclusion in the reply */
236 cred_create(p
->dc
.sess_key
, &p
->dc
.srv_cred
.challenge
, srv_time
, &srv_cred
);
238 /* copy the received client credentials for use next time */
239 memcpy(p
->dc
.clnt_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
240 memcpy(p
->dc
.srv_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
242 status
= NT_STATUS_ACCESS_DENIED
;
245 /* set up the LSA AUTH 2 response */
246 init_net_r_auth(r_u
, &srv_cred
, status
);
251 /*************************************************************************
253 *************************************************************************/
255 static void init_net_r_auth_2(NET_R_AUTH_2
*r_a
,
256 DOM_CHAL
*resp_cred
, NEG_FLAGS
*flgs
, int status
)
258 memcpy(r_a
->srv_chal
.data
, resp_cred
->data
, sizeof(resp_cred
->data
));
259 memcpy(&r_a
->srv_flgs
, flgs
, sizeof(r_a
->srv_flgs
));
260 r_a
->status
= status
;
263 /*************************************************************************
265 *************************************************************************/
267 uint32
_net_auth_2(pipes_struct
*p
, NET_Q_AUTH_2
*q_u
, NET_R_AUTH_2
*r_u
)
269 uint32 status
= NT_STATUS_NOPROBLEMO
;
274 if (!get_valid_user_struct(p
->vuid
))
275 return NT_STATUS_NO_SUCH_USER
;
279 /* check that the client credentials are valid */
280 if (cred_assert(&q_u
->clnt_chal
, p
->dc
.sess_key
, &p
->dc
.clnt_cred
.challenge
, srv_time
)) {
282 /* create server challenge for inclusion in the reply */
283 cred_create(p
->dc
.sess_key
, &p
->dc
.srv_cred
.challenge
, srv_time
, &srv_cred
);
285 /* copy the received client credentials for use next time */
286 memcpy(p
->dc
.clnt_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
287 memcpy(p
->dc
.srv_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
289 status
= NT_STATUS_ACCESS_DENIED
;
292 srv_flgs
.neg_flags
= 0x000001ff;
294 /* set up the LSA AUTH 2 response */
295 init_net_r_auth_2(r_u
, &srv_cred
, &srv_flgs
, status
);
300 /*************************************************************************
302 *************************************************************************/
304 uint32
_net_srv_pwset(pipes_struct
*p
, NET_Q_SRV_PWSET
*q_u
, NET_R_SRV_PWSET
*r_u
)
306 uint32 status
= NT_STATUS_NOPROBLEMO
;
309 struct smb_passwd
*smb_pass
;
311 unsigned char pwd
[16];
314 if (!get_valid_user_struct(p
->vuid
))
315 return NT_STATUS_NO_SUCH_USER
;
317 /* checks and updates credentials. creates reply credentials */
318 if (!deal_with_creds(p
->dc
.sess_key
, &p
->dc
.clnt_cred
, &q_u
->clnt_id
.cred
, &srv_cred
))
319 return NT_STATUS_INVALID_HANDLE
;
321 memcpy(&p
->dc
.srv_cred
, &p
->dc
.clnt_cred
, sizeof(p
->dc
.clnt_cred
));
323 DEBUG(5,("_net_srv_pwset: %d\n", __LINE__
));
325 pstrcpy(mach_acct
, dos_unistrn2(q_u
->clnt_id
.login
.uni_acct_name
.buffer
,
326 q_u
->clnt_id
.login
.uni_acct_name
.uni_str_len
));
329 * Check the machine account name we're changing is the same
330 * as the one we've authenticated from. This prevents arbitrary
331 * machines changing other machine account passwords.
334 if (!strequal(mach_acct
, p
->dc
.mach_acct
))
335 return NT_STATUS_ACCESS_DENIED
;
337 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct
));
340 smb_pass
= getsmbpwnam(mach_acct
);
343 /* Ensure the account exists and is a machine account. */
344 if (smb_pass
== NULL
|| !(smb_pass
->acct_ctrl
& ACB_WSTRUST
))
345 return NT_STATUS_NO_SUCH_USER
;
347 DEBUG(100,("Server password set : new given value was :\n"));
348 for(i
= 0; i
< 16; i
++)
349 DEBUG(100,("%02X ", q_u
->pwd
[i
]));
352 cred_hash3( pwd
, q_u
->pwd
, p
->dc
.sess_key
, 0);
354 /* lies! nt and lm passwords are _not_ the same: don't care */
355 smb_pass
->smb_passwd
= pwd
;
356 smb_pass
->smb_nt_passwd
= pwd
;
357 smb_pass
->acct_ctrl
= ACB_WSTRUST
;
360 ret
= mod_smbpwd_entry(smb_pass
,False
);
364 status
= NT_STATUS_WRONG_PASSWORD
;
366 /* set up the LSA Server Password Set response */
367 init_net_r_srv_pwset(r_u
, &srv_cred
, status
);
373 /*************************************************************************
375 *************************************************************************/
377 uint32
_net_sam_logoff(pipes_struct
*p
, NET_Q_SAM_LOGOFF
*q_u
, NET_R_SAM_LOGOFF
*r_u
)
381 if (!get_valid_user_struct(p
->vuid
))
382 return NT_STATUS_NO_SUCH_USER
;
384 /* checks and updates credentials. creates reply credentials */
385 if (!deal_with_creds(p
->dc
.sess_key
, &p
->dc
.clnt_cred
,
386 &q_u
->sam_id
.client
.cred
, &srv_cred
))
387 return NT_STATUS_INVALID_HANDLE
;
389 memcpy(&p
->dc
.srv_cred
, &p
->dc
.clnt_cred
, sizeof(p
->dc
.clnt_cred
));
391 /* XXXX maybe we want to say 'no', reject the client's credentials */
392 r_u
->buffer_creds
= 1; /* yes, we have valid server credentials */
393 memcpy(&r_u
->srv_creds
, &srv_cred
, sizeof(r_u
->srv_creds
));
395 r_u
->status
= NT_STATUS_NOPROBLEMO
;
400 /*************************************************************************
401 net_login_interactive:
402 *************************************************************************/
404 static uint32
net_login_interactive(NET_ID_INFO_1
*id1
, struct smb_passwd
*smb_pass
, pipes_struct
*p
)
410 unsigned char key
[16];
413 memcpy(key
, p
->dc
.sess_key
, 8);
415 memcpy(lm_pwd
, id1
->lm_owf
.data
, 16);
416 memcpy(nt_pwd
, id1
->nt_owf
.data
, 16);
418 #ifdef DEBUG_PASSWORD
420 dump_data(100, (char *)key
, 16);
422 DEBUG(100,("lm owf password:"));
423 dump_data(100, lm_pwd
, 16);
425 DEBUG(100,("nt owf password:"));
426 dump_data(100, nt_pwd
, 16);
429 SamOEMhash((uchar
*)lm_pwd
, key
, False
);
430 SamOEMhash((uchar
*)nt_pwd
, key
, False
);
432 #ifdef DEBUG_PASSWORD
433 DEBUG(100,("decrypt of lm owf password:"));
434 dump_data(100, lm_pwd
, 16);
436 DEBUG(100,("decrypt of nt owf password:"));
437 dump_data(100, nt_pwd
, 16);
440 if (memcmp(smb_pass
->smb_passwd
, lm_pwd
, 16) != 0 ||
441 memcmp(smb_pass
->smb_nt_passwd
, nt_pwd
, 16) != 0)
443 status
= NT_STATUS_WRONG_PASSWORD
;
449 /*************************************************************************
451 *************************************************************************/
453 static uint32
net_login_network(NET_ID_INFO_2
*id2
, struct smb_passwd
*smb_pass
)
455 DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
456 id2
->hdr_lm_chal_resp
.str_str_len
,
457 id2
->hdr_nt_chal_resp
.str_str_len
));
459 /* JRA. Check the NT password first if it exists - this is a higher quality
460 password, if it exists and it doesn't match - fail. */
462 if (id2
->hdr_nt_chal_resp
.str_str_len
== 24 &&
463 smb_pass
->smb_nt_passwd
!= NULL
)
465 if(smb_password_check((char *)id2
->nt_chal_resp
.buffer
,
466 smb_pass
->smb_nt_passwd
,
468 return NT_STATUS_NO_PROBLEMO
;
470 return NT_STATUS_WRONG_PASSWORD
;
473 /* lkclXXXX this is not a good place to put disabling of LM hashes in.
474 if that is to be done, first move this entire function into a
475 library routine that calls the two smb_password_check() functions.
476 if disabling LM hashes (which nt can do for security reasons) then
477 an attempt should be made to disable them everywhere (which nt does
478 not do, for various security-hole reasons).
481 if (lp_lanman_auth() &&
482 id2
->hdr_lm_chal_resp
.str_str_len
== 24 &&
483 smb_password_check((char *)id2
->lm_chal_resp
.buffer
,
484 smb_pass
->smb_passwd
,
487 return NT_STATUS_NO_PROBLEMO
;
491 /* oops! neither password check succeeded */
493 return NT_STATUS_WRONG_PASSWORD
;
496 /*************************************************************************
498 *************************************************************************/
500 uint32
_net_sam_logon(pipes_struct
*p
, NET_Q_SAM_LOGON
*q_u
, NET_R_SAM_LOGON
*r_u
)
502 uint32 status
= NT_STATUS_NOPROBLEMO
;
503 NET_USER_INFO_3
*usr_info
= NULL
;
505 struct smb_passwd
*smb_pass
= NULL
;
506 struct sam_passwd
*sam_pass
= NULL
;
507 UNISTR2
*uni_samlogon_user
= NULL
;
510 usr_info
= (NET_USER_INFO_3
*)talloc(p
->mem_ctx
, sizeof(NET_USER_INFO_3
));
512 return NT_STATUS_NO_MEMORY
;
513 ZERO_STRUCTP(usr_info
);
515 if (!get_valid_user_struct(p
->vuid
))
516 return NT_STATUS_NO_SUCH_USER
;
518 /* checks and updates credentials. creates reply credentials */
519 if (!deal_with_creds(p
->dc
.sess_key
, &p
->dc
.clnt_cred
, &q_u
->sam_id
.client
.cred
, &srv_cred
))
520 return NT_STATUS_INVALID_HANDLE
;
522 memcpy(&p
->dc
.srv_cred
, &p
->dc
.clnt_cred
, sizeof(p
->dc
.clnt_cred
));
524 r_u
->buffer_creds
= 1; /* yes, we have valid server credentials */
525 memcpy(&r_u
->srv_creds
, &srv_cred
, sizeof(r_u
->srv_creds
));
527 /* store the user information, if there is any. */
528 r_u
->user
= usr_info
;
529 r_u
->switch_value
= 0; /* indicates no info */
530 r_u
->auth_resp
= 1; /* authoritative response */
531 r_u
->switch_value
= 3; /* indicates type of validation user info */
533 /* find the username */
535 switch (q_u
->sam_id
.logon_level
) {
536 case INTERACTIVE_LOGON_TYPE
:
537 uni_samlogon_user
= &q_u
->sam_id
.ctr
->auth
.id1
.uni_user_name
;
539 DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup()));
542 uni_samlogon_user
= &q_u
->sam_id
.ctr
->auth
.id2
.uni_user_name
;
544 DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup()));
547 DEBUG(2,("SAM Logon: unsupported switch value\n"));
548 return NT_STATUS_INVALID_INFO_CLASS
;
551 /* check username exists */
553 pstrcpy(nt_username
, dos_unistrn2(uni_samlogon_user
->buffer
, uni_samlogon_user
->uni_str_len
));
555 DEBUG(3,("User:[%s]\n", nt_username
));
558 * Convert to a UNIX username.
561 map_username(nt_username
);
564 * We previously called Get_Pwnam(ntusername, True) here which could
565 * have modified the case of the username. Beaware of this
566 * is the username case in smbpasswd does not match that in /etc/passwd
567 * and domain logons begin to fail. -- jerry
570 /* XXXX hack to get standard_sub_basic() to use sam logon username */
571 /* possibly a better way would be to do a become_user() call */
572 sam_logon_in_ssb
= True
;
573 pstrcpy(samlogon_user
, nt_username
);
576 sam_pass
= getsam21pwnam(nt_username
);
578 smb_pass
= pdb_sam_to_smb(sam_pass
);
580 sam_logon_in_ssb
= False
;
582 if ((smb_pass
=pdb_sam_to_smb(sam_pass
)) == NULL
)
583 return NT_STATUS_NO_SUCH_USER
;
584 else if (smb_pass
->acct_ctrl
& ACB_DISABLED
)
585 return NT_STATUS_ACCOUNT_DISABLED
;
587 /* Validate password - if required. */
589 if (smb_pass
->acct_ctrl
& ACB_PWNOTREQ
) {
590 if (!lp_null_passwords()) {
591 DEBUG(3,("Account for user %s has a null password and null passwords are NOT allowed",nt_username
));
592 return NT_STATUS_ACCOUNT_DISABLED
;
598 status
= smb_pam_accountcheck(nt_username
);
600 if (status
!= NT_STATUS_NOPROBLEMO
)
604 if (!(smb_pass
->acct_ctrl
& ACB_PWNOTREQ
)) {
605 switch (q_u
->sam_id
.logon_level
) {
606 case INTERACTIVE_LOGON_TYPE
:
607 /* interactive login. */
608 status
= net_login_interactive(&q_u
->sam_id
.ctr
->auth
.id1
, smb_pass
, p
);
611 /* network login. lm challenge and 24 byte responses */
612 status
= net_login_network(&q_u
->sam_id
.ctr
->auth
.id2
, smb_pass
);
617 if (status
!= NT_STATUS_NOPROBLEMO
)
620 /* lkclXXXX this is the point at which, if the login was
621 successful, that the SAM Local Security Authority should
622 record that the user is logged in to the domain.
625 /* return the profile plus other bits :-) */
628 DOM_GID
*gids
= NULL
;
632 pstring my_workgroup
;
633 pstring domain_groups
;
637 /* set up pointer indicating user/password failed to be found */
638 usr_info
->ptr_user_info
= 0;
640 dummy_time
.low
= 0xffffffff;
641 dummy_time
.high
= 0x7fffffff;
643 pstrcpy(my_workgroup
, lp_workgroup());
645 pstrcpy(my_name
, global_myname
);
649 * This is the point at which we get the group
650 * database - we should be getting the gid_t list
651 * from /etc/group and then turning the uids into
652 * rids and then into machine sids for this user.
656 get_domain_user_groups(domain_groups
, nt_username
);
659 * make_dom_gids allocates the gids array. JRA.
662 num_gids
= make_dom_gids(p
->mem_ctx
, domain_groups
, &gids
);
664 if (pdb_name_to_rid(nt_username
, &r_uid
, &r_gid
))
666 init_net_user_info3(p
->mem_ctx
, usr_info
,
667 &dummy_time
, /* logon_time */
668 &dummy_time
, /* logoff_time */
669 &dummy_time
, /* kickoff_time */
670 &dummy_time
, /* pass_last_set_time */
671 &dummy_time
, /* pass_can_change_time */
672 &dummy_time
, /* pass_must_change_time */
674 nt_username
, /* user_name */
675 sam_pass
->full_name
, /* full_name */
676 sam_pass
->logon_script
, /* logon_script */
677 sam_pass
->profile_path
, /* profile_path */
678 sam_pass
->home_dir
, /* home_dir */
679 sam_pass
->dir_drive
, /* dir_drive */
682 0, /* bad_pw_count */
684 r_uid
, /* RID user_id */
685 r_gid
, /* RID group_id */
686 num_gids
, /* uint32 num_groups */
687 gids
, /* DOM_GID *gids */
688 0x20 , /* uint32 user_flgs (?) */
690 NULL
, /* char sess_key[16] */
692 my_name
, /* char *logon_srv */
693 my_workgroup
, /* char *logon_dom */
695 &global_sam_sid
, /* DOM_SID *dom_sid */
696 NULL
); /* char *other_sids */
700 return NT_STATUS_NO_SUCH_USER
;