credentials.c:
[kai/samba.git] / source3 / smbd / pipes.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Pipe SMB reply routines
5    Copyright (C) Andrew Tridgell 1992-1997,
6                  Paul Ashton  1997,
7                  Luke Kenneth Casson Leighton 1996-1997.
8    
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.
13    
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.
18    
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.
22 */
23 /*
24    This file handles reply_ calls on named pipes that the server
25    makes to handle specific protocols
26 */
27
28
29 #include "includes.h"
30 #include "trans2.h"
31 #include "nterr.h"
32
33 #define PIPE            "\\PIPE\\"
34 #define PIPELEN         strlen(PIPE)
35
36 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
37
38 /* look in server.c for some explanation of these variables */
39 extern int Protocol;
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;
47 extern int Client;
48 extern fstring myworkgroup;
49
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))
53
54 char * known_pipes [] =
55 {
56   "lsarpc",
57 #if 0
58   "NETLOGON",
59 #endif
60   NULL
61 };
62
63 /****************************************************************************
64   reply to an open and X on a named pipe
65
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...).
71
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)
76 {
77   pstring fname;
78   int cnum = SVAL(inbuf,smb_tid);
79   int fnum = -1;
80   int smb_mode = SVAL(inbuf,smb_vwv3);
81   int smb_attr = SVAL(inbuf,smb_vwv5);
82 #if 0
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);
86 #endif
87   int smb_ofun = SVAL(inbuf,smb_vwv8);
88   int unixmode;
89   int size=0,fmode=0,mtime=0,rmode=0;
90   struct stat sbuf;
91   int smb_action = 0;
92   int i;
93   BOOL bad_path = False;
94
95   /* XXXX we need to handle passed times, sattr and flags */
96   pstrcpy(fname,smb_buf(inbuf));
97
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));
103
104   DEBUG(4,("Opening pipe %s.\n", fname));
105
106   /* Strip \PIPE\ off the name. */
107   pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
108
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 )
112       break;
113
114   if ( known_pipes[i] == NULL )
115     return(ERROR(ERRSRV,ERRaccess));
116
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));
120   smb_attr &= ~aDIR;
121   Connections[cnum].read_only = 0;
122   smb_ofun |= 0x10;             /* Add Create it not exists flag */
123
124   unix_convert(fname,cnum,0,&bad_path);
125     
126   fnum = find_free_file();
127   if (fnum < 0)
128     return(ERROR(ERRSRV,ERRnofids));
129
130   if (!check_name(fname,cnum))
131     return(UNIXERROR(ERRDOS,ERRnoaccess));
132
133   unixmode = unix_mode(cnum,smb_attr);
134       
135   open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
136                    0, &rmode,&smb_action);
137       
138   if (!Files[fnum].open)
139   {
140     /* Change the error code if bad_path was set. */
141     if((errno == ENOENT) && bad_path)
142     {
143       unix_ERR_class = ERRDOS;
144       unix_ERR_code = ERRbadpath;
145     }
146     return(UNIXERROR(ERRDOS,ERRnoaccess));
147   }
148
149   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
150     close_file(fnum);
151     return(ERROR(ERRDOS,ERRnoaccess));
152   }
153
154   size = sbuf.st_size;
155   fmode = dos_mode(cnum,fname,&sbuf);
156   mtime = sbuf.st_mtime;
157   if (fmode & aDIR) {
158     close_file(fnum);
159     return(ERROR(ERRDOS,ERRnoaccess));
160   }
161
162   /* Prepare the reply */
163   set_message(outbuf,15,0,True);
164
165   /* Put things back the way they were. */
166   Connections[cnum].read_only = 1;
167
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);
171   if (rmode == 2)
172   {
173     DEBUG(4,("Resetting open result to open from create.\n"));
174     rmode = 1;
175   }
176
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);
183
184   chain_fnum = fnum;
185
186   DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
187            fname, fnum, Files[fnum].name));
188   
189   return chain_reply(inbuf,outbuf,length,bufsize);
190 }
191
192
193 /****************************************************************************
194  api_LsarpcSNPHS
195
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
199  named pipe handling.
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)
205 {
206   uint16 id;
207
208   id = param[0] + (param[1] << 8);
209   DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
210   return(True);
211 }
212
213
214 /****************************************************************************
215  api_LsarpcTNP
216
217  TransactNamedPipe on \PIPE\lsarpc.
218 ****************************************************************************/
219 static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
220 {
221   uint32 dword1, dword2;
222   char pname[] = "\\PIPE\\lsass";
223
224   /* All kinds of mysterious numbers here */
225   *rdata_len = 68;
226   *rdata = REALLOC(*rdata,*rdata_len);
227
228   dword1 = IVAL(data,0xC);
229   dword2 = IVAL(data,0x10);
230
231   SIVAL(*rdata,0,0xc0005);
232   SIVAL(*rdata,4,0x10);
233   SIVAL(*rdata,8,0x44);
234   SIVAL(*rdata,0xC,dword1);
235   
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);
242 }
243
244 static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
245 {
246   uint32 dword1;
247
248   /* All kinds of mysterious numbers here */
249   *rdata_len = 48;
250   *rdata = REALLOC(*rdata,*rdata_len);
251
252   dword1 = IVAL(data,0xC);
253
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);
263 }
264
265 static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
266 {
267   uint32 dword1;
268   uint16 word1;
269   char * workgroup = myworkgroup;
270   int wglen = strlen(workgroup);
271   int i;
272
273   /* All kinds of mysterious numbers here */
274   *rdata_len = 90 + 2 * wglen;
275   *rdata = REALLOC(*rdata,*rdata_len);
276
277   dword1 = IVAL(data,0xC);
278   word1 = SVAL(data,0x2C);
279
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];
298    
299   /* Now fill in the rest */
300   i = 0x38 + wglen * 2;
301   SSVAL(*rdata,i,0x648);
302   SIVAL(*rdata,i+2,4);
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);
309 }
310
311 static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
312 {
313   uint32 dword1;
314
315   /* All kinds of mysterious numbers here */
316   *rdata_len = 48;
317   *rdata = REALLOC(*rdata,*rdata_len);
318
319   dword1 = IVAL(data,0xC);
320
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);
326 }
327
328
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)
333 {
334   uint32 id,id2;
335
336   id = IVAL(data,0);
337
338   DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
339   switch (id)
340   {
341     case 0xb0005:
342       LsarpcTNP1(data,rdata,rdata_len);
343       break;
344
345     case 0x03000005:
346       id2 = IVAL(data,8);
347       DEBUG(4,("\t- Suboperation %lx\n",id2));
348       switch (id2 & 0xF)
349       {
350         case 8:
351           LsarpcTNP2(data,rdata,rdata_len);
352           break;
353
354         case 0xC:
355           LsarpcTNP4(data,rdata,rdata_len);
356           break;
357
358         case 0xE:
359           LsarpcTNP3(data,rdata,rdata_len);
360           break;
361       }
362       break;
363   }
364   return(True);
365 }
366
367 /*
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 :-)
371 */
372
373 /* RID username mapping function.  just for fun, it maps to the unix uid */
374 static uint32 name_to_rid(char *user_name)
375 {
376     struct passwd *pw = Get_Pwnam(user_name, False);
377     if (!pw)
378         {
379       DEBUG(1,("Username %s is invalid on this system\n", user_name));
380       return (uint32)(-1);
381     }
382
383     return (uint32)(pw->pw_uid);
384 }
385
386
387 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
388 char *dom_sid_to_string(DOM_SID *sid)
389 {
390   static pstring sidstr;
391   char subauth[16];
392   int i;
393   uint32 ia = (sid->id_auth[0]) +
394               (sid->id_auth[1] << 8 ) +
395               (sid->id_auth[2] << 16) +
396               (sid->id_auth[3] << 24);
397
398   sprintf(sidstr, "S-%d-%d", sid->sid_no, ia);
399
400   for (i = 0; i < sid->num_auths; i++)
401   {
402     sprintf(subauth, "-%d", sid->sub_auths[i]);
403     strcat(sidstr, subauth);
404   }
405
406   DEBUG(5,("dom_sid_to_string returning %s\n", sidstr));
407   return sidstr;
408 }
409
410 /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
411 /* identauth >= 2^32 can be detected because it will be specified in hex */
412 static void make_dom_sid(DOM_SID *sid, char *domsid)
413 {
414         int identauth;
415         char *p;
416
417         DEBUG(4,("netlogon domain SID: %s\n", domsid));
418
419         /* assume, but should check, that domsid starts "S-" */
420         p = strtok(domsid+2,"-");
421         sid->sid_no = atoi(p);
422
423         /* identauth in decimal should be <  2^32 */
424         /* identauth in hex     should be >= 2^32 */
425         identauth = atoi(strtok(0,"-"));
426
427         DEBUG(4,("netlogon rev %d\n", sid->sid_no));
428         DEBUG(4,("netlogon %s ia %d\n", p, identauth));
429
430         sid->id_auth[0] = 0;
431         sid->id_auth[1] = 0;
432         sid->id_auth[2] = (identauth & 0xff000000) >> 24;
433         sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
434         sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
435         sid->id_auth[5] = (identauth & 0x000000ff);
436
437         sid->num_auths = 0;
438
439         while ((p = strtok(0, "-")) != NULL)
440         {
441                 sid->sub_auths[sid->num_auths++] = atoi(p);
442         }
443 }
444
445 static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
446 {
447         if (hdr == NULL) return;
448
449         hdr->major        = 5;               /* RPC version 5 */
450         hdr->minor        = 0;               /* minor version 0 */
451         hdr->pkt_type     = 2;               /* RPC response packet */
452         hdr->frag         = 3;               /* first frag + last frag */
453         hdr->pack_type    = 1;               /* packed data representation */
454         hdr->frag_len     = data_len;        /* fragment length, fill in later */
455         hdr->auth_len     = 0;               /* authentication length */
456         hdr->call_id      = call_id;         /* call identifier - match incoming RPC */
457         hdr->alloc_hint   = data_len - 0x18; /* allocation hint (no idea) */
458         hdr->context_id   = 0;               /* presentation context identifier */
459         hdr->cancel_count = 0;               /* cancel count */
460         hdr->reserved     = 0;               /* reserved */
461 }
462
463 static void make_rpc_reply(char *inbuf, char *q, int data_len)
464 {
465         uint32 callid = RIVAL(inbuf, 12);
466         RPC_HDR hdr;
467
468         create_rpc_reply(&hdr, callid, data_len);
469         smb_io_rpc_hdr(False, &hdr, q, q, 4);
470 }
471
472 static int lsa_reply_open_policy(char *q, char *base)
473 {
474         char *start = q;
475         LSA_R_OPEN_POL r_o;
476
477         /* set up the LSA QUERY INFO response */
478         bzero(&(r_o.pol.data), POL_HND_SIZE);
479         r_o.status = 0x0;
480
481         /* store the response in the SMB stream */
482         q = lsa_io_r_open_pol(False, &r_o, q, base, 4);
483
484         /* return length of SMB data stored */
485         return q - start; 
486 }
487
488 static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
489 {
490         hdr->uni_max_len = max_len;
491         hdr->uni_str_len = len;
492         hdr->undoc       = terminate;
493 }
494
495 static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
496 {
497         make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
498         hdr->undoc_buffer = len > 0 ? 1 : 0;
499 }
500
501 static void make_unistr(UNISTR *str, char *buf)
502 {
503         /* store the string (null-terminated copy) */
504         PutUniCode((char *)(str->buffer), buf);
505 }
506
507 static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
508 {
509         /* set up string lengths. add one if string is not null-terminated */
510         str->uni_max_len = len + (terminate != 0 ? 1 : 0);
511         str->undoc       = 0;
512         str->uni_str_len = len;
513
514         /* store the string (null-terminated copy) */
515         PutUniCode((char *)str->buffer, buf);
516
517         /* overwrite the last character: some strings are terminated with 4 not 0 */
518         str->buffer[len] = (uint16)terminate;
519 }
520
521 static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid)
522 {
523         rid2->type    = 0x5;
524         rid2->undoc   = 0x5;
525         rid2->rid     = rid;
526         rid2->rid_idx = 0;
527 }
528
529 static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str)
530 {
531         int len_sid_str = strlen(sid_str);
532
533         sid2->type = 0x5;
534         sid2->undoc = 0;
535         make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0);
536         make_unistr  (&(sid2->str), sid_str);
537 }
538
539 static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
540 {
541         int domlen = strlen(dom_name);
542
543         d_q->uni_dom_max_len = domlen * 2;
544         d_q->padding = 0;
545         d_q->uni_dom_str_len = domlen * 2;
546
547         d_q->buffer_dom_name = 0; /* domain buffer pointer */
548         d_q->buffer_dom_sid  = 0; /* domain sid pointer */
549
550         /* NOT null-terminated: 4-terminated instead! */
551         make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
552
553         make_dom_sid(&(d_q->dom_sid), dom_sid);
554 }
555
556 static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
557                                 char *dom_name, char *dom_sid)
558 {
559         char *start = q;
560         LSA_R_QUERY_INFO r_q;
561
562         /* set up the LSA QUERY INFO response */
563
564         r_q.undoc_buffer = 1; /* not null */
565         r_q.info_class = q_q->info_class;
566
567         make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
568
569         r_q.status = 0x0;
570
571         /* store the response in the SMB stream */
572         q = lsa_io_r_query(False, &r_q, q, base, 4);
573
574         /* return length of SMB data stored */
575         return q - start; 
576 }
577
578 /* pretty much hard-coded choice of "other" sids, unfortunately... */
579 static void make_dom_ref(DOM_R_REF *ref,
580                                 char *dom_name, char *dom_sid,
581                                 char *other_sid1, char *other_sid2, char *other_sid3)
582 {
583         int len_dom_name   = strlen(dom_name);
584         int len_other_sid1 = strlen(other_sid1);
585         int len_other_sid2 = strlen(other_sid2);
586         int len_other_sid3 = strlen(other_sid3);
587
588         ref->undoc_buffer = 1;
589         ref->num_ref_doms_1 = 4;
590         ref->buffer_dom_name = 1;
591         ref->max_entries = 32;
592         ref->num_ref_doms_2 = 4;
593
594         make_uni_hdr2(&(ref->hdr_dom_name  ), len_dom_name  , len_dom_name  , 0);
595         make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
596         make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
597         make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
598
599         if (dom_name != NULL)
600         {
601                 make_unistr(&(ref->uni_dom_name), dom_name);
602         }
603
604         make_dom_sid(&(ref->ref_dom[0]), dom_sid   );
605         make_dom_sid(&(ref->ref_dom[1]), other_sid1);
606         make_dom_sid(&(ref->ref_dom[2]), other_sid2);
607         make_dom_sid(&(ref->ref_dom[3]), other_sid3);
608 }
609
610 static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
611                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
612                                 char *dom_name, char *dom_sid,
613                                 char *other_sid1, char *other_sid2, char *other_sid3)
614 {
615         int i;
616
617         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
618                      other_sid1, other_sid2, other_sid3);
619
620         r_l->num_entries = num_entries;
621         r_l->undoc_buffer = 1;
622         r_l->num_entries2 = num_entries;
623
624         for (i = 0; i < num_entries; i++)
625         {
626                 make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
627         }
628
629         r_l->num_entries3 = num_entries;
630 }
631
632 static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
633                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
634                                 char *dom_name, char *dom_sid,
635                                 char *other_sid1, char *other_sid2, char *other_sid3)
636 {
637         int i;
638
639         make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
640                      other_sid1, other_sid2, other_sid3);
641
642         r_l->num_entries = num_entries;
643         r_l->undoc_buffer = 1;
644         r_l->num_entries2 = num_entries;
645
646         for (i = 0; i < num_entries; i++)
647         {
648                 make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
649         }
650
651         r_l->num_entries3 = num_entries;
652 }
653
654 static int lsa_reply_lookup_sids(char *q, char *base,
655                                 int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
656                                 char *dom_name, char *dom_sid,
657                                 char *other_sid1, char *other_sid2, char *other_sid3)
658 {
659         char *start = q;
660         LSA_R_LOOKUP_SIDS r_l;
661
662         /* set up the LSA Lookup SIDs response */
663         make_reply_lookup_sids(&r_l, num_entries, dom_sids,
664                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
665         r_l.status = 0x0;
666
667         /* store the response in the SMB stream */
668         q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4);
669
670         /* return length of SMB data stored */
671         return q - start; 
672 }
673
674 static int lsa_reply_lookup_rids(char *q, char *base,
675                                 int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
676                                 char *dom_name, char *dom_sid,
677                                 char *other_sid1, char *other_sid2, char *other_sid3)
678 {
679         char *start = q;
680         LSA_R_LOOKUP_RIDS r_l;
681
682         /* set up the LSA Lookup RIDs response */
683         make_reply_lookup_rids(&r_l, num_entries, dom_rids,
684                                 dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
685         r_l.status = 0x0;
686
687         /* store the response in the SMB stream */
688         q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4);
689
690         /* return length of SMB data stored */
691         return q - start; 
692 }
693
694 static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status)
695 {
696         memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data));
697         r_c->status = status;
698 }
699
700 #if 0
701         char chal[8];
702         /* PAXX: set these to random values */
703         for (int i = 0; i < 8; i+++)
704         {
705                 chal[i] = 0xA5;
706         }
707 #endif
708
709 static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
710                                         char chal[8])
711 {
712         char *start = q;
713         LSA_R_REQ_CHAL r_c;
714
715         /* set up the LSA REQUEST CHALLENGE response */
716
717         make_lsa_r_req_chal(&r_c, chal, 0);
718
719         /* store the response in the SMB stream */
720         q = lsa_io_r_req_chal(False, &r_c, q, base, 4);
721
722         /* return length of SMB data stored */
723         return q - start; 
724 }
725
726 static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8])
727 {
728         memcpy(cred->data, resp_cred, sizeof(cred->data));
729 }
730
731 static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
732                               char resp_cred[8], NEG_FLAGS *flgs, int status)
733 {
734         make_lsa_chal(&(r_a->srv_chal), resp_cred);
735         memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs));
736         r_a->status = status;
737 }
738
739 static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
740                                 char resp_cred[8], int status)
741 {
742         char *start = q;
743         LSA_R_AUTH_2 r_a;
744
745         /* set up the LSA AUTH 2 response */
746
747         make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
748
749         /* store the response in the SMB stream */
750         q = lsa_io_r_auth_2(False, &r_a, q, base, 4);
751
752         /* return length of SMB data stored */
753         return q - start; 
754 }
755
756 static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time)
757 {
758         make_lsa_chal(&(cred->challenge), srv_chal);
759         cred->timestamp = srv_time;
760 }
761         
762
763 static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
764                               char srv_chal[8], UTIME srv_time, int status)
765 {
766         make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time);
767         r_a->status = status;
768 }
769
770 static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
771                                 char srv_cred[8], UTIME srv_time,
772                                 int status)
773 {
774         char *start = q;
775         LSA_R_SRV_PWSET r_s;
776
777         /* set up the LSA Server Password Set response */
778         make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status);
779
780         /* store the response in the SMB stream */
781         q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4);
782
783         /* return length of SMB data stored */
784         return q - start; 
785 }
786
787 static void make_lsa_user_info(LSA_USER_INFO *usr,
788
789         NTTIME *logon_time,
790         NTTIME *logoff_time,
791         NTTIME *kickoff_time,
792         NTTIME *pass_last_set_time,
793         NTTIME *pass_can_change_time,
794         NTTIME *pass_must_change_time,
795
796         char *user_name,
797         char *full_name,
798         char *logon_script,
799         char *profile_path,
800         char *home_dir,
801         char *dir_drive,
802
803         uint16 logon_count,
804         uint16 bad_pw_count,
805
806         uint32 user_id,
807         uint32 group_id,
808         uint32 num_groups,
809         DOM_GID *gids,
810         uint32 user_flgs,
811
812         char sess_key[16],
813
814         char *logon_srv,
815         char *logon_dom,
816
817         char *dom_sid,
818         char *other_sids) /* space-delimited set of SIDs */ 
819 {
820         /* only cope with one "other" sid, right now. */
821         /* need to count the number of space-delimited sids */
822         int i;
823         int num_other_sids = other_sids != NULL ? 1 : 0;
824
825         int len_user_name    = strlen(user_name   );
826         int len_full_name    = strlen(full_name   );
827         int len_logon_script = strlen(logon_script);
828         int len_profile_path = strlen(profile_path);
829         int len_home_dir     = strlen(home_dir    );
830         int len_dir_drive    = strlen(dir_drive   );
831
832         int len_logon_srv    = strlen(logon_srv);
833         int len_logon_dom    = strlen(logon_dom);
834
835         usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
836
837         usr->logon_time            = *logon_time;
838         usr->logoff_time           = *logoff_time;
839         usr->kickoff_time          = *kickoff_time;
840         usr->pass_last_set_time    = *pass_last_set_time;
841         usr->pass_can_change_time  = *pass_can_change_time;
842         usr->pass_must_change_time = *pass_must_change_time;
843
844         make_uni_hdr(&(usr->hdr_user_name   ), len_user_name   , len_user_name   , 4);
845         make_uni_hdr(&(usr->hdr_full_name   ), len_full_name   , len_full_name   , 4);
846         make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
847         make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
848         make_uni_hdr(&(usr->hdr_home_dir    ), len_home_dir    , len_home_dir    , 4);
849         make_uni_hdr(&(usr->hdr_dir_drive   ), len_dir_drive   , len_dir_drive   , 4);
850
851         usr->logon_count = logon_count;
852         usr->bad_pw_count = bad_pw_count;
853
854         usr->user_id = user_id;
855         usr->group_id = group_id;
856         usr->num_groups = num_groups;
857         usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
858         usr->user_flgs = user_flgs;
859
860         if (sess_key != NULL)
861         {
862                 memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
863         }
864         else
865         {
866                 bzero(usr->sess_key, sizeof(usr->sess_key));
867         }
868
869         make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
870         make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
871
872         usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
873
874         bzero(usr->padding, sizeof(usr->padding));
875
876         usr->num_other_sids = num_other_sids;
877         usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; 
878         
879         make_unistr2(&(usr->uni_user_name   ), user_name   , len_user_name   , 0);
880         make_unistr2(&(usr->uni_full_name   ), full_name   , len_full_name   , 0);
881         make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
882         make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
883         make_unistr2(&(usr->uni_home_dir    ), home_dir    , len_home_dir    , 0);
884         make_unistr2(&(usr->uni_dir_drive   ), dir_drive   , len_dir_drive   , 0);
885
886         usr->num_groups2 = num_groups;
887         for (i = 0; i < num_groups; i++)
888         {
889                 usr->gids[i] = gids[i];
890         }
891
892         make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
893         make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
894
895         make_dom_sid(&(usr->dom_sid), dom_sid);
896         make_dom_sid(&(usr->other_sids[0]), other_sids);
897 }
898
899
900 static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
901                                 char srv_cred[8], UTIME srv_time,
902                                 LSA_USER_INFO *user_info)
903 {
904         char *start = q;
905         LSA_R_SAM_LOGON r_s;
906
907         /* XXXX maybe we want to say 'no', reject the client's credentials */
908         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
909         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
910
911         /* store the user information, if there is any. */
912         r_s.user = user_info;
913         r_s.buffer_user = user_info != NULL ? 1 : 0;
914         r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
915
916         /* store the response in the SMB stream */
917         q = lsa_io_r_sam_logon(False, &r_s, q, base, 4);
918
919         /* return length of SMB data stored */
920         return q - start; 
921 }
922
923
924 static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
925                                 char srv_cred[8], UTIME srv_time,
926                                 uint32 status)
927 {
928         char *start = q;
929         LSA_R_SAM_LOGOFF r_s;
930
931         /* XXXX maybe we want to say 'no', reject the client's credentials */
932         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
933         make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
934
935         r_s.status = status;
936
937         /* store the response in the SMB stream */
938         q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4);
939
940         /* return length of SMB data stored */
941         return q - start; 
942 }
943
944
945 static void api_lsa_open_policy( char *param, char *data,
946                              char **rdata, int *rdata_len )
947 {
948         int reply_len;
949
950         /* we might actually want to decode the query, but it's not necessary */
951         /* lsa_io_q_open_policy(...); */
952
953         /* return a 20 byte policy handle */
954         reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18);
955
956         /* construct header, now that we know the reply length */
957         make_rpc_reply(data, *rdata, reply_len);
958         *rdata_len = reply_len + 0x18;
959 }
960
961 static void api_lsa_query_info( char *param, char *data,
962                                 char **rdata, int *rdata_len )
963 {
964         int reply_len;
965
966         LSA_Q_QUERY_INFO q_i;
967         pstring dom_name;
968         pstring dom_sid;
969
970         /* grab the info class and policy handle */
971         lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4);
972
973         pstrcpy(dom_name, lp_workgroup());
974         pstrcpy(dom_sid , lp_domainsid());
975
976         /* construct reply.  return status is always 0x0 */
977         reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, 
978                                                                          dom_name, dom_sid);
979
980         /* construct header, now that we know the reply length */
981         make_rpc_reply(data, *rdata, reply_len);
982         *rdata_len = reply_len + 0x18;
983 }
984
985 static void api_lsa_lookup_sids( char *param, char *data,
986                                  char **rdata, int *rdata_len )
987 {
988         int reply_len;
989
990         int i;
991         LSA_Q_LOOKUP_SIDS q_l;
992         pstring dom_name;
993         pstring dom_sid;
994         fstring dom_sids[MAX_LOOKUP_SIDS];
995
996         /* grab the info class and policy handle */
997         lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4);
998
999         pstrcpy(dom_name, lp_workgroup());
1000         pstrcpy(dom_sid , lp_domainsid());
1001
1002         /* convert received SIDs to strings, so we can do them. */
1003         for (i = 0; i < q_l.num_entries; i++)
1004         {
1005                 fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
1006         }
1007
1008         /* construct reply.  return status is always 0x0 */
1009         reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18,
1010                     q_l.num_entries, dom_sids, /* text-converted SIDs */
1011                                 dom_name, dom_sid, /* domain name, domain SID */
1012                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1013
1014         /* construct header, now that we know the reply length */
1015         make_rpc_reply(data, *rdata, reply_len);
1016         *rdata_len = reply_len + 0x18;
1017 }
1018
1019 static void api_lsa_lookup_names( char *param, char *data,
1020                                   char **rdata, int *rdata_len )
1021 {
1022         int reply_len;
1023
1024         int i;
1025         LSA_Q_LOOKUP_RIDS q_l;
1026         pstring dom_name;
1027         pstring dom_sid;
1028         uint32 dom_rids[MAX_LOOKUP_SIDS];
1029
1030         /* grab the info class and policy handle */
1031         lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4);
1032
1033         pstrcpy(dom_name, lp_workgroup());
1034         pstrcpy(dom_sid , lp_domainsid());
1035
1036         /* convert received RIDs to strings, so we can do them. */
1037         for (i = 0; i < q_l.num_entries; i++)
1038         {
1039                 char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
1040                 dom_rids[i] = name_to_rid(user_name);
1041         }
1042
1043         /* construct reply.  return status is always 0x0 */
1044         reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18,
1045                     q_l.num_entries, dom_rids, /* text-converted SIDs */
1046                                 dom_name, dom_sid, /* domain name, domain SID */
1047                                 "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
1048
1049         /* construct header, now that we know the reply length */
1050         make_rpc_reply(data, *rdata, reply_len);
1051         *rdata_len = reply_len + 0x18;
1052 }
1053
1054 #if 0
1055   q = data + 0x18;
1056   policyhandle = q; q += 20;
1057   nentries = qIVAL;
1058   DEBUG(4,("lookupnames entries %d\n",nentries));
1059   q += 4; /* skip second count */
1060   q += 8 * nentries; /* skip pointers */
1061   for (nnames = 0; nnames < nentries; nnames++)
1062   {
1063           names[nnames] = q; /* set name string to unicode header */
1064           q += IVAL(q,0)*2; /* guessing here */
1065   }
1066   /* There's a translated sids structure next but it looks fals */
1067
1068   DEBUG(4,("lookupnames line %d\n",__LINE__));
1069   /* formulate reply */
1070   q = *rdata + 0x18;
1071   qSIVAL(2); /* bufptr */
1072   qSIVAL(4); /* number of referenced domains
1073                  - need one per each identifier authority in call */
1074   qSIVAL(2); /* dom bufptr */
1075   qSIVAL(32); /* max entries */
1076   qSIVAL(4); /* number of reference domains? */
1077
1078   qunihdr(lp_workgroup()); /* reference domain */
1079   qSIVAL(2); /* sid bufptr */
1080
1081   qunihdr("S-1-1");
1082   qSIVAL(2); /* sid bufptr */
1083
1084   qunihdr("S-1-5");
1085   qSIVAL(2); /* sid bufptr */
1086
1087   qunihdr("S-1-3");
1088   qSIVAL(2); /* sid bufptr */
1089
1090   qunistr(lp_workgroup());
1091   DEBUG(4,("lookupnames line %d\n",__LINE__));
1092
1093   strcpy(domsid,lp_domainsid());
1094   p = strtok(domsid+2,"-");
1095   revision = atoi(p);
1096   identauth = atoi(strtok(0,"-"));
1097   numsubauths = 0;
1098   while (p = strtok(0, "-"))
1099         subauths[numsubauths++] = atoi(p);
1100   qSIVAL(numsubauths);
1101   qSCVAL(revision);
1102   qSCVAL(numsubauths);
1103   qRSSVAL(0); /* PAXX: FIX! first 2 bytes identifier authority */
1104   qRSIVAL(identauth); /* next 4 bytes */
1105   DEBUG(4,("lookupsid line %d\n",__LINE__));
1106   for (i = 0; i < numsubauths; i++)
1107   {
1108 qSIVAL(subauths[i]);
1109   }
1110   DEBUG(4,("lookupsid line %d\n",__LINE__));
1111
1112   qunistr("S-1-1");
1113   qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(1); /* S-1-1 */
1114   DEBUG(4,("lookupsid line %d\n",__LINE__));
1115
1116   qunistr("S-1-5");
1117   qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(5); /* S-1-5 */
1118
1119   qunistr("S-1-3");
1120   qSIVAL(0); qSCVAL(1); qSCVAL(0); qRSSVAL(0); qRSIVAL(3); /* S-1-3 */
1121
1122   qSIVAL(nentries);
1123   qSIVAL(2); /* bufptr */
1124   qSIVAL(nentries);
1125   DEBUG(4,("lookupnames line %d\n",__LINE__));
1126   for (i = 0; i < nentries; i++)
1127   {
1128 qSSVAL(5); /* SID name use  5 == well known sid, 1 == user sid see showacls */
1129 qSSVAL(5); /* undocumented */
1130   DEBUG(4,("lookupnames line %d\n",__LINE__));
1131 qSIVAL(name_to_rid(names[i]));
1132   DEBUG(4,("lookupnames name_to_rid %d\n",name_to_rid(names[i])));
1133 qSIVAL(0); /* domain index out of above reference domains */
1134   }
1135   qSIVAL(nentries); /* mapped count */
1136   endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
1137   break;
1138
1139 #endif
1140
1141
1142 /* space in front of this function so that make proto doesn't pick it up */
1143  void _dummy_function(void)
1144 {
1145         UTIME t;
1146         lsa_reply_req_chal(NULL, NULL, NULL, NULL);
1147         lsa_reply_auth_2(NULL, NULL, NULL, NULL, 0);
1148         lsa_reply_srv_pwset(NULL, NULL, NULL, NULL, t, 0);
1149         make_lsa_user_info(NULL,
1150                                                 NULL, NULL, NULL, NULL, NULL, NULL,
1151                                            NULL, NULL, NULL, NULL, NULL, NULL,
1152                                                 0, 0,
1153                         0, 0, 0, NULL, 0,
1154                                                  NULL,
1155                                                 NULL, NULL,
1156                                                 NULL, NULL);
1157         lsa_reply_sam_logon(NULL,NULL,NULL,NULL,t, NULL);
1158         lsa_reply_sam_logoff(NULL,NULL,NULL,NULL,t,0);
1159         api_lsa_open_policy(NULL,NULL,NULL,NULL);
1160         api_lsa_query_info(NULL,NULL,NULL,NULL);
1161         api_lsa_lookup_sids (NULL,NULL,NULL,NULL);
1162         api_lsa_lookup_names(NULL,NULL,NULL,NULL);
1163 }