2 Unix SMB/Netbios implementation.
4 Pipe SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1997,
7 Luke Kenneth Casson Leighton 1996-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 #define PIPE "\\PIPE\\"
34 #define PIPELEN strlen(PIPE)
36 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
38 /* look in server.c for some explanation of these variables */
40 extern int DEBUGLEVEL;
41 extern int chain_fnum;
42 extern char magic_char;
43 extern connection_struct Connections[];
44 extern files_struct Files[];
45 extern BOOL case_sensitive;
46 extern pstring sesssetup_user;
48 extern fstring myworkgroup;
50 /* this macro should always be used to extract an fnum (smb_fid) from
51 a packet to ensure chaining works correctly */
52 #define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
54 char * known_pipes [] =
63 /****************************************************************************
64 reply to an open and X on a named pipe
66 In fact what we do is to open a regular file with the same name in
67 /tmp. This can then be closed as normal. Reading and writing won't
68 make much sense, but will do *something*. The real reason for this
69 support is to be able to do transactions on them (well, on lsarpc
70 for domain login purposes...).
72 This code is basically stolen from reply_open_and_X with some
73 wrinkles to handle pipes.
74 ****************************************************************************/
75 int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
78 int cnum = SVAL(inbuf,smb_tid);
80 int smb_mode = SVAL(inbuf,smb_vwv3);
81 int smb_attr = SVAL(inbuf,smb_vwv5);
83 int open_flags = SVAL(inbuf,smb_vwv2);
84 int smb_sattr = SVAL(inbuf,smb_vwv4);
85 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
87 int smb_ofun = SVAL(inbuf,smb_vwv8);
89 int size=0,fmode=0,mtime=0,rmode=0;
93 BOOL bad_path = False;
95 /* XXXX we need to handle passed times, sattr and flags */
96 pstrcpy(fname,smb_buf(inbuf));
98 /* If the name doesn't start \PIPE\ then this is directed */
99 /* at a mailslot or something we really, really don't understand, */
100 /* not just something we really don't understand. */
101 if ( strncmp(fname,PIPE,PIPELEN) != 0 )
102 return(ERROR(ERRSRV,ERRaccess));
104 DEBUG(4,("Opening pipe %s.\n", fname));
106 /* Strip \PIPE\ off the name. */
107 pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
109 /* See if it is one we want to handle. */
110 for( i = 0; known_pipes[i] ; i++ )
111 if( strcmp(fname,known_pipes[i]) == 0 )
114 if ( known_pipes[i] == NULL )
115 return(ERROR(ERRSRV,ERRaccess));
117 /* Known pipes arrive with DIR attribs. Remove it so a regular file */
118 /* can be opened and add it in after the open. */
119 DEBUG(3,("Known pipe %s opening.\n",fname));
121 Connections[cnum].read_only = 0;
122 smb_ofun |= 0x10; /* Add Create it not exists flag */
124 unix_convert(fname,cnum,0,&bad_path);
126 fnum = find_free_file();
128 return(ERROR(ERRSRV,ERRnofids));
130 if (!check_name(fname,cnum))
131 return(UNIXERROR(ERRDOS,ERRnoaccess));
133 unixmode = unix_mode(cnum,smb_attr);
135 open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
136 0, &rmode,&smb_action);
138 if (!Files[fnum].open)
140 /* Change the error code if bad_path was set. */
141 if((errno == ENOENT) && bad_path)
143 unix_ERR_class = ERRDOS;
144 unix_ERR_code = ERRbadpath;
146 return(UNIXERROR(ERRDOS,ERRnoaccess));
149 if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
151 return(ERROR(ERRDOS,ERRnoaccess));
155 fmode = dos_mode(cnum,fname,&sbuf);
156 mtime = sbuf.st_mtime;
159 return(ERROR(ERRDOS,ERRnoaccess));
162 /* Prepare the reply */
163 set_message(outbuf,15,0,True);
165 /* Put things back the way they were. */
166 Connections[cnum].read_only = 1;
168 /* Mark the opened file as an existing named pipe in message mode. */
169 SSVAL(outbuf,smb_vwv9,2);
170 SSVAL(outbuf,smb_vwv10,0xc700);
173 DEBUG(4,("Resetting open result to open from create.\n"));
177 SSVAL(outbuf,smb_vwv2,fnum);
178 SSVAL(outbuf,smb_vwv3,fmode);
179 put_dos_date3(outbuf,smb_vwv4,mtime);
180 SIVAL(outbuf,smb_vwv6,size);
181 SSVAL(outbuf,smb_vwv8,rmode);
182 SSVAL(outbuf,smb_vwv11,smb_action);
186 DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
187 fname, fnum, Files[fnum].name));
189 return chain_reply(inbuf,outbuf,length,bufsize);
193 /****************************************************************************
196 SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
197 so just blithely return True. This is really only for NT domain stuff,
198 we we're only handling that - don't assume Samba now does complete
200 ****************************************************************************/
201 BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
202 int mdrcnt,int mprcnt,
203 char **rdata,char **rparam,
204 int *rdata_len,int *rparam_len)
208 id = param[0] + (param[1] << 8);
209 DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
214 /****************************************************************************
217 TransactNamedPipe on \PIPE\lsarpc.
218 ****************************************************************************/
219 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
221 uint32 dword1, dword2;
222 char pname[] = "\\PIPE\\lsass";
224 /* All kinds of mysterious numbers here */
226 *rdata = REALLOC(*rdata,*rdata_len);
228 dword1 = IVAL(data,0xC);
229 dword2 = IVAL(data,0x10);
231 SIVAL(*rdata,0,0xc0005);
232 SIVAL(*rdata,4,0x10);
233 SIVAL(*rdata,8,0x44);
234 SIVAL(*rdata,0xC,dword1);
236 SIVAL(*rdata,0x10,dword2);
237 SIVAL(*rdata,0x14,0x15);
238 SSVAL(*rdata,0x18,sizeof(pname));
239 strcpy(*rdata + 0x1a,pname);
240 SIVAL(*rdata,0x28,1);
241 memcpy(*rdata + 0x30, data + 0x34, 0x14);
244 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
248 /* All kinds of mysterious numbers here */
250 *rdata = REALLOC(*rdata,*rdata_len);
252 dword1 = IVAL(data,0xC);
254 SIVAL(*rdata,0,0x03020005);
255 SIVAL(*rdata,4,0x10);
256 SIVAL(*rdata,8,0x30);
257 SIVAL(*rdata,0xC,dword1);
258 SIVAL(*rdata,0x10,0x18);
259 SIVAL(*rdata,0x1c,0x44332211);
260 SIVAL(*rdata,0x20,0x88776655);
261 SIVAL(*rdata,0x24,0xCCBBAA99);
262 SIVAL(*rdata,0x28,0x11FFEEDD);
265 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
269 char * workgroup = myworkgroup;
270 int wglen = strlen(workgroup);
273 /* All kinds of mysterious numbers here */
274 *rdata_len = 90 + 2 * wglen;
275 *rdata = REALLOC(*rdata,*rdata_len);
277 dword1 = IVAL(data,0xC);
278 word1 = SVAL(data,0x2C);
280 SIVAL(*rdata,0,0x03020005);
281 SIVAL(*rdata,4,0x10);
282 SIVAL(*rdata,8,0x60);
283 SIVAL(*rdata,0xC,dword1);
284 SIVAL(*rdata,0x10,0x48);
285 SSVAL(*rdata,0x18,0x5988); /* This changes */
286 SSVAL(*rdata,0x1A,0x15);
287 SSVAL(*rdata,0x1C,word1);
288 SSVAL(*rdata,0x20,6);
289 SSVAL(*rdata,0x22,8);
290 SSVAL(*rdata,0x24,0x8E8); /* So does this */
291 SSVAL(*rdata,0x26,0x15);
292 SSVAL(*rdata,0x28,0x4D48); /* And this */
293 SSVAL(*rdata,0x2A,0x15);
294 SIVAL(*rdata,0x2C,4);
295 SIVAL(*rdata,0x34,wglen);
296 for ( i = 0 ; i < wglen ; i++ )
297 (*rdata)[0x38 + i * 2] = workgroup[i];
299 /* Now fill in the rest */
300 i = 0x38 + wglen * 2;
301 SSVAL(*rdata,i,0x648);
303 SIVAL(*rdata,i+6,0x401);
304 SSVAL(*rdata,i+0xC,0x500);
305 SIVAL(*rdata,i+0xE,0x15);
306 SIVAL(*rdata,i+0x12,0x2372FE1);
307 SIVAL(*rdata,i+0x16,0x7E831BEF);
308 SIVAL(*rdata,i+0x1A,0x4B454B2);
311 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
315 /* All kinds of mysterious numbers here */
317 *rdata = REALLOC(*rdata,*rdata_len);
319 dword1 = IVAL(data,0xC);
321 SIVAL(*rdata,0,0x03020005);
322 SIVAL(*rdata,4,0x10);
323 SIVAL(*rdata,8,0x30);
324 SIVAL(*rdata,0xC,dword1);
325 SIVAL(*rdata,0x10,0x18);
329 BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
330 int mdrcnt,int mprcnt,
331 char **rdata,char **rparam,
332 int *rdata_len,int *rparam_len)
338 DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
342 LsarpcTNP1(data,rdata,rdata_len);
347 DEBUG(4,("\t- Suboperation %lx\n",id2));
351 LsarpcTNP2(data,rdata,rdata_len);
355 LsarpcTNP4(data,rdata,rdata_len);
359 LsarpcTNP3(data,rdata,rdata_len);
367 #ifdef UNDEFINED_NTDOMAIN
369 PAXX: Someone fix above.
370 The above API is indexing RPC calls based on RPC flags and
371 fragment length. I've decided to do it based on operation number :-)
374 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
375 char *dom_sid_to_string(DOM_SID *sid)
377 static pstring sidstr;
380 uint32 ia = (sid->id_auth[0]) +
381 (sid->id_auth[1] << 8 ) +
382 (sid->id_auth[2] << 16) +
383 (sid->id_auth[3] << 24);
385 sprintf(sidstr, "S-%d-%d", sid->sid_no, ia);
387 for (i = 0; i < sid->num_auths; i++)
389 sprintf(subauth, "-%d", sid->sub_auths[i]);
390 strcat(sidstr, subauth);
393 DEBUG(5,("dom_sid_to_string returning %s\n", sidstr));
397 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
398 /* identauth >= 2^32 can be detected because it will be specified in hex */
399 static void make_dom_sid(DOM_SID *sid, char *domsid)
404 DEBUG(4,("netlogon domain SID: %s\n", domsid));
406 /* assume, but should check, that domsid starts "S-" */
407 p = strtok(domsid+2,"-");
408 sid->sid_no = atoi(p);
410 /* identauth in decimal should be < 2^32 */
411 /* identauth in hex should be >= 2^32 */
412 identauth = atoi(strtok(0,"-"));
414 DEBUG(4,("netlogon rev %d\n", sid->sid_no));
415 DEBUG(4,("netlogon %s ia %d\n", p, identauth));
419 sid->id_auth[2] = (identauth & 0xff000000) >> 24;
420 sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
421 sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
422 sid->id_auth[5] = (identauth & 0x000000ff);
426 while ((p = strtok(0, "-")) != NULL)
428 sid->sub_auths[sid->num_auths++] = atoi(p);
432 static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
434 if (hdr == NULL) return;
436 hdr->major = 5; /* RPC version 5 */
437 hdr->minor = 0; /* minor version 0 */
438 hdr->pkt_type = 2; /* RPC response packet */
439 hdr->frag = 3; /* first frag + last frag */
440 hdr->pack_type = 1; /* packed data representation */
441 hdr->frag_len = data_len; /* fragment length, fill in later */
442 hdr->auth_len = 0; /* authentication length */
443 hdr->call_id = call_id; /* call identifier - match incoming RPC */
444 hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */
445 hdr->context_id = 0; /* presentation context identifier */
446 hdr->cancel_count = 0; /* cancel count */
447 hdr->reserved = 0; /* reserved */
450 static void make_rpc_reply(char *inbuf, char *q, int data_len)
452 uint32 callid = RIVAL(inbuf, 12);
455 create_rpc_reply(&hdr, callid, data_len);
456 smb_io_rpc_hdr(False, &hdr, q, q, 4);
459 static int lsa_reply_open_policy(char *q, char *base)
464 /* set up the LSA QUERY INFO response */
465 bzero(&(r_o.pol.data), POL_HND_SIZE);
468 /* store the response in the SMB stream */
469 q = lsa_io_r_open_pol(False, &r_o, q, base, 4);
471 /* return length of SMB data stored */
475 static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
477 hdr->uni_max_len = max_len;
478 hdr->uni_str_len = len;
479 hdr->undoc = terminate;
482 static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
484 make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
485 hdr->undoc_buffer = len > 0 ? 1 : 0;
488 static void make_unistr(UNISTR *str, char *buf)
490 /* store the string (null-terminated copy) */
491 PutUniCode((char *)(str->buffer), buf);
494 static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
496 /* set up string lengths. add one if string is not null-terminated */
497 str->uni_max_len = len + (terminate != 0 ? 1 : 0);
499 str->uni_str_len = len;
501 /* store the string (null-terminated copy) */
502 PutUniCode((char *)str->buffer, buf);
504 /* overwrite the last character: some strings are terminated with 4 not 0 */
505 str->buffer[len] = (uint16)terminate;
508 static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str)
510 int len_sid_str = strlen(sid_str);
514 make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0);
515 make_unistr (&(sid2->str), sid_str);
518 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
520 int domlen = strlen(dom_name);
522 d_q->uni_dom_max_len = domlen * 2;
524 d_q->uni_dom_str_len = domlen * 2;
526 d_q->buffer_dom_name = 0; /* domain buffer pointer */
527 d_q->buffer_dom_sid = 0; /* domain sid pointer */
529 /* NOT null-terminated: 4-terminated instead! */
530 make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
532 make_dom_sid(&(d_q->dom_sid), dom_sid);
535 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
536 char *dom_name, char *dom_sid)
539 LSA_R_QUERY_INFO r_q;
541 /* set up the LSA QUERY INFO response */
543 r_q.undoc_buffer = 1; /* not null */
544 r_q.info_class = q_q->info_class;
546 make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
550 /* store the response in the SMB stream */
551 q = lsa_io_r_query(False, &r_q, q, base, 4);
553 /* return length of SMB data stored */
557 /* pretty much hard-coded choice of "other" sids, unfortunately... */
558 static void make_dom_ref(DOM_R_REF *ref,
559 char *dom_name, char *dom_sid,
560 char *other_sid1, char *other_sid2, char *other_sid3)
562 int len_dom_name = strlen(dom_name);
563 int len_other_sid1 = strlen(other_sid1);
564 int len_other_sid2 = strlen(other_sid2);
565 int len_other_sid3 = strlen(other_sid3);
567 ref->undoc_buffer = 1;
568 ref->num_ref_doms_1 = 4;
569 ref->buffer_dom_name = 1;
570 ref->max_entries = 32;
571 ref->num_ref_doms_2 = 4;
573 make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0);
574 make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
575 make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
576 make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
578 if (dom_name != NULL)
580 make_unistr(&(ref->uni_dom_name), dom_name);
583 make_dom_sid(&(ref->ref_dom[0]), dom_sid );
584 make_dom_sid(&(ref->ref_dom[1]), other_sid1);
585 make_dom_sid(&(ref->ref_dom[2]), other_sid2);
586 make_dom_sid(&(ref->ref_dom[3]), other_sid3);
589 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
590 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
591 char *dom_name, char *dom_sid,
592 char *other_sid1, char *other_sid2, char *other_sid3)
596 make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
597 other_sid1, other_sid2, other_sid3);
599 r_l->num_entries = num_entries;
600 r_l->undoc_buffer = 1;
601 r_l->num_entries2 = num_entries;
603 for (i = 0; i < num_entries; i++)
605 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
608 r_l->num_entries3 = num_entries;
611 static int lsa_reply_lookup_sids(char *q, char *base,
612 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
613 char *dom_name, char *dom_sid,
614 char *other_sid1, char *other_sid2, char *other_sid3)
617 LSA_R_LOOKUP_SIDS r_l;
619 /* set up the LSA Lookup SIDs response */
620 make_reply_lookup_sids(&r_l, num_entries, dom_sids,
621 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
624 /* store the response in the SMB stream */
625 q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4);
627 /* return length of SMB data stored */
631 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status)
633 memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data));
634 r_c->status = status;
639 /* PAXX: set these to random values */
640 for (int i = 0; i < 8; i+++)
646 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
652 /* set up the LSA REQUEST CHALLENGE response */
654 make_lsa_r_req_chal(&r_c, chal, 0);
656 /* store the response in the SMB stream */
657 q = lsa_io_r_req_chal(False, &r_c, q, base, 4);
659 /* return length of SMB data stored */
663 static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8])
665 memcpy(cred->data, resp_cred, sizeof(cred->data));
668 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
669 char resp_cred[8], NEG_FLAGS *flgs, int status)
671 make_lsa_chal(&(r_a->srv_chal), resp_cred);
672 memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs));
673 r_a->status = status;
676 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
677 char resp_cred[8], int status)
682 /* set up the LSA AUTH 2 response */
684 make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
686 /* store the response in the SMB stream */
687 q = lsa_io_r_auth_2(False, &r_a, q, base, 4);
689 /* return length of SMB data stored */
693 static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time)
695 make_lsa_chal(&(cred->challenge), srv_chal);
696 cred->timestamp = srv_time;
700 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
701 char srv_chal[8], UTIME srv_time, int status)
703 make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time);
704 r_a->status = status;
707 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
708 char srv_cred[8], UTIME srv_time,
714 /* set up the LSA Server Password Set response */
715 make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status);
717 /* store the response in the SMB stream */
718 q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4);
720 /* return length of SMB data stored */
724 static void make_lsa_user_info(LSA_USER_INFO *usr,
728 NTTIME *kickoff_time,
729 NTTIME *pass_last_set_time,
730 NTTIME *pass_can_change_time,
731 NTTIME *pass_must_change_time,
755 char *other_sids) /* space-delimited set of SIDs */
757 /* only cope with one "other" sid, right now. */
758 /* need to count the number of space-delimited sids */
760 int num_other_sids = other_sids != NULL ? 1 : 0;
762 int len_user_name = strlen(user_name );
763 int len_full_name = strlen(full_name );
764 int len_logon_script = strlen(logon_script);
765 int len_profile_path = strlen(profile_path);
766 int len_home_dir = strlen(home_dir );
767 int len_dir_drive = strlen(dir_drive );
769 int len_logon_srv = strlen(logon_srv);
770 int len_logon_dom = strlen(logon_dom);
772 usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
774 usr->logon_time = *logon_time;
775 usr->logoff_time = *logoff_time;
776 usr->kickoff_time = *kickoff_time;
777 usr->pass_last_set_time = *pass_last_set_time;
778 usr->pass_can_change_time = *pass_can_change_time;
779 usr->pass_must_change_time = *pass_must_change_time;
781 make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4);
782 make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4);
783 make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
784 make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
785 make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4);
786 make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4);
788 usr->logon_count = logon_count;
789 usr->bad_pw_count = bad_pw_count;
791 usr->user_id = user_id;
792 usr->group_id = group_id;
793 usr->num_groups = num_groups;
794 usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
795 usr->user_flgs = user_flgs;
797 if (sess_key != NULL)
799 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
803 bzero(usr->sess_key, sizeof(usr->sess_key));
806 make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
807 make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
809 usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
811 bzero(usr->padding, sizeof(usr->padding));
813 usr->num_other_sids = num_other_sids;
814 usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0;
816 make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0);
817 make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0);
818 make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
819 make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
820 make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0);
821 make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0);
823 usr->num_groups2 = num_groups;
824 for (i = 0; i < num_groups; i++)
826 usr->gids[i] = gids[i];
829 make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
830 make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
832 make_dom_sid(&(usr->dom_sid), dom_sid);
833 make_dom_sid(&(usr->other_sids[0]), other_sids);
837 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
838 char srv_cred[8], UTIME srv_time,
839 LSA_USER_INFO *user_info)
844 /* XXXX maybe we want to say 'no', reject the client's credentials */
845 r_s.buffer_creds = 1; /* yes, we have valid server credentials */
846 make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
848 /* store the user information, if there is any. */
849 r_s.user = user_info;
850 r_s.buffer_user = user_info != NULL ? 1 : 0;
851 r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
853 /* store the response in the SMB stream */
854 q = lsa_io_r_sam_logon(False, &r_s, q, base, 4);
856 /* return length of SMB data stored */
861 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
862 char srv_cred[8], UTIME srv_time,
866 LSA_R_SAM_LOGOFF r_s;
868 /* XXXX maybe we want to say 'no', reject the client's credentials */
869 r_s.buffer_creds = 1; /* yes, we have valid server credentials */
870 make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
874 /* store the response in the SMB stream */
875 q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4);
877 /* return length of SMB data stored */
882 static void api_lsa_open_policy( char *param, char *data,
883 char **rdata, int *rdata_len )
887 /* we might actually want to decode the query, but it's not necessary */
888 /* lsa_io_q_open_policy(...); */
890 /* return a 20 byte policy handle */
891 reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18);
893 /* construct header, now that we know the reply length */
894 make_rpc_reply(data, *rdata, reply_len);
895 *rdata_len = reply_len + 0x18;
898 static void api_lsa_query_info( char *param, char *data,
899 char **rdata, int *rdata_len )
903 LSA_Q_QUERY_INFO q_i;
907 /* grab the info class and policy handle */
908 lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4);
910 pstrcpy(dom_name, lp_workgroup());
911 pstrcpy(dom_sid , lp_domainsid());
913 /* construct reply. return status is always 0x0 */
914 reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18,
917 /* construct header, now that we know the reply length */
918 make_rpc_reply(data, *rdata, reply_len);
919 *rdata_len = reply_len + 0x18;
922 static void api_lsa_lookup_sids( char *param, char *data,
923 char **rdata, int *rdata_len )
928 LSA_Q_LOOKUP_SIDS q_l;
931 fstring dom_sids[MAX_LOOKUP_SIDS];
933 /* grab the info class and policy handle */
934 lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4);
936 pstrcpy(dom_name, lp_workgroup());
937 pstrcpy(dom_sid , lp_domainsid());
939 /* convert received SIDs to strings, so we can do them. */
940 for (i = 0; i < q_l.num_entries; i++)
942 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
945 /* construct reply. return status is always 0x0 */
946 reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18,
947 q_l.num_entries, dom_sids, /* text-converted SIDs */
948 dom_name, dom_sid, /* domain name, domain SID */
949 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
951 /* construct header, now that we know the reply length */
952 make_rpc_reply(data, *rdata, reply_len);
953 *rdata_len = reply_len + 0x18;
958 PAXX: Someone fix above.
959 The above API is indexing RPC calls based on RPC flags and
960 fragment length. I've decided to do it based on operation number :-)
963 BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data,
964 int mdrcnt,int mprcnt,
965 char **rdata,char **rparam,
966 int *rdata_len,int *rparam_len)
975 int subauths[MAXSUBAUTHS];
976 struct smb_passwd *smb_pass; /* To check if machine account exists */
980 uint16 revision; /* Domain sid revision */
986 uint16 secchanneltype;
1000 uint16 usernamemaxlen;
1003 uchar *rc4lmowfpass;
1004 uchar *rc4ntowfpass;
1008 struct uinfo *userinfo;
1012 uchar ntowfpass[16];
1016 uchar *sids[MAXSIDS]; /* for lookup SID */
1020 uchar *names[MAXNAMES];
1022 opnum = SVAL(data,22);
1024 pkttype = CVAL(data, 2);
1025 if (pkttype == 0x0b) /* RPC BIND */
1027 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1028 LsarpcTNP1(data,rdata,rdata_len);
1032 DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1033 initrpcreply(data, *rdata);
1034 DEBUG(4,("netlogon LINE %d\n",__LINE__));
1038 DEBUG(1,("LSAOPENPOLICY\n"));
1039 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1040 DEBUG(4,("netlogon data %lx\n", data));
1042 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1043 /* return a 20 byte policy handle */
1044 /* here's a pretty handle:- */
1050 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1051 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */
1052 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1055 case LSAQUERYINFOPOLICY:
1056 DEBUG(1,("LSAQUERYINFOPOLICY\n"));
1057 dump_data(1,data,128);
1058 infoclass = SVAL(data, 44); /* also a policy handle but who cares? */
1060 qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose
1063 domainname = lp_workgroup();
1064 domlen = strlen(domainname);
1065 strcpy(domsid,lp_domainsid());
1066 DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1067 /* assume, but should check, that domsid starts "S-" */
1068 p = strtok(domsid+2,"-");
1070 DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1071 identauth = atoi(strtok(0,"-"));
1072 DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1074 while (p = strtok(0, "-"))
1075 subauths[numsubauths++] = atoi(p);
1076 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1083 qSSVAL(0); /* 2 undocumented bytes */
1085 qSSVAL(domlen*2); /* unicode domain len and maxlen */
1086 qSIVAL(4); /* domain buffer pointer */
1087 qSIVAL(2); /* domain sid pointer */
1088 qunistr(domainname);
1089 qSIVAL(numsubauths);
1091 qSCVAL(numsubauths);
1092 qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1093 qRSIVAL(identauth); /* next 4 bytes */
1094 for (i = 0; i < numsubauths; i++)
1096 qSIVAL(subauths[i]);
1099 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1102 case LSAENUMTRUSTDOM:
1103 DEBUG(1,("LSAENUMTRUSTDOM\n"));
1105 qSIVAL(0); /* enumeration context */
1106 qSIVAL(0); /* entries read */
1107 qSIVAL(0); /* trust information */
1108 endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1112 DEBUG(1,("LSACLOSE\n"));
1119 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1123 DEBUG(1,("LSAOPENSECRET\n"));
1130 endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1134 DEBUG(1,("LSAOPENSECRET\n"));
1136 policyhandle = q; q += 20;
1138 DEBUG(4,("lookupsid entries %d\n",nentries));
1139 q += (2+nentries) * 4; /* skip bufptrs */
1140 /* now we have nentries sids of the form:
1141 uint32 Subauthority count (SAC)
1143 char Subaurity count again
1144 char[6] Identifier authority
1145 [uint32 subauthority] * SAC
1147 for (nsids = 0; nsids < nentries; nsids++)
1149 DEBUG(4,("lookupsid q in %lx\n",q));
1151 DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0)));
1152 q += 4+1+1+6+IVAL(q,0)*4;
1153 DEBUG(4,("lookupsid q %lx\n",q));
1155 /* There's 16 bytes of something after all of that, don't know
1156 what it is though - incorrectly documented */
1158 DEBUG(4,("lookupsid line %d\n",__LINE__));
1159 /* formulate reply */
1161 qSIVAL(2); /* bufptr */
1162 qSIVAL(4); /* number of referenced domains
1163 - need one per each identifier authority in call */
1164 qSIVAL(2); /* dom bufptr */
1165 qSIVAL(32); /* max entries */
1166 qSIVAL(4); /* number of reference domains? */
1168 qunihdr(lp_workgroup()); /* reference domain */
1169 qSIVAL(2); /* sid bufptr */
1172 qSIVAL(2); /* sid bufptr */
1175 qSIVAL(2); /* sid bufptr */
1178 qSIVAL(2); /* sid bufptr */
1180 qunistr(lp_workgroup());
1181 DEBUG(4,("lookupsid line %d\n",__LINE__));
1183 strcpy(domsid,lp_domainsid());
1184 p = strtok(domsid+2,"-");
1186 identauth = atoi(strtok(0,"-"));
1188 while (p = strtok(0, "-"))
1189 subauths[numsubauths++] = atoi(p);
1190 qSIVAL(numsubauths);
1192 qSCVAL(numsubauths);
1193 qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1194 qRSIVAL(identauth); /* next 4 bytes */
1195 DEBUG(4,("lookupsid line %d\n",__LINE__));
1196 for (i = 0; i < numsubauths; i++)
1198 qSIVAL(subauths[i]);
1200 DEBUG(4,("lookupsid line %d\n",__LINE__));
1203 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1204 DEBUG(4,("lookupsid line %d\n",__LINE__));
1207 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1210 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1213 qSIVAL(2); /* bufptr */
1215 DEBUG(4,("lookupsid line %d\n",__LINE__));
1216 for (i = 0; i < nentries; i++)
1218 qSSVAL(5); /* SID name use ?! */
1219 qSSVAL(0); /* undocumented */
1220 DEBUG(4,("lookupsid line %d\n",__LINE__));
1221 qunihdr(sidtostring(sids[i]));
1222 DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i])));
1223 qSIVAL(0); /* domain index out of above reference domains */
1225 DEBUG(4,("lookupsid line %d\n",__LINE__));
1226 for (i = 0; i < nentries; i++)
1228 qunistr(sidtostring(sids[i]));
1230 qSIVAL(nentries); /* mapped count */
1231 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1234 case LSALOOKUPNAMES:
1235 DEBUG(1,("LSALOOKUPNAMES\n"));
1237 policyhandle = q; q += 20;
1239 DEBUG(4,("lookupnames entries %d\n",nentries));
1240 q += 4; /* skip second count */
1241 q += 8 * nentries; /* skip pointers */
1242 for (nnames = 0; nnames < nentries; nnames++)
1244 names[nnames] = q; /* set name string to unicode header */
1245 q += IVAL(q,0)*2; /* guessing here */
1247 /* There's a translated sids structure next but it looks fals */
1249 DEBUG(4,("lookupnames line %d\n",__LINE__));
1250 /* formulate reply */
1252 qSIVAL(2); /* bufptr */
1253 qSIVAL(4); /* number of referenced domains
1254 - need one per each identifier authority in call */
1255 qSIVAL(2); /* dom bufptr */
1256 qSIVAL(32); /* max entries */
1257 qSIVAL(4); /* number of reference domains? */
1259 qunihdr(lp_workgroup()); /* reference domain */
1260 qSIVAL(2); /* sid bufptr */
1263 qSIVAL(2); /* sid bufptr */
1266 qSIVAL(2); /* sid bufptr */
1269 qSIVAL(2); /* sid bufptr */
1271 qunistr(lp_workgroup());
1272 DEBUG(4,("lookupnames line %d\n",__LINE__));
1274 strcpy(domsid,lp_domainsid());
1275 p = strtok(domsid+2,"-");
1277 identauth = atoi(strtok(0,"-"));
1279 while (p = strtok(0, "-"))
1280 subauths[numsubauths++] = atoi(p);
1281 qSIVAL(numsubauths);
1283 qSCVAL(numsubauths);
1284 qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1285 qRSIVAL(identauth); /* next 4 bytes */
1286 DEBUG(4,("lookupsid line %d\n",__LINE__));
1287 for (i = 0; i < numsubauths; i++)
1289 qSIVAL(subauths[i]);
1291 DEBUG(4,("lookupsid line %d\n",__LINE__));
1294 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1295 DEBUG(4,("lookupsid line %d\n",__LINE__));
1298 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1301 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1304 qSIVAL(2); /* bufptr */
1306 DEBUG(4,("lookupnames line %d\n",__LINE__));
1307 for (i = 0; i < nentries; i++)
1309 qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */
1310 qSSVAL(5); /* undocumented */
1311 DEBUG(4,("lookupnames line %d\n",__LINE__));
1312 qSIVAL(nametorid(names[i]));
1313 DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i])));
1314 qSIVAL(0); /* domain index out of above reference domains */
1316 qSIVAL(nentries); /* mapped count */
1317 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1321 DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1326 BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data,
1327 int mdrcnt,int mprcnt,
1328 char **rdata,char **rparam,
1329 int *rdata_len,int *rparam_len)
1338 int subauths[MAXSUBAUTHS];
1339 struct smb_passwd *smb_pass; /* To check if machine account exists */
1343 uint16 revision; /* Domain sid revision */
1349 uint16 secchanneltype;
1360 uint16 paramcontrol;
1363 uint16 usernamemaxlen;
1366 uchar *rc4lmowfpass;
1367 uchar *rc4ntowfpass;
1371 struct uinfo *userinfo;
1375 uchar ntowfpass[16];
1377 opnum = SVAL(data,22);
1379 pkttype = CVAL(data, 2);
1380 if (pkttype == 0x0b) /* RPC BIND */
1382 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1383 LsarpcTNP1(data,rdata,rdata_len);
1387 DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum));
1388 initrpcreply(data, *rdata);
1389 DEBUG(4,("netlogon LINE %d\n",__LINE__));
1393 DEBUG(1,("LSAREQCHAL\n"));
1396 logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */
1397 q = skip_unicode_string(logonsrv,1) + 12;
1398 q = align4(q, data);
1400 q = skip_unicode_string(unicomp,1);
1403 DEBUG(1,("logonsrv=%s unicomp=%s\n",
1407 dcauth[cnum].chal[0] = IVAL(q, 0);
1408 dcauth[cnum].chal[1] = IVAL(q, 4);
1409 dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */
1410 dcauth[cnum].cred[1] = IVAL(q, 4);
1412 DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1]));
1414 /* PAXX: set these to random values */
1415 dcauth[cnum].svrchal[0] = 0x11111111;
1416 dcauth[cnum].svrchal[1] = 0x22222222;
1417 dcauth[cnum].svrcred[0] = 0x11111111;
1418 dcauth[cnum].svrcred[1] = 0x22222222;
1419 strcpy(machacct,unistr(unicomp));
1420 strcat(machacct, "$");
1421 smb_pass = get_smbpwnam(machacct);
1423 memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16);
1426 /* No such machine account. Should error out here, but we'll
1427 print and carry on */
1428 DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct));
1430 for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]);
1431 DEBUG(1,("pass %s %s\n", machacct, foo));
1434 qSIVAL(dcauth[cnum].svrchal[0]);
1435 qSIVAL(dcauth[cnum].svrchal[1]);
1437 DEBUG(1,("NL: server challenge %08x %08x\n",
1438 dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1]));
1440 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1444 DEBUG(1,("LSAAUTH2\n"));
1448 q = skip_unicode_string(logonsrv,1)+12;
1449 q = align4(q, data);
1452 q = skip_unicode_string(accountname,1);
1453 secchanneltype = qSVAL;
1455 q = align4(q, data);
1457 dump_data(1,unicomp,32);
1458 q = skip_unicode_string(unicomp,1);
1461 q = align4(q, data);
1463 DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n",
1464 unistr(logonsrv), unistr(accountname), unistr(unicomp),
1465 rcvcred[0], rcvcred[1], negflags));
1467 DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n",
1468 rcvcred[0], rcvcred[1], negflags));
1470 checkcred(cnum, rcvcred[0], rcvcred[1], 0);
1472 makecred(cnum, 0, q);
1476 /* update stored client credentials */
1477 dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0];
1478 dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1];
1479 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1483 DEBUG(1,("LSASVRPWSET\n"));
1487 q = skip_unicode_string(logonsrv,1)+12;
1488 q = align4(q, data);
1490 q = skip_unicode_string(accountname,1);
1491 secchanneltype = qSVAL;
1493 q = align4(q, data);
1495 q = skip_unicode_string(unicomp,1);
1500 DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n",
1501 unistr(logonsrv), unistr(accountname), unistr(unicomp)));
1503 checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1504 DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags));
1507 DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n",
1508 unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass));
1510 /* PAXX: For the moment we'll reject these */
1511 /* TODO Need to set newpass in smbpasswd file for accountname */
1513 makecred(cnum, clnttime+1, q);
1515 qSIVAL(0); /* timestamp. Seems to be ignored */
1517 dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1519 endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len);
1523 DEBUG(1,("LSASAMLOGON\n"));
1524 dump_data(1,data,128);
1527 DEBUG(1,("SMLOG %d\n", __LINE__));
1528 q = skip_unicode_string(logonsrv,1)+16;
1529 q = align4(q, data);
1531 q = skip_unicode_string(unicomp,1)+4;
1532 DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n",
1533 __LINE__, unistr(logonsrv), unistr(unicomp)));
1534 q = align4(q, data);
1536 DEBUG(1,("SMLOG %d\n", __LINE__));
1538 DEBUG(1,("SMLOG %d\n", __LINE__));
1540 checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1542 rtncred[0] = qIVAL; /* all these are ignored */
1543 DEBUG(1,("SMLOG %d\n", __LINE__));
1547 DEBUG(1,("SMLOG %d\n", __LINE__));
1555 dommaxlen = qSVAL; q += 4;
1556 paramcontrol = qIVAL;
1557 logonid[0] = qIVAL; /* low part */
1558 logonid[1] = qIVAL; /* high part */
1560 usernamelen = qSVAL;
1562 DEBUG(1,("SMLOG %d\n", __LINE__));
1563 usernamemaxlen = qSVAL; q += 4;
1565 DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n",
1566 usernamelen, usernamemaxlen, dommaxlen));
1571 wsmaxlen = qSVAL; q += 4;
1572 rc4lmowfpass = q; q += 16;
1573 rc4ntowfpass = q; q += 16;
1575 q += 12; domain = q; q += dommaxlen + 12;
1576 q = align4(q, data);
1577 username = q; q += usernamemaxlen + 12;
1578 q = align4(q, data);
1580 DEBUG(1,("domain=%s username=%s ws=%s\n",
1581 unistr(domain), unistr(username),
1585 DEBUG(0,("unknown switch in SAMLOGON %d\n",
1588 for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]);
1589 DEBUG(1,("userNAME %s [%s]\n", foo, username));
1590 DEBUG(1,("SMLOG %d\n", __LINE__));
1592 qSIVAL(0x16a4b4); /* magic buffer pointer ? */
1593 makecred(cnum, clnttime+1, q);
1594 dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1596 qSIVAL(0); /* timestamp. client doesn't care */
1597 qSSVAL(3); /* switch value 3. May be others? */
1598 qSSVAL(0); /* undocumented */
1599 DEBUG(1,("SMLOG %d\n", __LINE__));
1601 memset(rc4key, 0, sizeof rc4key);
1602 SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]);
1603 SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]);
1604 for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]);
1605 DEBUG(1,("rc4ntowf %s\n", foo));
1606 arcfour_init(&c, rc4key, sizeof rc4key);
1607 arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass);
1608 for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]);
1609 DEBUG(1,("ntowf %s\n", foo));
1611 if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) {
1612 qSIVAL(0); /* no buffer */
1613 qSCVAL(1); /* Authoratitive. Change if passthrough? */
1614 qSCVAL(0); /* pad for above boolean */
1615 qSSVAL(0); /* pad for above boolean */
1617 endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len);
1621 qSIVAL(2); /* another magic bufptr? */
1622 DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo));
1623 qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]);
1624 qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]);
1625 DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1]));
1626 qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]);
1627 qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]);
1628 qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]);
1629 qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]);
1630 DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename));
1631 qunihdr(userinfo->effectivename);
1632 qunihdr(userinfo->fullname);
1633 DEBUG(1,("SMLOG %d\n", __LINE__));
1634 qunihdr(userinfo->logonscript);
1635 qunihdr(userinfo->profilepath);
1636 qunihdr(userinfo->homedirectory);
1637 qunihdr(userinfo->homedirectorydrive);
1638 DEBUG(1,("SMLOG %d\n", __LINE__));
1639 qSSVAL(userinfo->logoncount);
1640 qSSVAL(userinfo->badpwcount);
1641 qSIVAL(userinfo->uid);
1642 qSIVAL(userinfo->gid);
1643 DEBUG(1,("SMLOG %d\n", __LINE__));
1644 qSIVAL(userinfo->ngroups);
1645 qSIVAL(8); /* ptr to groups */
1646 qSIVAL(userinfo->userflags);
1647 DEBUG(1,("SMLOG %d\n", __LINE__));
1648 qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */
1649 qunihdr(userinfo->logonserver);
1650 qunihdr(userinfo->logondomain);
1651 DEBUG(1,("SMLOG %d\n", __LINE__));
1652 qSIVAL(2); /* logon domain id ptr */
1653 DEBUG(1,("SMLOG %d\n", __LINE__));
1654 memset(q,0,40); q += 40; /* expansion room */
1655 DEBUG(1,("SMLOG %d\n", __LINE__));
1656 qSIVAL(userinfo->nsids);
1657 DEBUG(1,("SMLOG %d\n", __LINE__));
1658 qSIVAL(0); /* ptr to sids and values */
1659 DEBUG(1,("SMLOG %d\n", __LINE__));
1660 qunistr(userinfo->effectivename);
1661 DEBUG(1,("SMLOG %d\n", __LINE__));
1662 qunistr(userinfo->fullname);
1663 DEBUG(1,("SMLOG %d\n", __LINE__));
1664 qunistr(userinfo->logonscript);
1665 DEBUG(1,("SMLOG %d\n", __LINE__));
1666 qunistr(userinfo->profilepath);
1667 qunistr(userinfo->homedirectory);
1668 qunistr(userinfo->homedirectorydrive);
1669 DEBUG(1,("SMLOG %d\n", __LINE__));
1670 qSIVAL(userinfo->ngroups);
1671 for (i = 0; i < userinfo->ngroups; i++)
1673 qSIVAL(userinfo->groups[i].gid);
1674 qSIVAL(userinfo->groups[i].attr);
1676 qunistr(userinfo->logonserver);
1677 qunistr(userinfo->logondomain);
1678 for (i = 0; i < userinfo->nsids; i++)
1680 /* put the extra sids: PAXX: TODO */
1682 /* Assumption. This is the only domain, sending our SID */
1683 /* PAXX: may want to do passthrough later */
1684 strcpy(domsid,lp_domainsid());
1685 DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1686 /* assume, but should check, that domsid starts "S-" */
1687 p = strtok(domsid+2,"-");
1689 DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1690 identauth = atoi(strtok(0,"-"));
1691 DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1693 while (p = strtok(0, "-"))
1694 subauths[numsubauths++] = atoi(p);
1695 qSIVAL(numsubauths);
1697 qSCVAL(numsubauths);
1698 qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */
1699 qRSIVAL(identauth); /* next 4 bytes */
1700 DEBUG(1,("SMLOG %d\n", __LINE__));
1701 for (i = 0; i < numsubauths; i++)
1703 qSIVAL(subauths[i]);
1705 qSCVAL(1); /* Authoratitive. Change if passthrough? */
1706 qSCVAL(0); /* pad for above boolean */
1707 qSSVAL(0); /* pad for above boolean */
1709 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1713 DEBUG(1,("LSASAMLOGOFF\n"));
1716 DEBUG(1,("SAMLOGOFF %d\n", __LINE__));
1717 unicomp = skip_unicode_string(logonsrv,1)+16;
1718 if (strlen(unistr(logonsrv)) % 2 == 0)
1720 DEBUG(1,("SMLOG %d\n", __LINE__));
1721 q = skip_unicode_string(unicomp,1)+4;
1722 if (strlen(unistr(unicomp)) % 2 == 0)
1724 DEBUG(1,("SMLOG %d\n", __LINE__));
1726 DEBUG(1,("SMLOG %d\n", __LINE__));
1728 DEBUG(1,("SMLOG %d\n", __LINE__));
1730 checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1732 rtncred[0] = qIVAL; /* all these are ignored */
1733 DEBUG(1,("SMLOG %d\n", __LINE__));
1737 DEBUG(1,("SMLOG %d\n", __LINE__));
1744 dommaxlen = qSVAL; q += 4;
1745 paramcontrol = qIVAL;
1746 logonid[0] = qIVAL; /* low part */
1747 logonid[1] = qIVAL; /* high part */
1748 usernamelen = qSVAL;
1749 DEBUG(1,("SMLOG %d\n", __LINE__));
1750 usernamemaxlen = qSVAL; q += 4;
1752 wsmaxlen = qSVAL; q += 4;
1753 rc4lmowfpass = q; q += 16;
1754 rc4ntowfpass = q; q += 16;
1755 q += 12; domain = q; q += dommaxlen + 12;
1756 if ((domlen/2) % 2 != 0) q += 2;
1757 username = q; q += usernamemaxlen + 12; /* PAXX: HACK */
1758 if ((usernamelen/2) % 2 != 0) q += 2;
1761 default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval));
1763 DEBUG(1,("SAMLOGOFF %s\n", unistr(username)));
1765 DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum));
1770 void initrpcreply(char *inbuf, char *q)
1774 qSCVAL(5); /* RPC version 5 */
1775 qSCVAL(0); /* minor version 0 */
1776 qSCVAL(2); /* RPC response packet */
1777 qSCVAL(3); /* first frag + last frag */
1778 qRSIVAL(0x10000000); /* packed data representation */
1779 qRSSVAL(0); /* fragment length, fill in later */
1780 qSSVAL(0); /* authentication length */
1781 callid = RIVAL(inbuf,12);
1782 qRSIVAL(callid); /* call identifier - match incoming RPC */
1783 qSIVAL(0x18); /* allocation hint (no idea) */
1784 qSSVAL(0); /* presentation context identifier */
1785 qSCVAL(0); /* cancel count */
1786 qSCVAL(0); /* reserved */
1789 endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen)
1791 SSVAL(q, 8, datalen + 4);
1792 SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */
1793 SIVAL(q, datalen, rtnval);
1794 *rlen = datalen + 4;
1795 {int fd; fd = open("/tmp/rpc", O_RDWR);write(fd,q,datalen+4);}
1798 void setsesskey(int cnum)
1805 sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0];
1806 sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1];
1807 SIVAL(netsum,0,sum[0]);
1808 SIVAL(netsum,4,sum[1]);
1809 E1(dcauth[cnum].md4pw,netsum,icv);
1810 E1(dcauth[cnum].md4pw+9,icv,netsesskey);
1811 dcauth[cnum].sesskey[0] = IVAL(netsesskey,0);
1812 dcauth[cnum].sesskey[1] = IVAL(netsesskey,4);
1814 DEBUG(1,("NL: session key %08x %08x\n",
1815 dcauth[cnum].sesskey[0],
1816 dcauth[cnum].sesskey[1]));
1819 void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time)
1828 SIVAL(netdata, 0, dcauth[cnum].cred[0]+time);
1829 SIVAL(netdata, 4, dcauth[cnum].cred[1]);
1830 SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]);
1831 SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]);
1832 E1(netsesskey,netdata,icv);
1833 memset(key2, 0, sizeof key2);
1834 key2[0] = netsesskey[7];
1835 E1(key2, icv, calccred);
1836 if (IVAL(calccred,0) != cred0 ||
1837 IVAL(calccred,4) != cred1)
1839 DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n",
1841 dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
1842 dcauth[cnum].cred[0], dcauth[cnum].cred[1],
1843 IVAL(calccred,0), IVAL(calccred,4)));
1844 /* PAXX: do something about it! */
1846 DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n",
1848 dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
1849 dcauth[cnum].cred[0], dcauth[cnum].cred[1],
1850 IVAL(calccred,0), IVAL(calccred,4)));
1853 void makecred(int cnum, uint32 time, char *calccred)
1861 SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time);
1862 SIVAL(netdata, 4, dcauth[cnum].svrcred[1]);
1863 SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]);
1864 SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]);
1865 E1(netsesskey,netdata,icv);
1866 memset(key2, 0, sizeof key2);
1867 key2[0] = netsesskey[7];
1868 E1(key2, icv, calccred);
1869 DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n",
1870 dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1],
1871 dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
1872 dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1],
1873 IVAL(calccred, 0), IVAL(calccred, 4)));
1877 struct uinfo *getuserinfo(char *user, int len, char *ntowfpass)
1879 static struct uinfo u;
1880 static pstring fullnm;
1881 static pstring ascuser;
1882 extern pstring myname;
1883 static pstring stme;
1884 static pstring stdom;
1885 struct smb_passwd *smb_pass;
1887 strcpy(ascuser,unistr(user));
1888 ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */
1889 DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len));
1891 smb_pass = get_smbpwnam(ascuser);
1894 DEBUG(1,("GETU %d\n", __LINE__));
1895 if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) {
1896 DEBUG(1,("pass mismatch:\n"));
1897 dump_data(1,ntowfpass,16);
1898 dump_data(1,smb_pass->smb_nt_passwd,16);
1902 DEBUG(1,("GETU %d\n", __LINE__));
1903 u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff;
1904 u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff;
1905 u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff;
1906 DEBUG(1,("GETU %d\n", __LINE__));
1907 u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff;
1908 u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff;
1909 u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff;
1910 DEBUG(1,("GETU %d\n", __LINE__));
1911 u.effectivename = ascuser;
1912 strcpy(fullnm, "Full name of ");
1913 strcat(fullnm, ascuser);
1914 DEBUG(1,("GETU %d\n", __LINE__));
1915 u.fullname = fullnm;
1916 u.logonscript = "foologin.cmd";
1917 u.profilepath = "prof";
1918 u.homedirectory = "foohomes";
1919 DEBUG(1,("GETU %d\n", __LINE__));
1920 u.homedirectorydrive = "a:";
1924 DEBUG(1,("GETU %d\n", __LINE__));
1927 u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2));
1928 u.groups[0].gid = 776;
1929 DEBUG(1,("GETU %d\n", __LINE__));
1930 u.groups[0].attr = 0x7;
1931 u.groups[1].gid = 776;
1932 u.groups[1].attr = 0x7;
1934 u.logonserver = stme;
1935 get_myname(myname,NULL);
1936 strcpy(stme, myname);
1938 DEBUG(1,("LS %s\n", u.logonserver));
1939 u.logondomain = stdom;
1940 strcpy(stdom, lp_workgroup());
1942 DEBUG(1,("DOM %s\n", u.logondomain));
1945 DEBUG(1,("GETU %d\n", __LINE__));
1950 nametorid(char *uniuser)
1952 if (!strncmp(unistr(uniuser+12),"ashtonp",7))
1954 if (!strncmp(unistr(uniuser+12),"user1",5))
1956 if (!strncmp(unistr(uniuser+12),"user2",5))
1958 if (!strncmp(unistr(uniuser+12),"user3",5))
1963 #endif /* NTDOMAIN */