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 #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);
368 PAXX: Someone fix above.
369 The above API is indexing RPC calls based on RPC flags and
370 fragment length. I've decided to do it based on operation number :-)
373 /* this function is due to be replaced */
374 static void initrpcreply(char *inbuf, char *q)
378 SCVAL(q, 0, 5); q++; /* RPC version 5 */
379 SCVAL(q, 0, 0); q++; /* minor version 0 */
380 SCVAL(q, 0, 2); q++; /* RPC response packet */
381 SCVAL(q, 0, 3); q++; /* first frag + last frag */
382 RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */
383 RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */
384 SSVAL(q, 0, 0); q += 2; /* authentication length */
385 callid = RIVAL(inbuf, 12);
386 RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */
387 SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */
388 SSVAL(q, 0, 0); q += 2; /* presentation context identifier */
389 SCVAL(q, 0, 0); q++; /* cancel count */
390 SCVAL(q, 0, 0); q++; /* reserved */
393 /* this function is due to be replaced */
394 static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen)
396 SSVAL(q, 8, datalen + 4);
397 SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */
398 SIVAL(q, datalen, rtnval);
400 { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); }
403 /* RID username mapping function. just for fun, it maps to the unix uid */
404 static uint32 name_to_rid(char *user_name)
406 struct passwd *pw = Get_Pwnam(user_name, False);
409 DEBUG(1,("Username %s is invalid on this system\n", user_name));
413 return (uint32)(pw->pw_uid);
417 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
418 char *dom_sid_to_string(DOM_SID *sid)
420 static pstring sidstr;
423 uint32 ia = (sid->id_auth[0]) +
424 (sid->id_auth[1] << 8 ) +
425 (sid->id_auth[2] << 16) +
426 (sid->id_auth[3] << 24);
428 sprintf(sidstr, "S-%d-%d", sid->sid_no, ia);
430 for (i = 0; i < sid->num_auths; i++)
432 sprintf(subauth, "-%d", sid->sub_auths[i]);
433 strcat(sidstr, subauth);
436 DEBUG(5,("dom_sid_to_string returning %s\n", sidstr));
440 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
441 /* identauth >= 2^32 can be detected because it will be specified in hex */
442 static void make_dom_sid(DOM_SID *sid, char *domsid)
447 DEBUG(4,("netlogon domain SID: %s\n", domsid));
449 /* assume, but should check, that domsid starts "S-" */
450 p = strtok(domsid+2,"-");
451 sid->sid_no = atoi(p);
453 /* identauth in decimal should be < 2^32 */
454 /* identauth in hex should be >= 2^32 */
455 identauth = atoi(strtok(0,"-"));
457 DEBUG(4,("netlogon rev %d\n", sid->sid_no));
458 DEBUG(4,("netlogon %s ia %d\n", p, identauth));
462 sid->id_auth[2] = (identauth & 0xff000000) >> 24;
463 sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
464 sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
465 sid->id_auth[5] = (identauth & 0x000000ff);
469 while ((p = strtok(0, "-")) != NULL)
471 sid->sub_auths[sid->num_auths++] = atoi(p);
475 static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
477 if (hdr == NULL) return;
479 hdr->major = 5; /* RPC version 5 */
480 hdr->minor = 0; /* minor version 0 */
481 hdr->pkt_type = 2; /* RPC response packet */
482 hdr->frag = 3; /* first frag + last frag */
483 hdr->pack_type = 1; /* packed data representation */
484 hdr->frag_len = data_len; /* fragment length, fill in later */
485 hdr->auth_len = 0; /* authentication length */
486 hdr->call_id = call_id; /* call identifier - match incoming RPC */
487 hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */
488 hdr->context_id = 0; /* presentation context identifier */
489 hdr->cancel_count = 0; /* cancel count */
490 hdr->reserved = 0; /* reserved */
493 static void make_rpc_reply(char *inbuf, char *q, int data_len)
495 uint32 callid = RIVAL(inbuf, 12);
498 create_rpc_reply(&hdr, callid, data_len);
499 smb_io_rpc_hdr(False, &hdr, q, q, 4);
502 static int lsa_reply_open_policy(char *q, char *base)
507 /* set up the LSA QUERY INFO response */
508 bzero(&(r_o.pol.data), POL_HND_SIZE);
511 /* store the response in the SMB stream */
512 q = lsa_io_r_open_pol(False, &r_o, q, base, 4);
514 /* return length of SMB data stored */
518 static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
520 hdr->uni_max_len = max_len;
521 hdr->uni_str_len = len;
522 hdr->undoc = terminate;
525 static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
527 make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
528 hdr->undoc_buffer = len > 0 ? 1 : 0;
531 static void make_unistr(UNISTR *str, char *buf)
533 /* store the string (null-terminated copy) */
534 PutUniCode((char *)(str->buffer), buf);
537 static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
539 /* set up string lengths. add one if string is not null-terminated */
540 str->uni_max_len = len + (terminate != 0 ? 1 : 0);
542 str->uni_str_len = len;
544 /* store the string (null-terminated copy) */
545 PutUniCode((char *)str->buffer, buf);
547 /* overwrite the last character: some strings are terminated with 4 not 0 */
548 str->buffer[len] = (uint16)terminate;
551 static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid)
559 static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str)
561 int len_sid_str = strlen(sid_str);
565 make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0);
566 make_unistr (&(sid2->str), sid_str);
569 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
571 int domlen = strlen(dom_name);
573 d_q->uni_dom_max_len = domlen * 2;
575 d_q->uni_dom_str_len = domlen * 2;
577 d_q->buffer_dom_name = 0; /* domain buffer pointer */
578 d_q->buffer_dom_sid = 0; /* domain sid pointer */
580 /* NOT null-terminated: 4-terminated instead! */
581 make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
583 make_dom_sid(&(d_q->dom_sid), dom_sid);
586 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
587 char *dom_name, char *dom_sid)
590 LSA_R_QUERY_INFO r_q;
592 /* set up the LSA QUERY INFO response */
594 r_q.undoc_buffer = 1; /* not null */
595 r_q.info_class = q_q->info_class;
597 make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
601 /* store the response in the SMB stream */
602 q = lsa_io_r_query(False, &r_q, q, base, 4);
604 /* return length of SMB data stored */
608 /* pretty much hard-coded choice of "other" sids, unfortunately... */
609 static void make_dom_ref(DOM_R_REF *ref,
610 char *dom_name, char *dom_sid,
611 char *other_sid1, char *other_sid2, char *other_sid3)
613 int len_dom_name = strlen(dom_name);
614 int len_other_sid1 = strlen(other_sid1);
615 int len_other_sid2 = strlen(other_sid2);
616 int len_other_sid3 = strlen(other_sid3);
618 ref->undoc_buffer = 1;
619 ref->num_ref_doms_1 = 4;
620 ref->buffer_dom_name = 1;
621 ref->max_entries = 32;
622 ref->num_ref_doms_2 = 4;
624 make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0);
625 make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
626 make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
627 make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
629 if (dom_name != NULL)
631 make_unistr(&(ref->uni_dom_name), dom_name);
634 make_dom_sid(&(ref->ref_dom[0]), dom_sid );
635 make_dom_sid(&(ref->ref_dom[1]), other_sid1);
636 make_dom_sid(&(ref->ref_dom[2]), other_sid2);
637 make_dom_sid(&(ref->ref_dom[3]), other_sid3);
640 static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
641 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
642 char *dom_name, char *dom_sid,
643 char *other_sid1, char *other_sid2, char *other_sid3)
647 make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
648 other_sid1, other_sid2, other_sid3);
650 r_l->num_entries = num_entries;
651 r_l->undoc_buffer = 1;
652 r_l->num_entries2 = num_entries;
654 for (i = 0; i < num_entries; i++)
656 make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
659 r_l->num_entries3 = num_entries;
662 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
663 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
664 char *dom_name, char *dom_sid,
665 char *other_sid1, char *other_sid2, char *other_sid3)
669 make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
670 other_sid1, other_sid2, other_sid3);
672 r_l->num_entries = num_entries;
673 r_l->undoc_buffer = 1;
674 r_l->num_entries2 = num_entries;
676 for (i = 0; i < num_entries; i++)
678 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
681 r_l->num_entries3 = num_entries;
684 static int lsa_reply_lookup_sids(char *q, char *base,
685 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
686 char *dom_name, char *dom_sid,
687 char *other_sid1, char *other_sid2, char *other_sid3)
690 LSA_R_LOOKUP_SIDS r_l;
692 /* set up the LSA Lookup SIDs response */
693 make_reply_lookup_sids(&r_l, num_entries, dom_sids,
694 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
697 /* store the response in the SMB stream */
698 q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4);
700 /* return length of SMB data stored */
704 static int lsa_reply_lookup_rids(char *q, char *base,
705 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
706 char *dom_name, char *dom_sid,
707 char *other_sid1, char *other_sid2, char *other_sid3)
710 LSA_R_LOOKUP_RIDS r_l;
712 /* set up the LSA Lookup RIDs response */
713 make_reply_lookup_rids(&r_l, num_entries, dom_rids,
714 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
717 /* store the response in the SMB stream */
718 q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4);
720 /* return length of SMB data stored */
724 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status)
726 memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data));
727 r_c->status = status;
732 /* PAXX: set these to random values */
733 for (int i = 0; i < 8; i+++)
739 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
745 /* set up the LSA REQUEST CHALLENGE response */
747 make_lsa_r_req_chal(&r_c, chal, 0);
749 /* store the response in the SMB stream */
750 q = lsa_io_r_req_chal(False, &r_c, q, base, 4);
752 /* return length of SMB data stored */
756 static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8])
758 memcpy(cred->data, resp_cred, sizeof(cred->data));
761 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
762 char resp_cred[8], NEG_FLAGS *flgs, int status)
764 make_lsa_chal(&(r_a->srv_chal), resp_cred);
765 memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs));
766 r_a->status = status;
769 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
770 char resp_cred[8], int status)
775 /* set up the LSA AUTH 2 response */
777 make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
779 /* store the response in the SMB stream */
780 q = lsa_io_r_auth_2(False, &r_a, q, base, 4);
782 /* return length of SMB data stored */
786 static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time)
788 make_lsa_chal(&(cred->challenge), srv_chal);
789 cred->timestamp = srv_time;
793 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
794 char srv_chal[8], UTIME srv_time, int status)
796 make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time);
797 r_a->status = status;
800 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
801 char srv_cred[8], UTIME srv_time,
807 /* set up the LSA Server Password Set response */
808 make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status);
810 /* store the response in the SMB stream */
811 q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4);
813 /* return length of SMB data stored */
817 static void make_lsa_user_info(LSA_USER_INFO *usr,
821 NTTIME *kickoff_time,
822 NTTIME *pass_last_set_time,
823 NTTIME *pass_can_change_time,
824 NTTIME *pass_must_change_time,
848 char *other_sids) /* space-delimited set of SIDs */
850 /* only cope with one "other" sid, right now. */
851 /* need to count the number of space-delimited sids */
853 int num_other_sids = other_sids != NULL ? 1 : 0;
855 int len_user_name = strlen(user_name );
856 int len_full_name = strlen(full_name );
857 int len_logon_script = strlen(logon_script);
858 int len_profile_path = strlen(profile_path);
859 int len_home_dir = strlen(home_dir );
860 int len_dir_drive = strlen(dir_drive );
862 int len_logon_srv = strlen(logon_srv);
863 int len_logon_dom = strlen(logon_dom);
865 usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
867 usr->logon_time = *logon_time;
868 usr->logoff_time = *logoff_time;
869 usr->kickoff_time = *kickoff_time;
870 usr->pass_last_set_time = *pass_last_set_time;
871 usr->pass_can_change_time = *pass_can_change_time;
872 usr->pass_must_change_time = *pass_must_change_time;
874 make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4);
875 make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4);
876 make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
877 make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
878 make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4);
879 make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4);
881 usr->logon_count = logon_count;
882 usr->bad_pw_count = bad_pw_count;
884 usr->user_id = user_id;
885 usr->group_id = group_id;
886 usr->num_groups = num_groups;
887 usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
888 usr->user_flgs = user_flgs;
890 if (sess_key != NULL)
892 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
896 bzero(usr->sess_key, sizeof(usr->sess_key));
899 make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
900 make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
902 usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
904 bzero(usr->padding, sizeof(usr->padding));
906 usr->num_other_sids = num_other_sids;
907 usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0;
909 make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0);
910 make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0);
911 make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
912 make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
913 make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0);
914 make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0);
916 usr->num_groups2 = num_groups;
917 for (i = 0; i < num_groups; i++)
919 usr->gids[i] = gids[i];
922 make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
923 make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
925 make_dom_sid(&(usr->dom_sid), dom_sid);
926 make_dom_sid(&(usr->other_sids[0]), other_sids);
930 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
931 char srv_cred[8], UTIME srv_time,
932 LSA_USER_INFO *user_info)
937 /* XXXX maybe we want to say 'no', reject the client's credentials */
938 r_s.buffer_creds = 1; /* yes, we have valid server credentials */
939 make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
941 /* store the user information, if there is any. */
942 r_s.user = user_info;
943 r_s.buffer_user = user_info != NULL ? 1 : 0;
944 r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
946 /* store the response in the SMB stream */
947 q = lsa_io_r_sam_logon(False, &r_s, q, base, 4);
949 /* return length of SMB data stored */
954 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
955 char srv_cred[8], UTIME srv_time,
959 LSA_R_SAM_LOGOFF r_s;
961 /* XXXX maybe we want to say 'no', reject the client's credentials */
962 r_s.buffer_creds = 1; /* yes, we have valid server credentials */
963 make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
967 /* store the response in the SMB stream */
968 q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4);
970 /* return length of SMB data stored */
975 static void api_lsa_open_policy( char *param, char *data,
976 char **rdata, int *rdata_len )
980 /* we might actually want to decode the query, but it's not necessary */
981 /* lsa_io_q_open_policy(...); */
983 /* return a 20 byte policy handle */
984 reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18);
986 /* construct header, now that we know the reply length */
987 make_rpc_reply(data, *rdata, reply_len);
988 *rdata_len = reply_len + 0x18;
991 static void api_lsa_query_info( char *param, char *data,
992 char **rdata, int *rdata_len )
996 LSA_Q_QUERY_INFO q_i;
1000 /* grab the info class and policy handle */
1001 lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4);
1003 pstrcpy(dom_name, lp_workgroup());
1004 pstrcpy(dom_sid , lp_domainsid());
1006 /* construct reply. return status is always 0x0 */
1007 reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18,
1010 /* construct header, now that we know the reply length */
1011 make_rpc_reply(data, *rdata, reply_len);
1012 *rdata_len = reply_len + 0x18;
1015 static void api_lsa_lookup_sids( char *param, char *data,
1016 char **rdata, int *rdata_len )
1021 LSA_Q_LOOKUP_SIDS q_l;
1024 fstring dom_sids[MAX_LOOKUP_SIDS];
1026 /* grab the info class and policy handle */
1027 lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4);
1029 pstrcpy(dom_name, lp_workgroup());
1030 pstrcpy(dom_sid , lp_domainsid());
1032 /* convert received SIDs to strings, so we can do them. */
1033 for (i = 0; i < q_l.num_entries; i++)
1035 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
1038 /* construct reply. return status is always 0x0 */
1039 reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18,
1040 q_l.num_entries, dom_sids, /* text-converted SIDs */
1041 dom_name, dom_sid, /* domain name, domain SID */
1042 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1044 /* construct header, now that we know the reply length */
1045 make_rpc_reply(data, *rdata, reply_len);
1046 *rdata_len = reply_len + 0x18;
1049 static void api_lsa_lookup_names( char *param, char *data,
1050 char **rdata, int *rdata_len )
1055 LSA_Q_LOOKUP_RIDS q_l;
1058 uint32 dom_rids[MAX_LOOKUP_SIDS];
1060 /* grab the info class and policy handle */
1061 lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4);
1063 pstrcpy(dom_name, lp_workgroup());
1064 pstrcpy(dom_sid , lp_domainsid());
1066 /* convert received RIDs to strings, so we can do them. */
1067 for (i = 0; i < q_l.num_entries; i++)
1069 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
1070 dom_rids[i] = name_to_rid(user_name);
1073 /* construct reply. return status is always 0x0 */
1074 reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18,
1075 q_l.num_entries, dom_rids, /* text-converted SIDs */
1076 dom_name, dom_sid, /* domain name, domain SID */
1077 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1079 /* construct header, now that we know the reply length */
1080 make_rpc_reply(data, *rdata, reply_len);
1081 *rdata_len = reply_len + 0x18;
1084 BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data,
1085 int mdrcnt,int mprcnt,
1086 char **rdata,char **rparam,
1087 int *rdata_len,int *rparam_len)
1089 uint16 opnum = SVAL(data,22);
1091 int pkttype = CVAL(data, 2);
1092 if (pkttype == 0x0b) /* RPC BIND */
1094 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1095 LsarpcTNP1(data,rdata,rdata_len);
1099 DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1102 case LSA_OPENPOLICY:
1104 DEBUG(3,("LSA_OPENPOLICY\n"));
1105 api_lsa_open_policy(param, data, rdata, rdata_len);
1109 case LSA_QUERYINFOPOLICY:
1111 DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
1113 api_lsa_query_info(param, data, rdata, rdata_len);
1117 case LSA_ENUMTRUSTDOM:
1119 char *q = *rdata + 0x18;
1121 DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
1123 initrpcreply(data, *rdata);
1125 SIVAL(q, 0, 0); /* enumeration context */
1126 SIVAL(q, 0, 4); /* entries read */
1127 SIVAL(q, 0, 8); /* trust information */
1129 endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1136 char *q = *rdata + 0x18;
1138 DEBUG(3,("LSA_CLOSE\n"));
1140 initrpcreply(data, *rdata);
1148 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1153 case LSA_OPENSECRET:
1155 char *q = *rdata + 0x18;
1156 DEBUG(3,("LSA_OPENSECRET\n"));
1158 initrpcreply(data, *rdata);
1166 endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1171 case LSA_LOOKUPSIDS:
1173 DEBUG(3,("LSA_OPENSECRET\n"));
1174 api_lsa_lookup_sids(param, data, rdata, rdata_len);
1178 case LSA_LOOKUPNAMES:
1180 DEBUG(3,("LSA_LOOKUPNAMES\n"));
1181 api_lsa_lookup_names(param, data, rdata, rdata_len);
1187 DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1195 #ifdef UNDEFINED_NTDOMAIN
1197 PAXX: Someone fix above.
1198 The above API is indexing RPC calls based on RPC flags and
1199 fragment length. I've decided to do it based on operation number :-)
1202 BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data,
1203 int mdrcnt,int mprcnt,
1204 char **rdata,char **rparam,
1205 int *rdata_len,int *rparam_len)
1214 int subauths[MAXSUBAUTHS];
1215 struct smb_passwd *smb_pass; /* To check if machine account exists */
1219 uint16 revision; /* Domain sid revision */
1225 uint16 secchanneltype;
1236 uint16 paramcontrol;
1239 uint16 usernamemaxlen;
1242 uchar *rc4lmowfpass;
1243 uchar *rc4ntowfpass;
1247 struct uinfo *userinfo;
1250 uchar ntowfpass[16];
1254 uchar *sids[MAXSIDS]; /* for lookup SID */
1257 uchar *names[MAXNAMES];
1259 opnum = SVAL(data,22);
1261 pkttype = CVAL(data, 2);
1262 if (pkttype == 0x0b) /* RPC BIND */
1264 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1265 LsarpcTNP1(data,rdata,rdata_len);
1269 DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
1270 initrpcreply(data, *rdata);
1271 DEBUG(4,("netlogon LINE %d\n",__LINE__));
1275 DEBUG(1,("LSAOPENPOLICY\n"));
1276 char *q = *rdata + 0x18;
1277 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1278 /* return a 20 byte policy handle */
1279 /* here's a pretty handle:- */
1285 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1286 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); /* size of data plus return code */
1287 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1290 case LSAQUERYINFOPOLICY:
1291 DEBUG(1,("LSAQUERYINFOPOLICY\n"));
1292 dump_data(1,data,128);
1293 infoclass = SVAL(data, 44); /* also a policy handle but who cares? */
1295 qRSIVAL(0x00000022); /* undocumented. Usually a buffer pointer whose
1298 domainname = lp_workgroup();
1299 domlen = strlen(domainname);
1300 strcpy(domsid,lp_domainsid());
1301 DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1302 /* assume, but should check, that domsid starts "S-" */
1303 p = strtok(domsid+2,"-");
1305 DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1306 identauth = atoi(strtok(0,"-"));
1307 DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1309 while (p = strtok(0, "-"))
1310 subauths[numsubauths++] = atoi(p);
1311 DEBUG(4,("netlogon LINE %d %lx\n",__LINE__, q));
1318 qSSVAL(0); /* 2 undocumented bytes */
1320 qSSVAL(domlen*2); /* unicode domain len and maxlen */
1321 qSIVAL(4); /* domain buffer pointer */
1322 qSIVAL(2); /* domain sid pointer */
1323 qunistr(domainname);
1324 qSIVAL(numsubauths);
1326 qSCVAL(numsubauths);
1327 qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1328 qRSIVAL(identauth); /* next 4 bytes */
1329 for (i = 0; i < numsubauths; i++)
1331 qSIVAL(subauths[i]);
1334 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1337 case LSAENUMTRUSTDOM:
1338 DEBUG(1,("LSAENUMTRUSTDOM\n"));
1340 qSIVAL(0); /* enumeration context */
1341 qSIVAL(0); /* entries read */
1342 qSIVAL(0); /* trust information */
1343 endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
1347 DEBUG(1,("LSACLOSE\n"));
1354 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1358 DEBUG(1,("LSAOPENSECRET\n"));
1365 endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
1369 DEBUG(1,("LSAOPENSECRET\n"));
1371 policyhandle = q; q += 20;
1373 DEBUG(4,("lookupsid entries %d\n",nentries));
1374 q += (2+nentries) * 4; /* skip bufptrs */
1375 /* now we have nentries sids of the form:
1376 uint32 Subauthority count (SAC)
1378 char Subaurity count again
1379 char[6] Identifier authority
1380 [uint32 subauthority] * SAC
1382 for (nsids = 0; nsids < nentries; nsids++)
1384 DEBUG(4,("lookupsid q in %lx\n",q));
1386 DEBUG(4,("lookupsid numsubs %d\n",IVAL(q,0)));
1387 q += 4+1+1+6+IVAL(q,0)*4;
1388 DEBUG(4,("lookupsid q %lx\n",q));
1390 /* There's 16 bytes of something after all of that, don't know
1391 what it is though - incorrectly documented */
1393 DEBUG(4,("lookupsid line %d\n",__LINE__));
1394 /* formulate reply */
1396 qSIVAL(2); /* bufptr */
1397 qSIVAL(4); /* number of referenced domains
1398 - need one per each identifier authority in call */
1399 qSIVAL(2); /* dom bufptr */
1400 qSIVAL(32); /* max entries */
1401 qSIVAL(4); /* number of reference domains? */
1403 qunihdr(lp_workgroup()); /* reference domain */
1404 qSIVAL(2); /* sid bufptr */
1407 qSIVAL(2); /* sid bufptr */
1410 qSIVAL(2); /* sid bufptr */
1413 qSIVAL(2); /* sid bufptr */
1415 qunistr(lp_workgroup());
1416 DEBUG(4,("lookupsid line %d\n",__LINE__));
1418 strcpy(domsid,lp_domainsid());
1419 p = strtok(domsid+2,"-");
1421 identauth = atoi(strtok(0,"-"));
1423 while (p = strtok(0, "-"))
1424 subauths[numsubauths++] = atoi(p);
1425 qSIVAL(numsubauths);
1427 qSCVAL(numsubauths);
1428 qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1429 qRSIVAL(identauth); /* next 4 bytes */
1430 DEBUG(4,("lookupsid line %d\n",__LINE__));
1431 for (i = 0; i < numsubauths; i++)
1433 qSIVAL(subauths[i]);
1435 DEBUG(4,("lookupsid line %d\n",__LINE__));
1438 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1439 DEBUG(4,("lookupsid line %d\n",__LINE__));
1442 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1445 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1448 qSIVAL(2); /* bufptr */
1450 DEBUG(4,("lookupsid line %d\n",__LINE__));
1451 for (i = 0; i < nentries; i++)
1453 qSSVAL(5); /* SID name use ?! */
1454 qSSVAL(0); /* undocumented */
1455 DEBUG(4,("lookupsid line %d\n",__LINE__));
1456 qunihdr(sidtostring(sids[i]));
1457 DEBUG(4,("lookupsid sidname %s\n",sidtostring(sids[i])));
1458 qSIVAL(0); /* domain index out of above reference domains */
1460 DEBUG(4,("lookupsid line %d\n",__LINE__));
1461 for (i = 0; i < nentries; i++)
1463 qunistr(sidtostring(sids[i]));
1465 qSIVAL(nentries); /* mapped count */
1466 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1469 case LSALOOKUPNAMES:
1470 DEBUG(1,("LSALOOKUPNAMES\n"));
1472 policyhandle = q; q += 20;
1474 DEBUG(4,("lookupnames entries %d\n",nentries));
1475 q += 4; /* skip second count */
1476 q += 8 * nentries; /* skip pointers */
1477 for (nnames = 0; nnames < nentries; nnames++)
1479 names[nnames] = q; /* set name string to unicode header */
1480 q += IVAL(q,0)*2; /* guessing here */
1482 /* There's a translated sids structure next but it looks fals */
1484 DEBUG(4,("lookupnames line %d\n",__LINE__));
1485 /* formulate reply */
1487 qSIVAL(2); /* bufptr */
1488 qSIVAL(4); /* number of referenced domains
1489 - need one per each identifier authority in call */
1490 qSIVAL(2); /* dom bufptr */
1491 qSIVAL(32); /* max entries */
1492 qSIVAL(4); /* number of reference domains? */
1494 qunihdr(lp_workgroup()); /* reference domain */
1495 qSIVAL(2); /* sid bufptr */
1498 qSIVAL(2); /* sid bufptr */
1501 qSIVAL(2); /* sid bufptr */
1504 qSIVAL(2); /* sid bufptr */
1506 qunistr(lp_workgroup());
1507 DEBUG(4,("lookupnames line %d\n",__LINE__));
1509 strcpy(domsid,lp_domainsid());
1510 p = strtok(domsid+2,"-");
1512 identauth = atoi(strtok(0,"-"));
1514 while (p = strtok(0, "-"))
1515 subauths[numsubauths++] = atoi(p);
1516 qSIVAL(numsubauths);
1518 qSCVAL(numsubauths);
1519 qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1520 qRSIVAL(identauth); /* next 4 bytes */
1521 DEBUG(4,("lookupsid line %d\n",__LINE__));
1522 for (i = 0; i < numsubauths; i++)
1524 qSIVAL(subauths[i]);
1526 DEBUG(4,("lookupsid line %d\n",__LINE__));
1529 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1530 DEBUG(4,("lookupsid line %d\n",__LINE__));
1533 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1536 qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1539 qSIVAL(2); /* bufptr */
1541 DEBUG(4,("lookupnames line %d\n",__LINE__));
1542 for (i = 0; i < nentries; i++)
1544 qSSVAL(5); /* SID name use 5 == well known sid, 1 == user sid see showacls */
1545 qSSVAL(5); /* undocumented */
1546 DEBUG(4,("lookupnames line %d\n",__LINE__));
1547 qSIVAL(nametorid(names[i]));
1548 DEBUG(4,("lookupnames nametorid %d\n",nametorid(names[i])));
1549 qSIVAL(0); /* domain index out of above reference domains */
1551 qSIVAL(nentries); /* mapped count */
1552 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1556 DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
1561 BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data,
1562 int mdrcnt,int mprcnt,
1563 char **rdata,char **rparam,
1564 int *rdata_len,int *rparam_len)
1573 int subauths[MAXSUBAUTHS];
1574 struct smb_passwd *smb_pass; /* To check if machine account exists */
1578 uint16 revision; /* Domain sid revision */
1584 uint16 secchanneltype;
1595 uint16 paramcontrol;
1598 uint16 usernamemaxlen;
1601 uchar *rc4lmowfpass;
1602 uchar *rc4ntowfpass;
1606 struct uinfo *userinfo;
1610 uchar ntowfpass[16];
1612 opnum = SVAL(data,22);
1614 pkttype = CVAL(data, 2);
1615 if (pkttype == 0x0b) /* RPC BIND */
1617 DEBUG(4,("netlogon rpc bind %x\n",pkttype));
1618 LsarpcTNP1(data,rdata,rdata_len);
1622 DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum));
1623 initrpcreply(data, *rdata);
1624 DEBUG(4,("netlogon LINE %d\n",__LINE__));
1628 DEBUG(1,("LSAREQCHAL\n"));
1631 logonsrv = q + 16; /* first 16 bytes, buffer ptr, + unicode lenghts */
1632 q = skip_unicode_string(logonsrv,1) + 12;
1633 q = align4(q, data);
1635 q = skip_unicode_string(unicomp,1);
1638 DEBUG(1,("logonsrv=%s unicomp=%s\n",
1642 dcauth[cnum].chal[0] = IVAL(q, 0);
1643 dcauth[cnum].chal[1] = IVAL(q, 4);
1644 dcauth[cnum].cred[0] = IVAL(q, 0); /* this looks weird (tridge) */
1645 dcauth[cnum].cred[1] = IVAL(q, 4);
1647 DEBUG(1,("NL: client challenge %08x %08x\n", dcauth[cnum].chal[0],dcauth[cnum].chal[1]));
1649 /* PAXX: set these to random values */
1650 dcauth[cnum].svrchal[0] = 0x11111111;
1651 dcauth[cnum].svrchal[1] = 0x22222222;
1652 dcauth[cnum].svrcred[0] = 0x11111111;
1653 dcauth[cnum].svrcred[1] = 0x22222222;
1654 strcpy(machacct,unistr(unicomp));
1655 strcat(machacct, "$");
1656 smb_pass = get_smbpwnam(machacct);
1658 memcpy(dcauth[cnum].md4pw, smb_pass->smb_nt_passwd, 16);
1661 /* No such machine account. Should error out here, but we'll
1662 print and carry on */
1663 DEBUG(1,("No account in domain at REQCHAL for %s\n", machacct));
1665 for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",dcauth[cnum].md4pw[i]);
1666 DEBUG(1,("pass %s %s\n", machacct, foo));
1669 qSIVAL(dcauth[cnum].svrchal[0]);
1670 qSIVAL(dcauth[cnum].svrchal[1]);
1672 DEBUG(1,("NL: server challenge %08x %08x\n",
1673 dcauth[cnum].svrchal[0],dcauth[cnum].svrchal[1]));
1675 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1679 DEBUG(1,("LSAAUTH2\n"));
1683 q = skip_unicode_string(logonsrv,1)+12;
1684 q = align4(q, data);
1687 q = skip_unicode_string(accountname,1);
1688 secchanneltype = qSVAL;
1690 q = align4(q, data);
1692 dump_data(1,unicomp,32);
1693 q = skip_unicode_string(unicomp,1);
1696 q = align4(q, data);
1698 DEBUG(3,("AUTH2 logonsrv=%s accountname=%s unicomp=%s %lx %lx %lx\n",
1699 unistr(logonsrv), unistr(accountname), unistr(unicomp),
1700 rcvcred[0], rcvcred[1], negflags));
1702 DEBUG(1,("NL: recvcred %08x %08x negflags=%08x\n",
1703 rcvcred[0], rcvcred[1], negflags));
1705 checkcred(cnum, rcvcred[0], rcvcred[1], 0);
1707 makecred(cnum, 0, q);
1711 /* update stored client credentials */
1712 dcauth[cnum].cred[0] = dcauth[cnum].svrcred[0] = rcvcred[0];
1713 dcauth[cnum].cred[1] = dcauth[cnum].svrcred[1] = rcvcred[1];
1714 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1718 DEBUG(1,("LSASVRPWSET\n"));
1722 q = skip_unicode_string(logonsrv,1)+12;
1723 q = align4(q, data);
1725 q = skip_unicode_string(accountname,1);
1726 secchanneltype = qSVAL;
1728 q = align4(q, data);
1730 q = skip_unicode_string(unicomp,1);
1735 DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s\n",
1736 unistr(logonsrv), unistr(accountname), unistr(unicomp)));
1738 checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1739 DEBUG(3,("PWSET %lx %lx %lx %lx\n", rcvcred[0], rcvcred[1], clnttime, negflags));
1742 DEBUG(1,("PWSET logonsrv=%s accountname=%s unicomp=%s newpass=%s\n",
1743 unistr(logonsrv), unistr(accountname), unistr(unicomp), newpass));
1745 /* PAXX: For the moment we'll reject these */
1746 /* TODO Need to set newpass in smbpasswd file for accountname */
1748 makecred(cnum, clnttime+1, q);
1750 qSIVAL(0); /* timestamp. Seems to be ignored */
1752 dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1754 endrpcreply(data, *rdata, q-*rdata, 0xc000006a, rdata_len);
1758 DEBUG(1,("LSASAMLOGON\n"));
1759 dump_data(1,data,128);
1762 DEBUG(1,("SMLOG %d\n", __LINE__));
1763 q = skip_unicode_string(logonsrv,1)+16;
1764 q = align4(q, data);
1766 q = skip_unicode_string(unicomp,1)+4;
1767 DEBUG(1,("SMLOG %d logonsrv=%s unicomp=%s\n",
1768 __LINE__, unistr(logonsrv), unistr(unicomp)));
1769 q = align4(q, data);
1771 DEBUG(1,("SMLOG %d\n", __LINE__));
1773 DEBUG(1,("SMLOG %d\n", __LINE__));
1775 checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1777 rtncred[0] = qIVAL; /* all these are ignored */
1778 DEBUG(1,("SMLOG %d\n", __LINE__));
1782 DEBUG(1,("SMLOG %d\n", __LINE__));
1790 dommaxlen = qSVAL; q += 4;
1791 paramcontrol = qIVAL;
1792 logonid[0] = qIVAL; /* low part */
1793 logonid[1] = qIVAL; /* high part */
1795 usernamelen = qSVAL;
1797 DEBUG(1,("SMLOG %d\n", __LINE__));
1798 usernamemaxlen = qSVAL; q += 4;
1800 DEBUG(1,("usernamelen=%d maxlen=%d dommaxlen=%d\n",
1801 usernamelen, usernamemaxlen, dommaxlen));
1806 wsmaxlen = qSVAL; q += 4;
1807 rc4lmowfpass = q; q += 16;
1808 rc4ntowfpass = q; q += 16;
1810 q += 12; domain = q; q += dommaxlen + 12;
1811 q = align4(q, data);
1812 username = q; q += usernamemaxlen + 12;
1813 q = align4(q, data);
1815 DEBUG(1,("domain=%s username=%s ws=%s\n",
1816 unistr(domain), unistr(username),
1820 DEBUG(0,("unknown switch in SAMLOGON %d\n",
1823 for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",username[i]);
1824 DEBUG(1,("userNAME %s [%s]\n", foo, username));
1825 DEBUG(1,("SMLOG %d\n", __LINE__));
1827 qSIVAL(0x16a4b4); /* magic buffer pointer ? */
1828 makecred(cnum, clnttime+1, q);
1829 dcauth[cnum].svrcred[0] = dcauth[cnum].cred[0] = dcauth[cnum].cred[0] + clnttime + 1;
1831 qSIVAL(0); /* timestamp. client doesn't care */
1832 qSSVAL(3); /* switch value 3. May be others? */
1833 qSSVAL(0); /* undocumented */
1834 DEBUG(1,("SMLOG %d\n", __LINE__));
1836 memset(rc4key, 0, sizeof rc4key);
1837 SIVAL(rc4key, 0, dcauth[cnum].sesskey[0]);
1838 SIVAL(rc4key, 4, dcauth[cnum].sesskey[1]);
1839 for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",rc4ntowfpass[i]);
1840 DEBUG(1,("rc4ntowf %s\n", foo));
1841 arcfour_init(&c, rc4key, sizeof rc4key);
1842 arcfour_encrypt(&c, ntowfpass, rc4ntowfpass, sizeof ntowfpass);
1843 for(i=0;i<16;i++) sprintf(foo+i*2,"%02x",ntowfpass[i]);
1844 DEBUG(1,("ntowf %s\n", foo));
1846 if(!(userinfo = getuserinfo(username, usernamelen, ntowfpass))) {
1847 qSIVAL(0); /* no buffer */
1848 qSCVAL(1); /* Authoratitive. Change if passthrough? */
1849 qSCVAL(0); /* pad for above boolean */
1850 qSSVAL(0); /* pad for above boolean */
1852 endrpcreply(data, *rdata, q-*rdata, 0xc0000064, rdata_len);
1856 qSIVAL(2); /* another magic bufptr? */
1857 DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo));
1858 qSIVAL(userinfo->logontime[0]); qSIVAL(userinfo->logontime[1]);
1859 qSIVAL(userinfo->logofftime[0]); qSIVAL(userinfo->logofftime[1]);
1860 DEBUG(1,("SMLOG %d %lx\n", __LINE__, userinfo->passlastsettime[1]));
1861 qSIVAL(userinfo->kickofftime[0]); qSIVAL(userinfo->kickofftime[1]);
1862 qSIVAL(userinfo->passlastsettime[0]); qSIVAL(userinfo->passlastsettime[1]);
1863 qSIVAL(userinfo->passcanchgtime[0]); qSIVAL(userinfo->passcanchgtime[1]);
1864 qSIVAL(userinfo->passmustchgtime[0]); qSIVAL(userinfo->passmustchgtime[1]);
1865 DEBUG(1,("SMLOG %d %s\n", __LINE__, userinfo->effectivename));
1866 qunihdr(userinfo->effectivename);
1867 qunihdr(userinfo->fullname);
1868 DEBUG(1,("SMLOG %d\n", __LINE__));
1869 qunihdr(userinfo->logonscript);
1870 qunihdr(userinfo->profilepath);
1871 qunihdr(userinfo->homedirectory);
1872 qunihdr(userinfo->homedirectorydrive);
1873 DEBUG(1,("SMLOG %d\n", __LINE__));
1874 qSSVAL(userinfo->logoncount);
1875 qSSVAL(userinfo->badpwcount);
1876 qSIVAL(userinfo->uid);
1877 qSIVAL(userinfo->gid);
1878 DEBUG(1,("SMLOG %d\n", __LINE__));
1879 qSIVAL(userinfo->ngroups);
1880 qSIVAL(8); /* ptr to groups */
1881 qSIVAL(userinfo->userflags);
1882 DEBUG(1,("SMLOG %d\n", __LINE__));
1883 qSIVAL(0); qSIVAL(0); qSIVAL(0); qSIVAL(0); /* unused user session key */
1884 qunihdr(userinfo->logonserver);
1885 qunihdr(userinfo->logondomain);
1886 DEBUG(1,("SMLOG %d\n", __LINE__));
1887 qSIVAL(2); /* logon domain id ptr */
1888 DEBUG(1,("SMLOG %d\n", __LINE__));
1889 memset(q,0,40); q += 40; /* expansion room */
1890 DEBUG(1,("SMLOG %d\n", __LINE__));
1891 qSIVAL(userinfo->nsids);
1892 DEBUG(1,("SMLOG %d\n", __LINE__));
1893 qSIVAL(0); /* ptr to sids and values */
1894 DEBUG(1,("SMLOG %d\n", __LINE__));
1895 qunistr(userinfo->effectivename);
1896 DEBUG(1,("SMLOG %d\n", __LINE__));
1897 qunistr(userinfo->fullname);
1898 DEBUG(1,("SMLOG %d\n", __LINE__));
1899 qunistr(userinfo->logonscript);
1900 DEBUG(1,("SMLOG %d\n", __LINE__));
1901 qunistr(userinfo->profilepath);
1902 qunistr(userinfo->homedirectory);
1903 qunistr(userinfo->homedirectorydrive);
1904 DEBUG(1,("SMLOG %d\n", __LINE__));
1905 qSIVAL(userinfo->ngroups);
1906 for (i = 0; i < userinfo->ngroups; i++)
1908 qSIVAL(userinfo->groups[i].gid);
1909 qSIVAL(userinfo->groups[i].attr);
1911 qunistr(userinfo->logonserver);
1912 qunistr(userinfo->logondomain);
1913 for (i = 0; i < userinfo->nsids; i++)
1915 /* put the extra sids: PAXX: TODO */
1917 /* Assumption. This is the only domain, sending our SID */
1918 /* PAXX: may want to do passthrough later */
1919 strcpy(domsid,lp_domainsid());
1920 DEBUG(4,("netlogon LINE %d %lx %s\n",__LINE__, q, domsid));
1921 /* assume, but should check, that domsid starts "S-" */
1922 p = strtok(domsid+2,"-");
1924 DEBUG(4,("netlogon LINE %d %lx %s rev %d\n",__LINE__, q, p, revision));
1925 identauth = atoi(strtok(0,"-"));
1926 DEBUG(4,("netlogon LINE %d %lx %s ia %d\n",__LINE__, q, p, identauth));
1928 while (p = strtok(0, "-"))
1929 subauths[numsubauths++] = atoi(p);
1930 qSIVAL(numsubauths);
1932 qSCVAL(numsubauths);
1933 qRSSVAL(0); /* PAXX: FIX. first 2 bytes identifier authority */
1934 qRSIVAL(identauth); /* next 4 bytes */
1935 DEBUG(1,("SMLOG %d\n", __LINE__));
1936 for (i = 0; i < numsubauths; i++)
1938 qSIVAL(subauths[i]);
1940 qSCVAL(1); /* Authoratitive. Change if passthrough? */
1941 qSCVAL(0); /* pad for above boolean */
1942 qSSVAL(0); /* pad for above boolean */
1944 endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1948 DEBUG(1,("LSASAMLOGOFF\n"));
1951 DEBUG(1,("SAMLOGOFF %d\n", __LINE__));
1952 unicomp = skip_unicode_string(logonsrv,1)+16;
1953 if (strlen(unistr(logonsrv)) % 2 == 0)
1955 DEBUG(1,("SMLOG %d\n", __LINE__));
1956 q = skip_unicode_string(unicomp,1)+4;
1957 if (strlen(unistr(unicomp)) % 2 == 0)
1959 DEBUG(1,("SMLOG %d\n", __LINE__));
1961 DEBUG(1,("SMLOG %d\n", __LINE__));
1963 DEBUG(1,("SMLOG %d\n", __LINE__));
1965 checkcred(cnum, rcvcred[0], rcvcred[1], clnttime);
1967 rtncred[0] = qIVAL; /* all these are ignored */
1968 DEBUG(1,("SMLOG %d\n", __LINE__));
1972 DEBUG(1,("SMLOG %d\n", __LINE__));
1979 dommaxlen = qSVAL; q += 4;
1980 paramcontrol = qIVAL;
1981 logonid[0] = qIVAL; /* low part */
1982 logonid[1] = qIVAL; /* high part */
1983 usernamelen = qSVAL;
1984 DEBUG(1,("SMLOG %d\n", __LINE__));
1985 usernamemaxlen = qSVAL; q += 4;
1987 wsmaxlen = qSVAL; q += 4;
1988 rc4lmowfpass = q; q += 16;
1989 rc4ntowfpass = q; q += 16;
1990 q += 12; domain = q; q += dommaxlen + 12;
1991 if ((domlen/2) % 2 != 0) q += 2;
1992 username = q; q += usernamemaxlen + 12; /* PAXX: HACK */
1993 if ((usernamelen/2) % 2 != 0) q += 2;
1996 default: DEBUG(0, ("unknown switch in SAMLOGON %d\n",switchval));
1998 DEBUG(1,("SAMLOGOFF %s\n", unistr(username)));
2000 DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum));
2005 static void checkcred(int cnum, uint32 cred0, uint32 cred1, uint32 time)
2014 SIVAL(netdata, 0, dcauth[cnum].cred[0]+time);
2015 SIVAL(netdata, 4, dcauth[cnum].cred[1]);
2016 SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]);
2017 SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]);
2018 E1(netsesskey,netdata,icv);
2019 memset(key2, 0, sizeof key2);
2020 key2[0] = netsesskey[7];
2021 E1(key2, icv, calccred);
2022 if (IVAL(calccred,0) != cred0 ||
2023 IVAL(calccred,4) != cred1)
2025 DEBUG(1,("Incorrect client credential received cred %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n",
2027 dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2028 dcauth[cnum].cred[0], dcauth[cnum].cred[1],
2029 IVAL(calccred,0), IVAL(calccred,4)));
2030 /* PAXX: do something about it! */
2032 DEBUG(4,("Correct client credential received chal %lx %lx time %lx sk %lx %lx cred %lx %lx expcred %lx %lx\n",
2034 dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2035 dcauth[cnum].cred[0], dcauth[cnum].cred[1],
2036 IVAL(calccred,0), IVAL(calccred,4)));
2039 static void makecred(int cnum, uint32 time, char *calccred)
2047 SIVAL(netdata, 0, dcauth[cnum].svrcred[0]+time);
2048 SIVAL(netdata, 4, dcauth[cnum].svrcred[1]);
2049 SIVAL(netsesskey, 0, dcauth[cnum].sesskey[0]);
2050 SIVAL(netsesskey, 4, dcauth[cnum].sesskey[1]);
2051 E1(netsesskey,netdata,icv);
2052 memset(key2, 0, sizeof key2);
2053 key2[0] = netsesskey[7];
2054 E1(key2, icv, calccred);
2055 DEBUG(4,("Server credential: chal %lx %lx sk %lx %lx cred %lx %lx calc %lx %lx\n",
2056 dcauth[cnum].svrchal[0], dcauth[cnum].svrchal[1],
2057 dcauth[cnum].sesskey[0], dcauth[cnum].sesskey[1],
2058 dcauth[cnum].svrcred[0], dcauth[cnum].svrcred[1],
2059 IVAL(calccred, 0), IVAL(calccred, 4)));
2062 static void setsesskey(int cnum)
2069 sum[0] = dcauth[cnum].chal[0] + dcauth[cnum].svrchal[0];
2070 sum[1] = dcauth[cnum].chal[1] + dcauth[cnum].svrchal[1];
2071 SIVAL(netsum,0,sum[0]);
2072 SIVAL(netsum,4,sum[1]);
2073 E1(dcauth[cnum].md4pw,netsum,icv);
2074 E1(dcauth[cnum].md4pw+9,icv,netsesskey);
2075 dcauth[cnum].sesskey[0] = IVAL(netsesskey,0);
2076 dcauth[cnum].sesskey[1] = IVAL(netsesskey,4);
2078 DEBUG(1,("NL: session key %08x %08x\n",
2079 dcauth[cnum].sesskey[0],
2080 dcauth[cnum].sesskey[1]));
2083 static struct uinfo *getuserinfo(char *user, int len, char *ntowfpass)
2085 static struct uinfo u;
2086 static pstring fullnm;
2087 static pstring ascuser;
2088 extern pstring myname;
2089 static pstring stme;
2090 static pstring stdom;
2091 struct smb_passwd *smb_pass;
2093 strcpy(ascuser,unistr(user));
2094 ascuser[len/2] = 0; /* PAXX: FIXMEFIXMEFIXME */
2095 DEBUG(1,("GETUSER username :%s: len=%d\n",ascuser, len));
2097 smb_pass = get_smbpwnam(ascuser);
2100 DEBUG(1,("GETU %d\n", __LINE__));
2101 if (memcmp(ntowfpass, smb_pass->smb_nt_passwd, 16)) {
2102 DEBUG(1,("pass mismatch:\n"));
2103 dump_data(1,ntowfpass,16);
2104 dump_data(1,smb_pass->smb_nt_passwd,16);
2108 DEBUG(1,("GETU %d\n", __LINE__));
2109 u.logontime[0] = 0xffffffff; u.logontime[1] = 0x7fffffff;
2110 u.logofftime[0] = 0xffffffff; u.logofftime[1] = 0x7fffffff;
2111 u.kickofftime[0] = 0xffffffff; u.kickofftime[1] = 0x7fffffff;
2112 DEBUG(1,("GETU %d\n", __LINE__));
2113 u.passlastsettime[0] = 0xffffffff; u.passlastsettime[1] = 0x7fffffff;
2114 u.passcanchgtime[0] = 0xffffffff; u.passcanchgtime[1] = 0x7fffffff;
2115 u.passmustchgtime[0] = 0xffffffff; u.passmustchgtime[1] = 0x7fffffff;
2116 DEBUG(1,("GETU %d\n", __LINE__));
2117 u.effectivename = ascuser;
2118 strcpy(fullnm, "Full name of ");
2119 strcat(fullnm, ascuser);
2120 DEBUG(1,("GETU %d\n", __LINE__));
2121 u.fullname = fullnm;
2122 u.logonscript = "foologin.cmd";
2123 u.profilepath = "prof";
2124 u.homedirectory = "foohomes";
2125 DEBUG(1,("GETU %d\n", __LINE__));
2126 u.homedirectorydrive = "a:";
2130 DEBUG(1,("GETU %d\n", __LINE__));
2133 u.groups = (struct groupinfo *)(malloc(sizeof (struct groupinfo) * 2));
2134 u.groups[0].gid = 776;
2135 DEBUG(1,("GETU %d\n", __LINE__));
2136 u.groups[0].attr = 0x7;
2137 u.groups[1].gid = 776;
2138 u.groups[1].attr = 0x7;
2140 u.logonserver = stme;
2141 get_myname(myname,NULL);
2142 strcpy(stme, myname);
2144 DEBUG(1,("LS %s\n", u.logonserver));
2145 u.logondomain = stdom;
2146 strcpy(stdom, lp_workgroup());
2148 DEBUG(1,("DOM %s\n", u.logondomain));
2151 DEBUG(1,("GETU %d\n", __LINE__));
2156 #endif /* NTDOMAIN */
2157 /* space in front of this function so that make proto doesn't pick it up */
2158 void _dummy_function(void)
2161 lsa_reply_req_chal(NULL, NULL, NULL, NULL);
2162 lsa_reply_auth_2(NULL, NULL, NULL, NULL, 0);
2163 lsa_reply_srv_pwset(NULL, NULL, NULL, NULL, t, 0);
2164 make_lsa_user_info(NULL,
2165 NULL, NULL, NULL, NULL, NULL, NULL,
2166 NULL, NULL, NULL, NULL, NULL, NULL,
2172 lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL);
2173 lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0);