ipc.c: Adding Andrews become_root code to the main branch.
[samba.git] / source3 / smbd / ipc.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Inter-process communication and named pipe handling
5    Copyright (C) Andrew Tridgell 1992-1997
6
7    SMB Version handling
8    Copyright (C) John H Terpstra 1995-1997
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23    */
24 /*
25    This file handles the named pipe and mailslot calls
26    in the SMBtrans protocol
27    */
28
29 #include "includes.h"
30
31 #ifdef CHECK_TYPES
32 #undef CHECK_TYPES
33 #endif
34 #define CHECK_TYPES 0
35
36 extern int DEBUGLEVEL;
37 extern int max_send;
38 extern files_struct Files[];
39 extern connection_struct Connections[];
40
41 extern fstring local_machine;
42 extern fstring myworkgroup;
43
44 #define NERR_Success 0
45 #define NERR_badpass 86
46 #define NERR_notsupported 50
47
48 #define NERR_BASE (2100)
49 #define NERR_BufTooSmall (NERR_BASE+23)
50 #define NERR_JobNotFound (NERR_BASE+51)
51 #define NERR_DestNotFound (NERR_BASE+52)
52 #define ERROR_INVALID_LEVEL 124
53 #define ERROR_MORE_DATA 234
54
55 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
56
57 #define ACCESS_READ 0x01
58 #define ACCESS_WRITE 0x02
59 #define ACCESS_CREATE 0x04
60
61 #define SHPWLEN 8               /* share password length */
62 #define NNLEN 12                /* 8.3 net name length */
63 #define SNLEN 15                /* service name length */
64 #define QNLEN 12                /* queue name maximum length */
65
66 extern int Client;
67
68 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
69                             int mdrcnt,int mprcnt,
70                             char **rdata,char **rparam,
71                             int *rdata_len,int *rparam_len);
72 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
73                          int mdrcnt,int mprcnt,
74                          char **rdata,char **rparam,
75                          int *rdata_len,int *rparam_len);
76
77
78 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
79 {
80   pstring buf;
81   int l;
82
83   if (!src || !dst || !n || !(*dst)) return(0);
84
85   StrnCpy(buf,src,sizeof(buf)/2);
86   string_sub(buf,"%S",lp_servicename(snum));
87   standard_sub(cnum,buf);
88   StrnCpy(*dst,buf,*n);
89   l = strlen(*dst) + 1;
90   (*dst) += l;
91   (*n) -= l;
92   return l;
93 }
94
95 static int CopyAndAdvance(char** dst, char* src, int* n)
96 {
97   int l;
98   if (!src || !dst || !n || !(*dst)) return(0);
99   StrnCpy(*dst,src,*n);
100   l = strlen(*dst) + 1;
101   (*dst) += l;
102   (*n) -= l;
103   return l;
104 }
105
106 static int StrlenExpanded(int cnum, int snum, char* s)
107 {
108   pstring buf;
109   if (!s) return(0);
110   StrnCpy(buf,s,sizeof(buf)/2);
111   string_sub(buf,"%S",lp_servicename(snum));
112   standard_sub(cnum,buf);
113   return strlen(buf) + 1;
114 }
115
116 static char* Expand(int cnum, int snum, char* s)
117 {
118   static pstring buf;
119   if (!s) return(NULL);
120   StrnCpy(buf,s,sizeof(buf)/2);
121   string_sub(buf,"%S",lp_servicename(snum));
122   standard_sub(cnum,buf);
123   return &buf[0];
124 }
125
126 /*******************************************************************
127   check a API string for validity when we only need to check the prefix
128   ******************************************************************/
129 static BOOL prefix_ok(char *str,char *prefix)
130 {
131   return(strncmp(str,prefix,strlen(prefix)) == 0);
132 }
133
134
135 /****************************************************************************
136   send a trans reply
137   ****************************************************************************/
138 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
139                              int ldata,int lparam,int lsetup)
140 {
141   int i;
142   int this_ldata,this_lparam;
143   int tot_data=0,tot_param=0;
144   int align;
145
146   this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
147   this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
148
149   align = (this_lparam%4);
150
151   set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
152   if (this_lparam)
153     memcpy(smb_buf(outbuf),param,this_lparam);
154   if (this_ldata)
155     memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
156
157   SSVAL(outbuf,smb_vwv0,lparam);
158   SSVAL(outbuf,smb_vwv1,ldata);
159   SSVAL(outbuf,smb_vwv3,this_lparam);
160   SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
161   SSVAL(outbuf,smb_vwv5,0);
162   SSVAL(outbuf,smb_vwv6,this_ldata);
163   SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
164   SSVAL(outbuf,smb_vwv8,0);
165   SSVAL(outbuf,smb_vwv9,lsetup);
166   for (i=0;i<lsetup;i++)
167     SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
168
169   show_msg(outbuf);
170   send_smb(Client,outbuf);
171
172   tot_data = this_ldata;
173   tot_param = this_lparam;
174
175   while (tot_data < ldata || tot_param < lparam)
176     {
177       this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
178       this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
179
180       align = (this_lparam%4);
181
182       set_message(outbuf,10,this_ldata+this_lparam+align,False);
183       if (this_lparam)
184         memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
185       if (this_ldata)
186         memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
187
188       SSVAL(outbuf,smb_vwv3,this_lparam);
189       SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
190       SSVAL(outbuf,smb_vwv5,tot_param);
191       SSVAL(outbuf,smb_vwv6,this_ldata);
192       SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
193       SSVAL(outbuf,smb_vwv8,tot_data);
194       SSVAL(outbuf,smb_vwv9,0);
195
196       show_msg(outbuf);
197       send_smb(Client,outbuf);
198
199       tot_data += this_ldata;
200       tot_param += this_lparam;
201     }
202 }
203
204 struct pack_desc {
205   char* format;     /* formatstring for structure */
206   char* subformat;  /* subformat for structure */
207   char* base;       /* baseaddress of buffer */
208   int buflen;      /* remaining size for fixed part; on init: length of base */
209   int subcount;     /* count of substructures */
210   char* structbuf;  /* pointer into buffer for remaining fixed part */
211   int stringlen;    /* remaining size for variable part */              
212   char* stringbuf;  /* pointer into buffer for remaining variable part */
213   int neededlen;    /* total needed size */
214   int usedlen;      /* total used size (usedlen <= neededlen and usedlen <= buflen) */
215   char* curpos;     /* current position; pointer into format or subformat */
216   int errcode;
217 };
218
219 static int get_counter(char** p)
220 {
221   int i, n;
222   if (!p || !(*p)) return(1);
223   if (!isdigit(**p)) return 1;
224   for (n = 0;;) {
225     i = **p;
226     if (isdigit(i))
227       n = 10 * n + (i - '0');
228     else
229       return n;
230     (*p)++;
231   }
232 }
233
234 static int getlen(char* p)
235 {
236   int n = 0;
237   if (!p) return(0);
238   while (*p) {
239     switch( *p++ ) {
240     case 'W':                   /* word (2 byte) */
241       n += 2;
242       break;
243     case 'N':                   /* count of substructures (word) at end */
244       n += 2;
245       break;
246     case 'D':                   /* double word (4 byte) */
247     case 'z':                   /* offset to zero terminated string (4 byte) */
248     case 'l':                   /* offset to user data (4 byte) */
249       n += 4;
250       break;
251     case 'b':                   /* offset to data (with counter) (4 byte) */
252       n += 4;
253       get_counter(&p);
254       break;
255     case 'B':                   /* byte (with optional counter) */
256       n += get_counter(&p);
257       break;
258     }
259   }
260   return n;
261 }
262
263 static BOOL init_package(struct pack_desc* p, int count, int subcount)
264 {
265   int n = p->buflen;
266   int i;
267
268   if (!p->format || !p->base) return(False);
269
270   i = count * getlen(p->format);
271   if (p->subformat) i += subcount * getlen(p->subformat);
272   p->structbuf = p->base;
273   p->neededlen = 0;
274   p->usedlen = 0;
275   p->subcount = 0;
276   p->curpos = p->format;
277   if (i > n) {
278     i = n = 0;
279     p->errcode = NERR_BufTooSmall;
280   }
281
282   p->errcode = NERR_Success;
283   p->buflen = i;
284   n -= i;
285   p->stringbuf = p->base + i;
286   p->stringlen = n;
287   return(p->errcode == NERR_Success);
288 }
289
290 #ifdef __STDC__
291 static int package(struct pack_desc* p, ...)
292 {
293 #else
294 static int package(va_alist)
295 va_dcl
296 {
297   struct pack_desc* p;
298 #endif
299   va_list args;
300   int needed=0, stringneeded;
301   char* str=NULL;
302   int is_string=0, stringused;
303   int32 temp;
304
305 #ifdef __STDC__
306   va_start(args,p);
307 #else
308   va_start(args);
309   p = va_arg(args,struct pack_desc *);
310 #endif
311
312   if (!*p->curpos) {
313     if (!p->subcount)
314       p->curpos = p->format;
315     else {
316       p->curpos = p->subformat;
317       p->subcount--;
318     }
319   }
320 #if CHECK_TYPES
321   str = va_arg(args,char*);
322   if (strncmp(str,p->curpos,strlen(str)) != 0) {
323     DEBUG(2,("type error in package: %s instead of %*s\n",str,
324              strlen(str),p->curpos));
325     va_end(args);
326 #if AJT
327     ajt_panic();
328 #endif  
329     return 0;
330   }
331 #endif
332   stringneeded = -1;
333
334   if (!p->curpos) return(0);
335
336   switch( *p->curpos++ ) {
337   case 'W':                     /* word (2 byte) */
338     needed = 2;
339     temp = va_arg(args,int);
340     if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
341     break;
342   case 'N':                     /* count of substructures (word) at end */
343     needed = 2;
344     p->subcount = va_arg(args,int);
345     if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
346     break;
347   case 'D':                     /* double word (4 byte) */
348     needed = 4;
349     temp = va_arg(args,int);
350     if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
351     break;
352   case 'B':                     /* byte (with optional counter) */
353     needed = get_counter(&p->curpos);
354     {
355       char *s = va_arg(args,char*);
356       if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
357     }
358     break;
359   case 'z':                     /* offset to zero terminated string (4 byte) */
360     str = va_arg(args,char*);
361     stringneeded = (str ? strlen(str)+1 : 0);
362     is_string = 1;
363     break;
364   case 'l':                     /* offset to user data (4 byte) */
365     str = va_arg(args,char*);
366     stringneeded = va_arg(args,int);
367     is_string = 0;
368     break;
369   case 'b':                     /* offset to data (with counter) (4 byte) */
370     str = va_arg(args,char*);
371     stringneeded = get_counter(&p->curpos);
372     is_string = 0;
373     break;
374   }
375   va_end(args);
376   if (stringneeded >= 0) {
377     needed = 4;
378     if (p->buflen >= needed) {
379       stringused = stringneeded;
380       if (stringused > p->stringlen) {
381         stringused = (is_string ? p->stringlen : 0);
382         if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
383       }
384       if (!stringused)
385         SIVAL(p->structbuf,0,0);
386       else {
387         SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
388         memcpy(p->stringbuf,str?str:"",stringused);
389         if (is_string) p->stringbuf[stringused-1] = '\0';
390         p->stringbuf += stringused;
391         p->stringlen -= stringused;
392         p->usedlen += stringused;
393       }
394     }
395     p->neededlen += stringneeded;
396   }
397   p->neededlen += needed;
398   if (p->buflen >= needed) {
399     p->structbuf += needed;
400     p->buflen -= needed;
401     p->usedlen += needed;
402   }
403   else {
404     if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
405   }
406   return 1;
407 }
408
409 #if CHECK_TYPES
410 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
411 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
412 #else
413 #define PACK(desc,t,v) package(desc,v)
414 #define PACKl(desc,t,v,l) package(desc,v,l)
415 #endif
416
417 static void PACKI(struct pack_desc* desc,char *t,int v)
418 {
419   PACK(desc,t,v);
420 }
421
422 static void PACKS(struct pack_desc* desc,char *t,char *v)
423 {
424   PACK(desc,t,v);
425 }
426
427
428 /****************************************************************************
429   get a print queue
430   ****************************************************************************/
431
432 static void PackDriverData(struct pack_desc* desc)
433 {
434   char drivdata[4+4+32];
435   SIVAL(drivdata,0,sizeof drivdata); /* cb */
436   SIVAL(drivdata,4,1000);       /* lVersion */
437   memset(drivdata+8,0,32);      /* szDeviceName */
438   strcpy(drivdata+8,"NULL");
439   PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
440 }
441
442 static int check_printq_info(struct pack_desc* desc,
443                              int uLevel, char *id1, char *id2)
444 {
445   desc->subformat = NULL;
446   switch( uLevel ) {
447   case 0:
448     desc->format = "B13";
449     break;
450   case 1:
451     desc->format = "B13BWWWzzzzzWW";
452     break;
453   case 2:
454     desc->format = "B13BWWWzzzzzWN";
455     desc->subformat = "WB21BB16B10zWWzDDz";
456     break;
457   case 3:
458     desc->format = "zWWWWzzzzWWzzl";
459     break;
460   case 4:
461     desc->format = "zWWWWzzzzWNzzl";
462     desc->subformat = "WWzWWDDzz";
463     break;
464   case 5:
465     desc->format = "z";
466     break;
467   default: return False;
468   }
469   if (strcmp(desc->format,id1) != 0) return False;
470   if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
471   return True;
472 }
473
474 static void fill_printjob_info(int cnum, int snum, int uLevel,
475                                struct pack_desc* desc,
476                                print_queue_struct* queue, int n)
477 {
478   time_t t = queue->time;
479
480   /* the client expects localtime */
481   t -= TimeDiff(t);
482
483   PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
484   if (uLevel == 1) {
485     PACKS(desc,"B21",queue->user); /* szUserName */
486     PACKS(desc,"B","");         /* pad */
487     PACKS(desc,"B16","");       /* szNotifyName */
488     PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
489     PACKS(desc,"z","");         /* pszParms */
490     PACKI(desc,"W",n+1);                /* uPosition */
491     PACKI(desc,"W",queue->status); /* fsStatus */
492     PACKS(desc,"z","");         /* pszStatus */
493     PACKI(desc,"D",t); /* ulSubmitted */
494     PACKI(desc,"D",queue->size); /* ulSize */
495     PACKS(desc,"z",queue->file); /* pszComment */
496   }
497   if (uLevel == 2 || uLevel == 3) {
498     PACKI(desc,"W",queue->priority);            /* uPriority */
499     PACKS(desc,"z",queue->user); /* pszUserName */
500     PACKI(desc,"W",n+1);                /* uPosition */
501     PACKI(desc,"W",queue->status); /* fsStatus */
502     PACKI(desc,"D",t); /* ulSubmitted */
503     PACKI(desc,"D",queue->size); /* ulSize */
504     PACKS(desc,"z","Samba");    /* pszComment */
505     PACKS(desc,"z",queue->file); /* pszDocument */
506     if (uLevel == 3) {
507       PACKS(desc,"z","");       /* pszNotifyName */
508       PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
509       PACKS(desc,"z","");       /* pszParms */
510       PACKS(desc,"z","");       /* pszStatus */
511       PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
512       PACKS(desc,"z","lpd");    /* pszQProcName */
513       PACKS(desc,"z","");       /* pszQProcParms */
514       PACKS(desc,"z","NULL"); /* pszDriverName */
515       PackDriverData(desc);     /* pDriverData */
516       PACKS(desc,"z","");       /* pszPrinterName */
517     }
518   }
519 }
520
521 static void fill_printq_info(int cnum, int snum, int uLevel,
522                              struct pack_desc* desc,
523                              int count, print_queue_struct* queue,
524                              print_status_struct* status)
525 {
526   if (uLevel < 3) {
527     PACKS(desc,"B13",SERVICE(snum));
528   } else {
529     PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
530   }
531   if (uLevel == 1 || uLevel == 2) {
532     PACKS(desc,"B","");         /* alignment */
533     PACKI(desc,"W",5);          /* priority */
534     PACKI(desc,"W",0);          /* start time */
535     PACKI(desc,"W",0);          /* until time */
536     PACKS(desc,"z","");         /* pSepFile */
537     PACKS(desc,"z","lpd");      /* pPrProc */
538     PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
539     PACKS(desc,"z","");         /* pParms */
540     if (snum < 0) {
541       PACKS(desc,"z","UNKNOWN PRINTER");
542       PACKI(desc,"W",LPSTAT_ERROR);
543     }
544     else if (!status || !status->message[0]) {
545       PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
546       PACKI(desc,"W",LPSTAT_OK); /* status */
547     } else {
548       PACKS(desc,"z",status->message);
549       PACKI(desc,"W",status->status); /* status */
550     }
551     PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
552   }
553   if (uLevel == 3 || uLevel == 4) {
554     PACKI(desc,"W",5);          /* uPriority */
555     PACKI(desc,"W",0);          /* uStarttime */
556     PACKI(desc,"W",0);          /* uUntiltime */
557     PACKI(desc,"W",5);          /* pad1 */
558     PACKS(desc,"z","");         /* pszSepFile */
559     PACKS(desc,"z","WinPrint"); /* pszPrProc */
560     PACKS(desc,"z","");         /* pszParms */
561     if (!status || !status->message[0]) {
562       PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
563       PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
564     } else {
565       PACKS(desc,"z",status->message); /* pszComment */
566       PACKI(desc,"W",status->status); /* fsStatus */
567     }
568     PACKI(desc,(uLevel == 3 ? "W" : "N"),count);        /* cJobs */
569     PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
570     PACKS(desc,"z",lp_printerdriver(snum));             /* pszDriverName */
571     PackDriverData(desc);       /* pDriverData */
572   }
573   if (uLevel == 2 || uLevel == 4) {
574     int i;
575     for (i=0;i<count;i++)
576       fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
577   }
578  
579   DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
580 }
581
582 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
583                                  int mdrcnt,int mprcnt,
584                                  char **rdata,char **rparam,
585                                  int *rdata_len,int *rparam_len)
586 {
587   char *str1 = param+2;
588   char *str2 = skip_string(str1,1);
589   char *p = skip_string(str2,1);
590   char *QueueName = p;
591   int uLevel,cbBuf;
592   int count=0;
593   int snum;
594   char* str3;
595   struct pack_desc desc;
596   print_queue_struct *queue=NULL;
597   print_status_struct status;
598   
599   bzero(&status,sizeof(status));
600   bzero(&desc,sizeof(desc));
601  
602   p = skip_string(p,1);
603   uLevel = SVAL(p,0);
604   cbBuf = SVAL(p,2);
605   str3 = p + 4;
606  
607   /* remove any trailing username */
608   if ((p = strchr(QueueName,'%'))) *p = 0;
609  
610   DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
611  
612   /* check it's a supported varient */
613   if (!prefix_ok(str1,"zWrLh")) return False;
614   if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
615  
616   snum = lp_servicenumber(QueueName);
617   if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
618     int pnum = lp_servicenumber(PRINTERS_NAME);
619     if (pnum >= 0) {
620       lp_add_printer(QueueName,pnum);
621       snum = lp_servicenumber(QueueName);
622     }
623   }
624   
625   if (snum < 0 || !VALID_SNUM(snum)) return(False);
626
627   count = get_printqueue(snum,cnum,&queue,&status);
628   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
629   desc.base = *rdata;
630   desc.buflen = mdrcnt;
631   if (init_package(&desc,1,count)) {
632     desc.subcount = count;
633     fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
634   }
635
636   *rdata_len = desc.usedlen;
637   
638   *rparam_len = 6;
639   *rparam = REALLOC(*rparam,*rparam_len);
640   SSVALS(*rparam,0,desc.errcode);
641   SSVAL(*rparam,2,0);
642   SSVAL(*rparam,4,desc.neededlen);
643   
644   DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
645
646   if (queue) free(queue);
647   
648   return(True);
649 }
650
651
652 /****************************************************************************
653   view list of all print jobs on all queues
654   ****************************************************************************/
655 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
656                               int mdrcnt, int mprcnt,
657                               char **rdata, char** rparam,
658                               int *rdata_len, int *rparam_len)
659 {
660   char *param_format = param+2;
661   char *output_format1 = skip_string(param_format,1);
662   char *p = skip_string(output_format1,1);
663   int uLevel = SVAL(p,0);
664   char *output_format2 = p + 4;
665   int services = lp_numservices();
666   int i, n;
667   struct pack_desc desc;
668   print_queue_struct **queue = NULL;
669   print_status_struct *status = NULL;
670   int* subcntarr = NULL;
671   int queuecnt, subcnt=0, succnt=0;
672  
673   bzero(&desc,sizeof(desc));
674
675   DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
676  
677   if (!prefix_ok(param_format,"WrLeh")) return False;
678   if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
679     return False;
680   queuecnt = 0;
681   for (i = 0; i < services; i++)
682     if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
683       queuecnt++;
684   if (uLevel > 0) {
685     queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
686     memset(queue,0,queuecnt*sizeof(print_queue_struct*));
687     status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
688     memset(status,0,queuecnt*sizeof(print_status_struct));
689     subcntarr = (int*)malloc(queuecnt*sizeof(int));
690     subcnt = 0;
691     n = 0;
692     for (i = 0; i < services; i++)
693       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
694         subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
695         subcnt += subcntarr[n];
696         n++;
697       }
698   }
699   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
700   desc.base = *rdata;
701   desc.buflen = mdrcnt;
702
703   if (init_package(&desc,queuecnt,subcnt)) {
704     n = 0;
705     succnt = 0;
706     for (i = 0; i < services; i++)
707       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
708         fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
709         n++;
710         if (desc.errcode == NERR_Success) succnt = n;
711       }
712   }
713
714   if (subcntarr) free(subcntarr);
715  
716   *rdata_len = desc.usedlen;
717   *rparam_len = 8;
718   *rparam = REALLOC(*rparam,*rparam_len);
719   SSVALS(*rparam,0,desc.errcode);
720   SSVAL(*rparam,2,0);
721   SSVAL(*rparam,4,succnt);
722   SSVAL(*rparam,6,queuecnt);
723   
724   for (i = 0; i < queuecnt; i++) {
725     if (queue && queue[i]) free(queue[i]);
726   }
727
728   if (queue) free(queue);
729   if (status) free(status);
730   
731   return True;
732 }
733
734 /****************************************************************************
735   get info level for a server list query
736   ****************************************************************************/
737 static BOOL check_server_info(int uLevel, char* id)
738 {
739   switch( uLevel ) {
740   case 0:
741     if (strcmp(id,"B16") != 0) return False;
742     break;
743   case 1:
744     if (strcmp(id,"B16BBDz") != 0) return False;
745     break;
746   default: 
747     return False;
748   }
749   return True;
750 }
751
752 struct srv_info_struct
753 {
754   fstring name;
755   uint32 type;
756   fstring comment;
757   fstring domain;
758   BOOL server_added;
759 };
760
761
762 /*******************************************************************
763   get server info lists from the files saved by nmbd. Return the
764   number of entries
765   ******************************************************************/
766 static int get_server_info(uint32 servertype, 
767                            struct srv_info_struct **servers,
768                            char *domain)
769 {
770   FILE *f;
771   pstring fname;
772   int count=0;
773   int alloced=0;
774   pstring line;
775   BOOL local_list_only;
776
777   pstrcpy(fname,lp_lockdir());
778   trim_string(fname,NULL,"/");
779   strcat(fname,"/");
780   strcat(fname,SERVER_LIST);
781
782   f = fopen(fname,"r");
783
784   if (!f) {
785     DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
786     return(0);
787   }
788
789   /* request for everything is code for request all servers */
790   if (servertype == SV_TYPE_ALL) 
791         servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
792
793   local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
794
795   DEBUG(4,("Servertype search: %8x\n",servertype));
796
797   while (!feof(f))
798   {
799     fstring stype;
800     struct srv_info_struct *s;
801     char *ptr = line;
802     BOOL ok = True;
803     *ptr = 0;
804
805     fgets(line,sizeof(line)-1,f);
806     if (!*line) continue;
807     
808     if (count == alloced) {
809       alloced += 10;
810       (*servers) = (struct srv_info_struct *)
811         Realloc(*servers,sizeof(**servers)*alloced);
812       if (!(*servers)) return(0);
813       bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
814     }
815     s = &(*servers)[count];
816     
817     if (!next_token(&ptr,s->name   , NULL)) continue;
818     if (!next_token(&ptr,stype     , NULL)) continue;
819     if (!next_token(&ptr,s->comment, NULL)) continue;
820     if (!next_token(&ptr,s->domain , NULL)) {
821       /* this allows us to cope with an old nmbd */
822       strcpy(s->domain,myworkgroup); 
823     }
824     
825     if (sscanf(stype,"%X",&s->type) != 1) { 
826       DEBUG(4,("r:host file ")); 
827       ok = False; 
828     }
829     
830         /* Filter the servers/domains we return based on what was asked for. */
831
832         /* Check to see if we are being asked for a local list only. */
833         if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
834           DEBUG(4,("r: local list only"));
835           ok = False;
836         }
837
838     /* doesn't match up: don't want it */
839     if (!(servertype & s->type)) { 
840       DEBUG(4,("r:serv type ")); 
841       ok = False; 
842     }
843     
844     if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
845         (s->type & SV_TYPE_DOMAIN_ENUM))
846       {
847         DEBUG(4,("s: dom mismatch "));
848         ok = False;
849       }
850     
851     if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
852       {
853         ok = False;
854       }
855     
856         /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
857         s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
858
859     if (ok)
860       {
861         DEBUG(4,("**SV** %20s %8x %25s %15s\n",
862                  s->name, s->type, s->comment, s->domain));
863         
864         s->server_added = True;
865         count++;
866       }
867     else
868       {
869         DEBUG(4,("%20s %8x %25s %15s\n",
870                  s->name, s->type, s->comment, s->domain));
871       }
872   }
873   
874   fclose(f);
875   return(count);
876 }
877
878
879 /*******************************************************************
880   fill in a server info structure
881   ******************************************************************/
882 static int fill_srv_info(struct srv_info_struct *service, 
883                          int uLevel, char **buf, int *buflen, 
884                          char **stringbuf, int *stringspace, char *baseaddr)
885 {
886   int struct_len;
887   char* p;
888   char* p2;
889   int l2;
890   int len;
891  
892   switch (uLevel) {
893   case 0: struct_len = 16; break;
894   case 1: struct_len = 26; break;
895   default: return -1;
896   }  
897  
898   if (!buf)
899     {
900       len = 0;
901       switch (uLevel) 
902         {
903         case 1:
904           len = strlen(service->comment)+1;
905           break;
906         }
907
908       if (buflen) *buflen = struct_len;
909       if (stringspace) *stringspace = len;
910       return struct_len + len;
911     }
912   
913   len = struct_len;
914   p = *buf;
915   if (*buflen < struct_len) return -1;
916   if (stringbuf)
917     {
918       p2 = *stringbuf;
919       l2 = *stringspace;
920     }
921   else
922     {
923       p2 = p + struct_len;
924       l2 = *buflen - struct_len;
925     }
926   if (!baseaddr) baseaddr = p;
927   
928   switch (uLevel)
929     {
930     case 0:
931       StrnCpy(p,service->name,15);
932       break;
933
934     case 1:
935       StrnCpy(p,service->name,15);
936       SIVAL(p,18,service->type);
937       SIVAL(p,22,PTR_DIFF(p2,baseaddr));
938       len += CopyAndAdvance(&p2,service->comment,&l2);
939       break;
940     }
941
942   if (stringbuf)
943     {
944       *buf = p + struct_len;
945       *buflen -= struct_len;
946       *stringbuf = p2;
947       *stringspace = l2;
948     }
949   else
950     {
951       *buf = p2;
952       *buflen -= len;
953     }
954   return len;
955 }
956
957
958 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
959 {
960   return(strcmp(s1->name,s2->name));
961 }
962
963 /****************************************************************************
964   view list of servers available (or possibly domains). The info is
965   extracted from lists saved by nmbd on the local host
966   ****************************************************************************/
967 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
968                                int mdrcnt, int mprcnt, char **rdata, 
969                                char **rparam, int *rdata_len, int *rparam_len)
970 {
971   char *str1 = param+2;
972   char *str2 = skip_string(str1,1);
973   char *p = skip_string(str2,1);
974   int uLevel = SVAL(p,0);
975   int buf_len = SVAL(p,2);
976   uint32 servertype = IVAL(p,4);
977   char *p2;
978   int data_len, fixed_len, string_len;
979   int f_len, s_len;
980   struct srv_info_struct *servers=NULL;
981   int counted=0,total=0;
982   int i,missed;
983   fstring domain;
984   BOOL domain_request;
985   BOOL local_request;
986
987   /* If someone sets all the bits they don't really mean to set
988      DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
989      known servers. */
990
991   if (servertype == SV_TYPE_ALL) 
992     servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
993
994   /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
995      any other bit (they may just set this bit on it's own) they 
996      want all the locally seen servers. However this bit can be 
997      set on its own so set the requested servers to be 
998      ALL - DOMAIN_ENUM. */
999
1000   if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) 
1001     servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1002
1003   domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1004   local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1005
1006   p += 8;
1007
1008   if (!prefix_ok(str1,"WrLehD")) return False;
1009   if (!check_server_info(uLevel,str2)) return False;
1010   
1011   DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1012   DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1013   DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1014
1015   if (strcmp(str1, "WrLehDz") == 0) {
1016     StrnCpy(domain, p, sizeof(fstring)-1);
1017   } else {
1018     StrnCpy(domain, myworkgroup, sizeof(fstring)-1);    
1019   }
1020
1021   if (lp_browse_list())
1022     total = get_server_info(servertype,&servers,domain);
1023
1024   data_len = fixed_len = string_len = 0;
1025   missed = 0;
1026
1027   qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1028
1029   {
1030     char *lastname=NULL;
1031
1032     for (i=0;i<total;i++)
1033     {
1034       struct srv_info_struct *s = &servers[i];
1035       if (lastname && strequal(lastname,s->name)) continue;
1036       lastname = s->name;
1037       data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1038       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1039                s->name, s->type, s->comment, s->domain));
1040       
1041       if (data_len <= buf_len) {
1042           counted++;
1043           fixed_len += f_len;
1044           string_len += s_len;
1045       } else {
1046         missed++;
1047       }
1048     }
1049   }
1050
1051   *rdata_len = fixed_len + string_len;
1052   *rdata = REALLOC(*rdata,*rdata_len);
1053   bzero(*rdata,*rdata_len);
1054   
1055   p2 = (*rdata) + fixed_len;    /* auxilliary data (strings) will go here */
1056   p = *rdata;
1057   f_len = fixed_len;
1058   s_len = string_len;
1059
1060   {
1061     char *lastname=NULL;
1062     int count2 = counted;
1063     for (i = 0; i < total && count2;i++)
1064       {
1065         struct srv_info_struct *s = &servers[i];
1066         if (lastname && strequal(lastname,s->name)) continue;
1067         lastname = s->name;
1068         fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1069         DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1070                  s->name, s->type, s->comment, s->domain));
1071         count2--;
1072       }
1073   }
1074   
1075   *rparam_len = 8;
1076   *rparam = REALLOC(*rparam,*rparam_len);
1077   SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1078   SSVAL(*rparam,2,0);
1079   SSVAL(*rparam,4,counted);
1080   SSVAL(*rparam,6,counted+missed);
1081
1082   if (servers) free(servers);
1083
1084   DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1085            domain,uLevel,counted,counted+missed));
1086
1087   return(True);
1088 }
1089
1090
1091 /****************************************************************************
1092   get info about a share
1093   ****************************************************************************/
1094 static BOOL check_share_info(int uLevel, char* id)
1095 {
1096   switch( uLevel ) {
1097   case 0:
1098     if (strcmp(id,"B13") != 0) return False;
1099     break;
1100   case 1:
1101     if (strcmp(id,"B13BWz") != 0) return False;
1102     break;
1103   case 2:
1104     if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1105     break;
1106   case 91:
1107     if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1108     break;
1109   default: return False;
1110   }
1111   return True;
1112 }
1113
1114 static int fill_share_info(int cnum, int snum, int uLevel,
1115                            char** buf, int* buflen,
1116                            char** stringbuf, int* stringspace, char* baseaddr)
1117 {
1118   int struct_len;
1119   char* p;
1120   char* p2;
1121   int l2;
1122   int len;
1123  
1124   switch( uLevel ) {
1125   case 0: struct_len = 13; break;
1126   case 1: struct_len = 20; break;
1127   case 2: struct_len = 40; break;
1128   case 91: struct_len = 68; break;
1129   default: return -1;
1130   }
1131   
1132  
1133   if (!buf)
1134     {
1135       len = 0;
1136       if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1137       if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1138       if (buflen) *buflen = struct_len;
1139       if (stringspace) *stringspace = len;
1140       return struct_len + len;
1141     }
1142   
1143   len = struct_len;
1144   p = *buf;
1145   if ((*buflen) < struct_len) return -1;
1146   if (stringbuf)
1147     {
1148       p2 = *stringbuf;
1149       l2 = *stringspace;
1150     }
1151   else
1152     {
1153       p2 = p + struct_len;
1154       l2 = (*buflen) - struct_len;
1155     }
1156   if (!baseaddr) baseaddr = p;
1157   
1158   StrnCpy(p,lp_servicename(snum),13);
1159   
1160   if (uLevel > 0)
1161     {
1162       int type;
1163       CVAL(p,13) = 0;
1164       type = STYPE_DISKTREE;
1165       if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1166       if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1167       SSVAL(p,14,type);         /* device type */
1168       SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1169       len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1170     }
1171   
1172   if (uLevel > 1)
1173     {
1174       SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1175       SSVALS(p,22,-1);          /* max uses */
1176       SSVAL(p,24,1); /* current uses */
1177       SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1178       len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1179       memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1180     }
1181   
1182   if (uLevel > 2)
1183     {
1184       memset(p+40,0,SHPWLEN+2);
1185       SSVAL(p,50,0);
1186       SIVAL(p,52,0);
1187       SSVAL(p,56,0);
1188       SSVAL(p,58,0);
1189       SIVAL(p,60,0);
1190       SSVAL(p,64,0);
1191       SSVAL(p,66,0);
1192     }
1193        
1194   if (stringbuf)
1195     {
1196       (*buf) = p + struct_len;
1197       (*buflen) -= struct_len;
1198       (*stringbuf) = p2;
1199       (*stringspace) = l2;
1200     }
1201   else
1202     {
1203       (*buf) = p2;
1204       (*buflen) -= len;
1205     }
1206   return len;
1207 }
1208
1209 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1210                                  int mdrcnt,int mprcnt,
1211                                  char **rdata,char **rparam,
1212                                  int *rdata_len,int *rparam_len)
1213 {
1214   char *str1 = param+2;
1215   char *str2 = skip_string(str1,1);
1216   char *netname = skip_string(str2,1);
1217   char *p = skip_string(netname,1);
1218   int uLevel = SVAL(p,0);
1219   int snum = find_service(netname);
1220   
1221   if (snum < 0) return False;
1222   
1223   /* check it's a supported varient */
1224   if (!prefix_ok(str1,"zWrLh")) return False;
1225   if (!check_share_info(uLevel,str2)) return False;
1226  
1227   *rdata = REALLOC(*rdata,mdrcnt);
1228   p = *rdata;
1229   *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1230   if (*rdata_len < 0) return False;
1231  
1232   *rparam_len = 6;
1233   *rparam = REALLOC(*rparam,*rparam_len);
1234   SSVAL(*rparam,0,NERR_Success);
1235   SSVAL(*rparam,2,0);           /* converter word */
1236   SSVAL(*rparam,4,*rdata_len);
1237  
1238   return(True);
1239 }
1240
1241 /****************************************************************************
1242   view list of shares available
1243   ****************************************************************************/
1244 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1245                               int mdrcnt,int mprcnt,
1246                               char **rdata,char **rparam,
1247                               int *rdata_len,int *rparam_len)
1248 {
1249   char *str1 = param+2;
1250   char *str2 = skip_string(str1,1);
1251   char *p = skip_string(str2,1);
1252   int uLevel = SVAL(p,0);
1253   int buf_len = SVAL(p,2);
1254   char *p2;
1255   int count=lp_numservices();
1256   int total=0,counted=0;
1257   int i;
1258   int data_len, fixed_len, string_len;
1259   int f_len, s_len;
1260  
1261   if (!prefix_ok(str1,"WrLeh")) return False;
1262   if (!check_share_info(uLevel,str2)) return False;
1263   
1264   data_len = fixed_len = string_len = 0;
1265   for (i=0;i<count;i++)
1266     if (lp_browseable(i) && lp_snum_ok(i))
1267       {
1268         total++;
1269         data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1270         if (data_len <= buf_len)
1271           {
1272             counted++;
1273             fixed_len += f_len;
1274             string_len += s_len;
1275           }
1276       }
1277   *rdata_len = fixed_len + string_len;
1278   *rdata = REALLOC(*rdata,*rdata_len);
1279   memset(*rdata,0,*rdata_len);
1280   
1281   p2 = (*rdata) + fixed_len;    /* auxillery data (strings) will go here */
1282   p = *rdata;
1283   f_len = fixed_len;
1284   s_len = string_len;
1285   for (i = 0; i < count;i++)
1286     if (lp_browseable(i) && lp_snum_ok(i))
1287       if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1288         break;
1289   
1290   *rparam_len = 8;
1291   *rparam = REALLOC(*rparam,*rparam_len);
1292   SSVAL(*rparam,0,NERR_Success);
1293   SSVAL(*rparam,2,0);
1294   SSVAL(*rparam,4,counted);
1295   SSVAL(*rparam,6,total);
1296   
1297   DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1298            counted,total,uLevel,
1299            buf_len,*rdata_len,mdrcnt));
1300   return(True);
1301 }
1302
1303
1304
1305 /****************************************************************************
1306   get the time of day info
1307   ****************************************************************************/
1308 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1309                              int mdrcnt,int mprcnt,
1310                              char **rdata,char **rparam,
1311                              int *rdata_len,int *rparam_len)
1312 {
1313   char *p;
1314   *rparam_len = 4;
1315   *rparam = REALLOC(*rparam,*rparam_len);
1316
1317   *rdata_len = 21;
1318   *rdata = REALLOC(*rdata,*rdata_len);
1319
1320   SSVAL(*rparam,0,NERR_Success);
1321   SSVAL(*rparam,2,0);           /* converter word */
1322
1323   p = *rdata;
1324
1325   {
1326     struct tm *t;
1327     time_t unixdate = time(NULL);
1328
1329     put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1330                                     by NT in a "net time" operation,
1331                                     it seems to ignore the one below */
1332
1333     /* the client expects to get localtime, not GMT, in this bit 
1334        (I think, this needs testing) */
1335     t = LocalTime(&unixdate);
1336
1337     SIVAL(p,4,0);               /* msecs ? */
1338     CVAL(p,8) = t->tm_hour;
1339     CVAL(p,9) = t->tm_min;
1340     CVAL(p,10) = t->tm_sec;
1341     CVAL(p,11) = 0;             /* hundredths of seconds */
1342     SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1343     SSVAL(p,14,10000);          /* timer interval in 0.0001 of sec */
1344     CVAL(p,16) = t->tm_mday;
1345     CVAL(p,17) = t->tm_mon + 1;
1346     SSVAL(p,18,1900+t->tm_year);
1347     CVAL(p,20) = t->tm_wday;
1348   }
1349
1350
1351   return(True);
1352 }
1353
1354 /****************************************************************************
1355   set the user password
1356   ****************************************************************************/
1357 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1358                                 int mdrcnt,int mprcnt,
1359                                 char **rdata,char **rparam,
1360                                 int *rdata_len,int *rparam_len)
1361 {
1362   char *p = skip_string(param+2,2);
1363   fstring user;
1364   fstring pass1,pass2;
1365
1366   fstrcpy(user,p);
1367
1368   p = skip_string(p,1);
1369
1370   StrnCpy(pass1,p,16);
1371   StrnCpy(pass2,p+16,16);
1372
1373   *rparam_len = 4;
1374   *rparam = REALLOC(*rparam,*rparam_len);
1375
1376   *rdata_len = 0;
1377
1378   SSVAL(*rparam,0,NERR_badpass);
1379   SSVAL(*rparam,2,0);           /* converter word */
1380
1381   DEBUG(3,("Set password for <%s>\n",user));
1382
1383   if (password_ok(user,pass1,strlen(pass1),NULL) &&
1384       chgpasswd(user,pass1,pass2))
1385   {
1386     SSVAL(*rparam,0,NERR_Success);
1387   }
1388
1389   bzero(pass1,sizeof(fstring));
1390   bzero(pass2,sizeof(fstring));  
1391          
1392   return(True);
1393 }
1394
1395 /****************************************************************************
1396   delete a print job
1397   Form: <W> <> 
1398   ****************************************************************************/
1399 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1400                                 int mdrcnt,int mprcnt,
1401                                 char **rdata,char **rparam,
1402                                 int *rdata_len,int *rparam_len)
1403 {
1404   int function = SVAL(param,0);
1405   char *str1 = param+2;
1406   char *str2 = skip_string(str1,1);
1407   char *p = skip_string(str2,1);
1408   int jobid, snum;
1409   int i, count;
1410
1411   printjob_decode(SVAL(p,0), &snum, &jobid);
1412
1413   /* check it's a supported varient */
1414   if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1415     return(False);
1416
1417   *rparam_len = 4;
1418   *rparam = REALLOC(*rparam,*rparam_len);
1419
1420   *rdata_len = 0;
1421
1422   SSVAL(*rparam,0,NERR_Success);
1423
1424   if (snum >= 0 && VALID_SNUM(snum))
1425     {
1426       print_queue_struct *queue=NULL;
1427       lpq_reset(snum);
1428       count = get_printqueue(snum,cnum,&queue,NULL);
1429   
1430       for (i=0;i<count;i++)
1431         if ((queue[i].job&0xFF) == jobid)
1432           {
1433             switch (function) {
1434             case 81:            /* delete */ 
1435               DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1436               del_printqueue(cnum,snum,queue[i].job);
1437               break;
1438             case 82:            /* pause */
1439             case 83:            /* resume */
1440               DEBUG(3,("%s queue entry %d\n",
1441                        (function==82?"pausing":"resuming"),queue[i].job));
1442               status_printjob(cnum,snum,queue[i].job,
1443                               (function==82?LPQ_PAUSED:LPQ_QUEUED));
1444               break;
1445             }
1446             break;
1447           }
1448   
1449       if (i==count)
1450         SSVAL(*rparam,0,NERR_JobNotFound);
1451
1452       if (queue) free(queue);
1453     }
1454
1455   SSVAL(*rparam,2,0);           /* converter word */
1456
1457   return(True);
1458 }
1459
1460 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1461                                  int mdrcnt,int mprcnt,
1462                                  char **rdata,char **rparam,
1463                                  int *rdata_len,int *rparam_len)
1464 {
1465   char *str1 = param+2;
1466   char *str2 = skip_string(str1,1);
1467   char *QueueName = skip_string(str2,1);
1468   int snum;
1469
1470   /* check it's a supported varient */
1471   if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1472     return(False);
1473
1474   *rparam_len = 4;
1475   *rparam = REALLOC(*rparam,*rparam_len);
1476
1477   *rdata_len = 0;
1478
1479   SSVAL(*rparam,0,NERR_Success);
1480   SSVAL(*rparam,2,0);           /* converter word */
1481
1482   snum = lp_servicenumber(QueueName);
1483   if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1484     int pnum = lp_servicenumber(PRINTERS_NAME);
1485     if (pnum >= 0) {
1486       lp_add_printer(QueueName,pnum);
1487       snum = lp_servicenumber(QueueName);
1488     }
1489   }
1490
1491   if (snum >= 0 && VALID_SNUM(snum)) {
1492     print_queue_struct *queue=NULL;
1493     int i, count;
1494     lpq_reset(snum);
1495     
1496     count = get_printqueue(snum,cnum,&queue,NULL);
1497     for (i = 0; i < count; i++)
1498       del_printqueue(cnum,snum,queue[i].job);
1499     
1500     if (queue) free(queue);
1501   }
1502
1503   DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1504
1505   return(True);
1506 }
1507
1508
1509 /****************************************************************************
1510   set the property of a print job (undocumented?)
1511   ? function = 0xb -> set name of print job
1512   ? function = 0x6 -> move print job up/down
1513   Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> 
1514   or   <WWsTP> <WB21BB16B10zWWzDDz> 
1515 ****************************************************************************/
1516 static int check_printjob_info(struct pack_desc* desc,
1517                                int uLevel, char* id)
1518 {
1519   desc->subformat = NULL;
1520   switch( uLevel ) {
1521   case 0: desc->format = "W"; break;
1522   case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1523   case 2: desc->format = "WWzWWDDzz"; break;
1524   case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1525   default: return False;
1526   }
1527   if (strcmp(desc->format,id) != 0) return False;
1528   return True;
1529 }
1530
1531 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1532                              int mdrcnt,int mprcnt,
1533                              char **rdata,char **rparam,
1534                              int *rdata_len,int *rparam_len)
1535 {
1536   struct pack_desc desc;
1537   char *str1 = param+2;
1538   char *str2 = skip_string(str1,1);
1539   char *p = skip_string(str2,1);
1540   int jobid, snum;
1541   int uLevel = SVAL(p,2);
1542   int function = SVAL(p,4);     /* what is this ?? */
1543   int i;
1544   char *s = data;
1545
1546   printjob_decode(SVAL(p,0), &snum, &jobid);
1547    
1548   *rparam_len = 4;
1549   *rparam = REALLOC(*rparam,*rparam_len);
1550   
1551   *rdata_len = 0;
1552   
1553   /* check it's a supported varient */
1554   if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1555     return(False);
1556    
1557   switch (function) {
1558   case 0x6:     /* change job place in the queue, data gives the new place */
1559     if (snum >= 0 && VALID_SNUM(snum))
1560       {
1561         print_queue_struct *queue=NULL;
1562         int count;
1563   
1564         lpq_reset(snum);
1565         count = get_printqueue(snum,cnum,&queue,NULL);
1566         for (i=0;i<count;i++)   /* find job */
1567           if ((queue[i].job&0xFF) == jobid) break;
1568             
1569         if (i==count) {
1570           desc.errcode=NERR_JobNotFound;
1571           if (queue) free(queue);
1572         }
1573         else {
1574           desc.errcode=NERR_Success;
1575           i++;
1576 #if 0   
1577           {
1578             int place= SVAL(data,0);
1579             /* we currently have no way of doing this. Can any unix do it? */
1580             if (i < place)      /* move down */;
1581             else if (i > place )        /* move up */;
1582           }
1583 #endif
1584           desc.errcode=NERR_notsupported; /* not yet supported */
1585           if (queue) free(queue);
1586         }
1587       }
1588     else desc.errcode=NERR_JobNotFound;
1589     break;
1590   case 0xb:   /* change print job name, data gives the name */
1591     /* jobid, snum should be zero */
1592     if (isalpha(*s))
1593       {
1594         pstring name;
1595         int l = 0;
1596         while (l<64 && *s)
1597           {
1598             if (issafe(*s)) name[l++] = *s;
1599             s++;
1600           }      
1601         name[l] = 0;
1602         
1603         DEBUG(3,("Setting print name to %s\n",name));
1604         
1605         become_root(True);
1606
1607         for (i=0;i<MAX_OPEN_FILES;i++)
1608           if (Files[i].open && Files[i].print_file)
1609             {
1610               pstring wd;
1611               GetWd(wd);
1612               unbecome_user();
1613               
1614               if (!become_user(Files[i].cnum,vuid) || 
1615                   !become_service(Files[i].cnum,True))
1616                 break;
1617               
1618               if (sys_rename(Files[i].name,name) == 0)
1619                 string_set(&Files[i].name,name);
1620               break;
1621             }
1622
1623          unbecome_root(True);
1624       }
1625     desc.errcode=NERR_Success;
1626   
1627     break;
1628   default:                      /* not implemented */
1629     return False;
1630   }
1631  
1632   SSVALS(*rparam,0,desc.errcode);
1633   SSVAL(*rparam,2,0);           /* converter word */
1634   
1635   return(True);
1636 }
1637
1638
1639 /****************************************************************************
1640   get info about the server
1641   ****************************************************************************/
1642 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1643                                   int mdrcnt,int mprcnt,
1644                                   char **rdata,char **rparam,
1645                                   int *rdata_len,int *rparam_len)
1646 {
1647   char *str1 = param+2;
1648   char *str2 = skip_string(str1,1);
1649   char *p = skip_string(str2,1);
1650   int uLevel = SVAL(p,0);
1651   char *p2;
1652   int struct_len;
1653
1654   DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1655
1656   /* check it's a supported varient */
1657   if (!prefix_ok(str1,"WrLh")) return False;
1658   switch( uLevel ) {
1659   case 0:
1660     if (strcmp(str2,"B16") != 0) return False;
1661     struct_len = 16;
1662     break;
1663   case 1:
1664     if (strcmp(str2,"B16BBDz") != 0) return False;
1665     struct_len = 26;
1666     break;
1667   case 2:
1668     if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1669         != 0) return False;
1670     struct_len = 134;
1671     break;
1672   case 3:
1673     if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1674         != 0) return False;
1675     struct_len = 144;
1676     break;
1677   case 20:
1678     if (strcmp(str2,"DN") != 0) return False;
1679     struct_len = 6;
1680     break;
1681   case 50:
1682     if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1683     struct_len = 42;
1684     break;
1685   default: return False;
1686   }
1687
1688   *rdata_len = mdrcnt;
1689   *rdata = REALLOC(*rdata,*rdata_len);
1690
1691   p = *rdata;
1692   p2 = p + struct_len;
1693   if (uLevel != 20) {
1694     StrnCpy(p,local_machine,16);
1695     strupper(p);
1696   }
1697   p += 16;
1698   if (uLevel > 0)
1699     {
1700       struct srv_info_struct *servers=NULL;
1701       int i,count;
1702       pstring comment;
1703       uint32 servertype= lp_default_server_announce();
1704
1705       pstrcpy(comment,lp_serverstring());
1706
1707       if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1708         for (i=0;i<count;i++)
1709           if (strequal(servers[i].name,local_machine))
1710       {
1711             servertype = servers[i].type;
1712             pstrcpy(comment,servers[i].comment);            
1713           }
1714       }
1715       if (servers) free(servers);
1716
1717       SCVAL(p,0,lp_major_announce_version());
1718       SCVAL(p,1,lp_minor_announce_version());
1719       SIVAL(p,2,servertype);
1720
1721       if (mdrcnt == struct_len) {
1722         SIVAL(p,6,0);
1723       } else {
1724         SIVAL(p,6,PTR_DIFF(p2,*rdata));
1725         standard_sub(cnum,comment);
1726         StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1727         p2 = skip_string(p2,1);
1728       }
1729     }
1730   if (uLevel > 1)
1731     {
1732       return False;             /* not yet implemented */
1733     }
1734
1735   *rdata_len = PTR_DIFF(p2,*rdata);
1736
1737   *rparam_len = 6;
1738   *rparam = REALLOC(*rparam,*rparam_len);
1739   SSVAL(*rparam,0,NERR_Success);
1740   SSVAL(*rparam,2,0);           /* converter word */
1741   SSVAL(*rparam,4,*rdata_len);
1742
1743   return(True);
1744 }
1745
1746
1747 /****************************************************************************
1748   get info about the server
1749   ****************************************************************************/
1750 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1751                                 int mdrcnt,int mprcnt,
1752                                 char **rdata,char **rparam,
1753                                 int *rdata_len,int *rparam_len)
1754 {
1755   char *str1 = param+2;
1756   char *str2 = skip_string(str1,1);
1757   char *p = skip_string(str2,1);
1758   char *p2;
1759   extern pstring sesssetup_user;
1760   int level = SVAL(p,0);
1761
1762   DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1763
1764   *rparam_len = 6;
1765   *rparam = REALLOC(*rparam,*rparam_len);
1766
1767   /* check it's a supported varient */
1768   if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1769     return(False);
1770
1771   *rdata_len = mdrcnt + 1024;
1772   *rdata = REALLOC(*rdata,*rdata_len);
1773
1774   SSVAL(*rparam,0,NERR_Success);
1775   SSVAL(*rparam,2,0);           /* converter word */
1776
1777   p = *rdata;
1778   p2 = p + 22;
1779
1780
1781   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1782   strcpy(p2,local_machine);
1783   strupper(p2);
1784   p2 = skip_string(p2,1);
1785   p += 4;
1786
1787   SIVAL(p,0,PTR_DIFF(p2,*rdata));
1788   strcpy(p2,sesssetup_user);
1789   p2 = skip_string(p2,1);
1790   p += 4;
1791
1792   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1793   strcpy(p2,myworkgroup);
1794   strupper(p2);
1795   p2 = skip_string(p2,1);
1796   p += 4;
1797
1798   SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1799   SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1800   p += 2;
1801
1802   SIVAL(p,0,PTR_DIFF(p2,*rdata));
1803   strcpy(p2,myworkgroup);       /* don't know.  login domain?? */
1804   p2 = skip_string(p2,1);
1805   p += 4;
1806
1807   SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1808   strcpy(p2,"");
1809   p2 = skip_string(p2,1);
1810   p += 4;
1811
1812   *rdata_len = PTR_DIFF(p2,*rdata);
1813
1814   SSVAL(*rparam,4,*rdata_len);
1815
1816   return(True);
1817 }
1818
1819 /****************************************************************************
1820   get info about a user
1821
1822     struct user_info_11 {
1823         char                usri11_name[21];  0-20 
1824         char                usri11_pad;       21 
1825         char                *usri11_comment;  22-25 
1826         char            *usri11_usr_comment;  26-29
1827         unsigned short      usri11_priv;      30-31
1828         unsigned long       usri11_auth_flags; 32-35
1829         long                usri11_password_age; 36-39
1830         char                *usri11_homedir; 40-43
1831         char            *usri11_parms; 44-47
1832         long                usri11_last_logon; 48-51
1833         long                usri11_last_logoff; 52-55
1834         unsigned short      usri11_bad_pw_count; 56-57
1835         unsigned short      usri11_num_logons; 58-59
1836         char                *usri11_logon_server; 60-63
1837         unsigned short      usri11_country_code; 64-65
1838         char            *usri11_workstations; 66-69
1839         unsigned long       usri11_max_storage; 70-73
1840         unsigned short      usri11_units_per_week; 74-75
1841         unsigned char       *usri11_logon_hours; 76-79
1842         unsigned short      usri11_code_page; 80-81
1843     };
1844
1845 where:
1846
1847   usri11_name specifies the user name for which information is retireved
1848
1849   usri11_pad aligns the next data structure element to a word boundary
1850
1851   usri11_comment is a null terminated ASCII comment
1852
1853   usri11_user_comment is a null terminated ASCII comment about the user
1854
1855   usri11_priv specifies the level of the privilege assigned to the user.
1856        The possible values are:
1857
1858 Name             Value  Description
1859 USER_PRIV_GUEST  0      Guest privilege
1860 USER_PRIV_USER   1      User privilege
1861 USER_PRV_ADMIN   2      Administrator privilege
1862
1863   usri11_auth_flags specifies the account operator privileges. The
1864        possible values are:
1865
1866 Name            Value   Description
1867 AF_OP_PRINT     0       Print operator
1868
1869
1870 Leach, Naik                                        [Page 28]\r\f
1871
1872
1873 INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
1874
1875
1876 AF_OP_COMM      1       Communications operator
1877 AF_OP_SERVER    2       Server operator
1878 AF_OP_ACCOUNTS  3       Accounts operator
1879
1880
1881   usri11_password_age specifies how many seconds have elapsed since the
1882        password was last changed.
1883
1884   usri11_home_dir points to a null terminated ASCII string that contains
1885        the path name of the user's home directory.
1886
1887   usri11_parms points to a null terminated ASCII string that is set
1888        aside for use by applications.
1889
1890   usri11_last_logon specifies the time when the user last logged on.
1891        This value is stored as the number of seconds elapsed since
1892        00:00:00, January 1, 1970.
1893
1894   usri11_last_logoff specifies the time when the user last logged off.
1895        This value is stored as the number of seconds elapsed since
1896        00:00:00, January 1, 1970. A value of 0 means the last logoff
1897        time is unknown.
1898
1899   usri11_bad_pw_count specifies the number of incorrect passwords
1900        entered since the last successful logon.
1901
1902   usri11_log1_num_logons specifies the number of times this user has
1903        logged on. A value of -1 means the number of logons is unknown.
1904
1905   usri11_logon_server points to a null terminated ASCII string that
1906        contains the name of the server to which logon requests are sent.
1907        A null string indicates logon requests should be sent to the
1908        domain controller.
1909
1910   usri11_country_code specifies the country code for the user's language
1911        of choice.
1912
1913   usri11_workstations points to a null terminated ASCII string that
1914        contains the names of workstations the user may log on from.
1915        There may be up to 8 workstations, with the names separated by
1916        commas. A null strings indicates there are no restrictions.
1917
1918   usri11_max_storage specifies the maximum amount of disk space the user
1919        can occupy. A value of 0xffffffff indicates there are no
1920        restrictions.
1921
1922   usri11_units_per_week specifies the equal number of time units into
1923        which a week is divided. This value must be equal to 168.
1924
1925   usri11_logon_hours points to a 21 byte (168 bits) string that
1926        specifies the time during which the user can log on. Each bit
1927        represents one unique hour in a week. The first bit (bit 0, word
1928        0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1929
1930
1931
1932 Leach, Naik                                        [Page 29]\r\f
1933
1934
1935 INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
1936
1937
1938        Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1939        are no restrictions.
1940
1941   usri11_code_page specifies the code page for the user's language of
1942        choice
1943
1944 All of the pointers in this data structure need to be treated
1945 specially. The  pointer is a 32 bit pointer. The higher 16 bits need
1946 to be ignored. The converter word returned in the parameters section
1947 needs to be subtracted from the lower 16 bits to calculate an offset
1948 into the return buffer where this ASCII string resides.
1949
1950 There is no auxiliary data in the response.
1951
1952   ****************************************************************************/
1953
1954 #define usri11_name           0 
1955 #define usri11_pad            21
1956 #define usri11_comment        22
1957 #define usri11_usr_comment    26
1958 #define usri11_full_name      30
1959 #define usri11_priv           34
1960 #define usri11_auth_flags     36
1961 #define usri11_password_age   40
1962 #define usri11_homedir        44
1963 #define usri11_parms          48
1964 #define usri11_last_logon     52
1965 #define usri11_last_logoff    56
1966 #define usri11_bad_pw_count   60
1967 #define usri11_num_logons     62
1968 #define usri11_logon_server   64
1969 #define usri11_country_code   68
1970 #define usri11_workstations   70
1971 #define usri11_max_storage    74
1972 #define usri11_units_per_week 78
1973 #define usri11_logon_hours    80
1974 #define usri11_code_page      84
1975 #define usri11_end            86
1976
1977 #define USER_PRIV_GUEST 0
1978 #define USER_PRIV_USER 1
1979 #define USER_PRIV_ADMIN 2
1980
1981 #define AF_OP_PRINT     0 
1982 #define AF_OP_COMM      1
1983 #define AF_OP_SERVER    2
1984 #define AF_OP_ACCOUNTS  3
1985
1986
1987 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1988                                 int mdrcnt,int mprcnt,
1989                                 char **rdata,char **rparam,
1990                                 int *rdata_len,int *rparam_len)
1991 {
1992         char *str1 = param+2;
1993         char *str2 = skip_string(str1,1);
1994         char *UserName = skip_string(str2,1);
1995         char *p = skip_string(UserName,1);
1996         int uLevel = SVAL(p,0);
1997         char *p2;
1998
1999     /* get NIS home of a previously validated user - simeon */
2000     user_struct *vuser = get_valid_user_struct(vuid);
2001     DEBUG(3,("  Username of UID %d is %s\n", vuser->uid, vuser->name));
2002 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2003     DEBUG(3,("  HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
2004 #endif
2005
2006     *rparam_len = 6;
2007     *rparam = REALLOC(*rparam,*rparam_len);
2008   
2009         /* check it's a supported variant */
2010         if (strcmp(str1,"zWrLh") != 0) return False;
2011         switch( uLevel )
2012         {
2013                 case 0: p2 = "B21"; break;
2014                 case 1: p2 = "B21BB16DWzzWz"; break;
2015                 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2016                 case 10: p2 = "B21Bzzz"; break;
2017                 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2018                 default: return False;
2019         }
2020
2021         if (strcmp(p2,str2) != 0) return False;
2022
2023         *rdata_len = mdrcnt + 1024;
2024         *rdata = REALLOC(*rdata,*rdata_len);
2025
2026         SSVAL(*rparam,0,NERR_Success);
2027         SSVAL(*rparam,2,0);             /* converter word */
2028
2029         p = *rdata;
2030         p2 = p + usri11_end;
2031
2032         memset(p,0,21); 
2033         fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2034
2035         if (uLevel > 0)
2036         {
2037                 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2038                 *p2 = 0;
2039         }
2040         if (uLevel >= 10)
2041         {
2042                 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2043                 strcpy(p2,"Comment");
2044                 p2 = skip_string(p2,1);
2045
2046                 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2047                 strcpy(p2,"UserComment");
2048                 p2 = skip_string(p2,1);
2049
2050                 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2051                 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2052                 strcpy(p2,vuser->real_name);    /* simeon */
2053                 p2 = skip_string(p2,1);
2054         }
2055
2056         if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2057         {         
2058                 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
2059                 SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
2060                 SIVALS(p,usri11_password_age,0xffffffff);               /* password age */
2061                 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2062                 if (*lp_logon_path())
2063                 {
2064                         strcpy(p2,lp_logon_path());
2065                 }
2066                 else
2067                 {
2068 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2069                         strcpy(p2, vuser->home_share);
2070 #else
2071                         strcpy(p2,"\\\\%L\\%U");
2072 #endif
2073                 }
2074                 standard_sub_basic(p2);
2075                 p2 = skip_string(p2,1);
2076                 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2077                 strcpy(p2,"");
2078                 p2 = skip_string(p2,1);
2079                 SIVAL(p,usri11_last_logon,0);           /* last logon */
2080                 SIVAL(p,usri11_last_logoff,0);          /* last logoff */
2081                 SSVALS(p,usri11_bad_pw_count,0xffffffff);               /* bad pw counts */
2082                 SSVALS(p,usri11_num_logons,0xffffffff);         /* num logons */
2083                 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2084                 strcpy(p2,"\\\\*");
2085                 p2 = skip_string(p2,1);
2086                 SSVAL(p,usri11_country_code,0);         /* country code */
2087
2088                 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2089                 strcpy(p2,"");
2090                 p2 = skip_string(p2,1);
2091
2092                 SIVALS(p,usri11_max_storage,0xffffffff);                /* max storage */
2093                 SSVAL(p,usri11_units_per_week,168);             /* units per week */
2094                 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2095
2096                 /* a simple way to get logon hours at all times. */
2097                 memset(p2,0xff,21);
2098                 SCVAL(p2,21,0);           /* fix zero termination */
2099                 p2 = skip_string(p2,1);
2100
2101                 SSVAL(p,usri11_code_page,0);            /* code page */
2102         }
2103         if (uLevel == 1 || uLevel == 2)
2104         {
2105                 memset(p+22,' ',16);    /* password */
2106                 SIVALS(p,38,-1);                /* password age */
2107                 SSVAL(p,42,
2108                 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2109                 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2110                 if (*lp_logon_path())
2111                 {
2112                         strcpy(p2,lp_logon_path());
2113                 }
2114                 else
2115                 {
2116 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2117             strcpy(p2, vuser->home_share);
2118 #else
2119                         strcpy(p2,"\\\\%L\\%U");
2120 #endif
2121                 }
2122                 standard_sub_basic(p2);
2123                 p2 = skip_string(p2,1);
2124                 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2125                 *p2++ = 0;
2126                 SSVAL(p,52,0);          /* flags */
2127                 SIVAL(p,54,0);          /* script_path */
2128                 if (uLevel == 2)
2129                 {
2130                         SIVAL(p,60,0);          /* auth_flags */
2131                         SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2132                         strcpy(p2,vuser->real_name);    /* simeon */
2133                         p2 = skip_string(p2,1);
2134                         SIVAL(p,68,0);          /* urs_comment */
2135                         SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2136                         strcpy(p2,"");
2137                         p2 = skip_string(p2,1);
2138                         SIVAL(p,76,0);          /* workstations */
2139                         SIVAL(p,80,0);          /* last_logon */
2140                         SIVAL(p,84,0);          /* last_logoff */
2141                         SIVALS(p,88,-1);                /* acct_expires */
2142                         SIVALS(p,92,-1);                /* max_storage */
2143                         SSVAL(p,96,168);        /* units_per_week */
2144                         SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2145                         memset(p2,-1,21);
2146                         p2 += 21;
2147                         SSVALS(p,102,-1);       /* bad_pw_count */
2148                         SSVALS(p,104,-1);       /* num_logons */
2149                         SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2150                         strcpy(p2,"\\\\%L");
2151                         standard_sub_basic(p2);
2152                         p2 = skip_string(p2,1);
2153                         SSVAL(p,110,49);        /* country_code */
2154                         SSVAL(p,112,860);       /* code page */
2155                 }
2156         }
2157
2158         *rdata_len = PTR_DIFF(p2,*rdata);
2159
2160         SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
2161
2162         return(True);
2163 }
2164
2165 /*******************************************************************
2166   get groups that a user is a member of
2167   ******************************************************************/
2168 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2169                                  int mdrcnt,int mprcnt,
2170                                  char **rdata,char **rparam,
2171                                  int *rdata_len,int *rparam_len)
2172 {
2173   char *str1 = param+2;
2174   char *str2 = skip_string(str1,1);
2175   char *UserName = skip_string(str2,1);
2176   char *p = skip_string(UserName,1);
2177   int uLevel = SVAL(p,0);
2178   char *p2;
2179   int count=0;
2180
2181   *rparam_len = 8;
2182   *rparam = REALLOC(*rparam,*rparam_len);
2183
2184   /* check it's a supported varient */
2185   if (strcmp(str1,"zWrLeh") != 0) return False;
2186   switch( uLevel ) {
2187   case 0: p2 = "B21"; break;
2188   default: return False;
2189   }
2190   if (strcmp(p2,str2) != 0) return False;
2191
2192   *rdata_len = mdrcnt + 1024;
2193   *rdata = REALLOC(*rdata,*rdata_len);
2194
2195   SSVAL(*rparam,0,NERR_Success);
2196   SSVAL(*rparam,2,0);           /* converter word */
2197
2198   p = *rdata;
2199
2200   /* XXXX we need a real SAM database some day */
2201   strcpy(p,"Users"); p += 21; count++;
2202   strcpy(p,"Domain Users"); p += 21; count++;
2203   strcpy(p,"Guests"); p += 21; count++;
2204   strcpy(p,"Domain Guests"); p += 21; count++;
2205
2206   *rdata_len = PTR_DIFF(p,*rdata);
2207
2208   SSVAL(*rparam,4,count);       /* is this right?? */
2209   SSVAL(*rparam,6,count);       /* is this right?? */
2210
2211   return(True);
2212 }
2213
2214
2215 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2216                                 int mdrcnt,int mprcnt,
2217                                 char **rdata,char **rparam,
2218                                 int *rdata_len,int *rparam_len)
2219 {
2220   char *str1 = param+2;
2221   char *str2 = skip_string(str1,1);
2222   char *p = skip_string(str2,1);
2223   int uLevel;
2224   struct pack_desc desc;
2225   char* name;
2226   char* logon_script;
2227
2228   uLevel = SVAL(p,0);
2229   name = p + 2;
2230
2231   bzero(&desc,sizeof(desc));
2232
2233   DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2234
2235   /* check it's a supported varient */
2236   if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2237   if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2238   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2239   desc.base = *rdata;
2240   desc.buflen = mdrcnt;
2241   desc.subformat = NULL;
2242   desc.format = str2;
2243   
2244   if (init_package(&desc,1,0))
2245   {
2246     PACKI(&desc,"W",0);         /* code */
2247     PACKS(&desc,"B21",name);    /* eff. name */
2248     PACKS(&desc,"B","");                /* pad */
2249     PACKI(&desc,"W",
2250           Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2251     PACKI(&desc,"D",0);         /* auth flags XXX */
2252     PACKI(&desc,"W",0);         /* num logons */
2253     PACKI(&desc,"W",0);         /* bad pw count */
2254     PACKI(&desc,"D",0);         /* last logon */
2255     PACKI(&desc,"D",-1);                /* last logoff */
2256     PACKI(&desc,"D",-1);                /* logoff time */
2257     PACKI(&desc,"D",-1);                /* kickoff time */
2258     PACKI(&desc,"D",0);         /* password age */
2259     PACKI(&desc,"D",0);         /* password can change */
2260     PACKI(&desc,"D",-1);                /* password must change */
2261     {
2262       fstring mypath;
2263       strcpy(mypath,"\\\\");
2264       strcat(mypath,local_machine);
2265       strupper(mypath);
2266       PACKS(&desc,"z",mypath); /* computer */
2267     }
2268     PACKS(&desc,"z",myworkgroup);/* domain */
2269
2270 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2271 /* made sure all macros are fully substituted and available */
2272     logon_script = lp_logon_script();
2273     standard_sub( cnum, logon_script );
2274     PACKS(&desc,"z", logon_script);             /* script path */
2275 /* End of JHT mods */
2276
2277     PACKI(&desc,"D",0x00000000);                /* reserved */
2278   }
2279
2280   *rdata_len = desc.usedlen;
2281   *rparam_len = 6;
2282   *rparam = REALLOC(*rparam,*rparam_len);
2283   SSVALS(*rparam,0,desc.errcode);
2284   SSVAL(*rparam,2,0);
2285   SSVAL(*rparam,4,desc.neededlen);
2286
2287   DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2288   return(True);
2289 }
2290
2291
2292 /****************************************************************************
2293   api_WAccessGetUserPerms
2294   ****************************************************************************/
2295 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2296                                     int mdrcnt,int mprcnt,
2297                                     char **rdata,char **rparam,
2298                                     int *rdata_len,int *rparam_len)
2299 {
2300   char *str1 = param+2;
2301   char *str2 = skip_string(str1,1);
2302   char *user = skip_string(str2,1);
2303   char *resource = skip_string(user,1);
2304
2305   DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2306
2307   /* check it's a supported varient */
2308   if (strcmp(str1,"zzh") != 0) return False;
2309   if (strcmp(str2,"") != 0) return False;
2310
2311   *rparam_len = 6;
2312   *rparam = REALLOC(*rparam,*rparam_len);
2313   SSVALS(*rparam,0,0);          /* errorcode */
2314   SSVAL(*rparam,2,0);           /* converter word */
2315   SSVAL(*rparam,4,0x7f);        /* permission flags */
2316
2317   return(True);
2318 }
2319
2320 /****************************************************************************
2321   api_WPrintJobEnumerate
2322   ****************************************************************************/
2323 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2324                                  int mdrcnt,int mprcnt,
2325                                  char **rdata,char **rparam,
2326                                  int *rdata_len,int *rparam_len)
2327 {
2328   char *str1 = param+2;
2329   char *str2 = skip_string(str1,1);
2330   char *p = skip_string(str2,1);
2331   int uLevel,cbBuf;
2332   int count;
2333   int i;
2334   int snum;
2335   int job;
2336   struct pack_desc desc;
2337   print_queue_struct *queue=NULL;
2338   print_status_struct status;
2339
2340   uLevel = SVAL(p,2);
2341   cbBuf = SVAL(p,4);
2342
2343   bzero(&desc,sizeof(desc));
2344   bzero(&status,sizeof(status));
2345
2346   DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2347
2348   /* check it's a supported varient */
2349   if (strcmp(str1,"WWrLh") != 0) return False;
2350   if (!check_printjob_info(&desc,uLevel,str2)) return False;
2351
2352   printjob_decode(SVAL(p,0), &snum, &job);
2353
2354   if (snum < 0 || !VALID_SNUM(snum)) return(False);
2355
2356   count = get_printqueue(snum,cnum,&queue,&status);
2357   for (i = 0; i < count; i++) {
2358     if ((queue[i].job & 0xFF) == job) break;
2359   }
2360   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2361   desc.base = *rdata;
2362   desc.buflen = mdrcnt;
2363
2364   if (init_package(&desc,1,0)) {
2365     if (i < count) {
2366       fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2367       *rdata_len = desc.usedlen;
2368     }
2369     else {
2370       desc.errcode = NERR_JobNotFound;
2371       *rdata_len = 0;
2372     }
2373   }
2374
2375   *rparam_len = 6;
2376   *rparam = REALLOC(*rparam,*rparam_len);
2377   SSVALS(*rparam,0,desc.errcode);
2378   SSVAL(*rparam,2,0);
2379   SSVAL(*rparam,4,desc.neededlen);
2380
2381   if (queue) free(queue);
2382
2383   DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2384   return(True);
2385 }
2386
2387 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2388                                    int mdrcnt,int mprcnt,
2389                                    char **rdata,char **rparam,
2390                                    int *rdata_len,int *rparam_len)
2391 {
2392   char *str1 = param+2;
2393   char *str2 = skip_string(str1,1);
2394   char *p = skip_string(str2,1);
2395   char* name = p;
2396   int uLevel,cbBuf;
2397   int count;
2398   int i, succnt=0;
2399   int snum;
2400   struct pack_desc desc;
2401   print_queue_struct *queue=NULL;
2402   print_status_struct status;
2403
2404   bzero(&desc,sizeof(desc));
2405   bzero(&status,sizeof(status));
2406
2407   p = skip_string(p,1);
2408   uLevel = SVAL(p,0);
2409   cbBuf = SVAL(p,2);
2410
2411   DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2412
2413   /* check it's a supported varient */
2414   if (strcmp(str1,"zWrLeh") != 0) return False;
2415   if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2416   if (!check_printjob_info(&desc,uLevel,str2)) return False;
2417
2418   snum = lp_servicenumber(name);
2419   if (snum < 0 && pcap_printername_ok(name,NULL)) {
2420     int pnum = lp_servicenumber(PRINTERS_NAME);
2421     if (pnum >= 0) {
2422       lp_add_printer(name,pnum);
2423       snum = lp_servicenumber(name);
2424     }
2425   }
2426
2427   if (snum < 0 || !VALID_SNUM(snum)) return(False);
2428
2429   count = get_printqueue(snum,cnum,&queue,&status);
2430   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2431   desc.base = *rdata;
2432   desc.buflen = mdrcnt;
2433
2434   if (init_package(&desc,count,0)) {
2435     succnt = 0;
2436     for (i = 0; i < count; i++) {
2437       fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2438       if (desc.errcode == NERR_Success) succnt = i+1;
2439     }
2440   }
2441
2442   *rdata_len = desc.usedlen;
2443
2444   *rparam_len = 8;
2445   *rparam = REALLOC(*rparam,*rparam_len);
2446   SSVALS(*rparam,0,desc.errcode);
2447   SSVAL(*rparam,2,0);
2448   SSVAL(*rparam,4,succnt);
2449   SSVAL(*rparam,6,count);
2450
2451   if (queue) free(queue);
2452
2453   DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2454   return(True);
2455 }
2456
2457 static int check_printdest_info(struct pack_desc* desc,
2458                                 int uLevel, char* id)
2459 {
2460   desc->subformat = NULL;
2461   switch( uLevel ) {
2462   case 0: desc->format = "B9"; break;
2463   case 1: desc->format = "B9B21WWzW"; break;
2464   case 2: desc->format = "z"; break;
2465   case 3: desc->format = "zzzWWzzzWW"; break;
2466   default: return False;
2467   }
2468   if (strcmp(desc->format,id) != 0) return False;
2469   return True;
2470 }
2471
2472 static void fill_printdest_info(int cnum, int snum, int uLevel,
2473                                 struct pack_desc* desc)
2474 {
2475   char buf[100];
2476   strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2477   buf[sizeof(buf)-1] = 0;
2478   strupper(buf);
2479   if (uLevel <= 1) {
2480     PACKS(desc,"B9",buf);       /* szName */
2481     if (uLevel == 1) {
2482       PACKS(desc,"B21","");     /* szUserName */
2483       PACKI(desc,"W",0);                /* uJobId */
2484       PACKI(desc,"W",0);                /* fsStatus */
2485       PACKS(desc,"z","");       /* pszStatus */
2486       PACKI(desc,"W",0);                /* time */
2487     }
2488   }
2489   if (uLevel == 2 || uLevel == 3) {
2490     PACKS(desc,"z",buf);                /* pszPrinterName */
2491     if (uLevel == 3) {
2492       PACKS(desc,"z","");       /* pszUserName */
2493       PACKS(desc,"z","");       /* pszLogAddr */
2494       PACKI(desc,"W",0);                /* uJobId */
2495       PACKI(desc,"W",0);                /* fsStatus */
2496       PACKS(desc,"z","");       /* pszStatus */
2497       PACKS(desc,"z","");       /* pszComment */
2498       PACKS(desc,"z","NULL"); /* pszDrivers */
2499       PACKI(desc,"W",0);                /* time */
2500       PACKI(desc,"W",0);                /* pad1 */
2501     }
2502   }
2503 }
2504
2505 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2506                                   int mdrcnt,int mprcnt,
2507                                   char **rdata,char **rparam,
2508                                   int *rdata_len,int *rparam_len)
2509 {
2510   char *str1 = param+2;
2511   char *str2 = skip_string(str1,1);
2512   char *p = skip_string(str2,1);
2513   char* PrinterName = p;
2514   int uLevel,cbBuf;
2515   struct pack_desc desc;
2516   int snum;
2517
2518   bzero(&desc,sizeof(desc));
2519
2520   p = skip_string(p,1);
2521   uLevel = SVAL(p,0);
2522   cbBuf = SVAL(p,2);
2523
2524   DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2525
2526   /* check it's a supported varient */
2527   if (strcmp(str1,"zWrLh") != 0) return False;
2528   if (!check_printdest_info(&desc,uLevel,str2)) return False;
2529
2530   snum = lp_servicenumber(PrinterName);
2531   if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2532     int pnum = lp_servicenumber(PRINTERS_NAME);
2533     if (pnum >= 0) {
2534       lp_add_printer(PrinterName,pnum);
2535       snum = lp_servicenumber(PrinterName);
2536     }
2537   }
2538
2539   if (snum < 0) {
2540     *rdata_len = 0;
2541     desc.errcode = NERR_DestNotFound;
2542     desc.neededlen = 0;
2543   }
2544   else {
2545     if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2546     desc.base = *rdata;
2547     desc.buflen = mdrcnt;
2548     if (init_package(&desc,1,0)) {
2549       fill_printdest_info(cnum,snum,uLevel,&desc);
2550     }
2551     *rdata_len = desc.usedlen;
2552   }
2553
2554   *rparam_len = 6;
2555   *rparam = REALLOC(*rparam,*rparam_len);
2556   SSVALS(*rparam,0,desc.errcode);
2557   SSVAL(*rparam,2,0);
2558   SSVAL(*rparam,4,desc.neededlen);
2559
2560   DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2561   return(True);
2562 }
2563
2564 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2565                                int mdrcnt,int mprcnt,
2566                                char **rdata,char **rparam,
2567                                int *rdata_len,int *rparam_len)
2568 {
2569   char *str1 = param+2;
2570   char *str2 = skip_string(str1,1);
2571   char *p = skip_string(str2,1);
2572   int uLevel,cbBuf;
2573   int queuecnt;
2574   int i, n, succnt=0;
2575   struct pack_desc desc;
2576   int services = lp_numservices();
2577
2578   bzero(&desc,sizeof(desc));
2579
2580   uLevel = SVAL(p,0);
2581   cbBuf = SVAL(p,2);
2582
2583   DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2584
2585   /* check it's a supported varient */
2586   if (strcmp(str1,"WrLeh") != 0) return False;
2587   if (!check_printdest_info(&desc,uLevel,str2)) return False;
2588
2589   queuecnt = 0;
2590   for (i = 0; i < services; i++)
2591     if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2592       queuecnt++;
2593
2594   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2595   desc.base = *rdata;
2596   desc.buflen = mdrcnt;
2597   if (init_package(&desc,queuecnt,0)) {    
2598     succnt = 0;
2599     n = 0;
2600     for (i = 0; i < services; i++) {
2601       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2602         fill_printdest_info(cnum,i,uLevel,&desc);
2603         n++;
2604         if (desc.errcode == NERR_Success) succnt = n;
2605       }
2606     }
2607   }
2608
2609   *rdata_len = desc.usedlen;
2610
2611   *rparam_len = 8;
2612   *rparam = REALLOC(*rparam,*rparam_len);
2613   SSVALS(*rparam,0,desc.errcode);
2614   SSVAL(*rparam,2,0);
2615   SSVAL(*rparam,4,succnt);
2616   SSVAL(*rparam,6,queuecnt);
2617
2618   DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2619   return(True);
2620 }
2621
2622 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2623                                  int mdrcnt,int mprcnt,
2624                                  char **rdata,char **rparam,
2625                                  int *rdata_len,int *rparam_len)
2626 {
2627   char *str1 = param+2;
2628   char *str2 = skip_string(str1,1);
2629   char *p = skip_string(str2,1);
2630   int uLevel,cbBuf;
2631   int succnt;
2632   struct pack_desc desc;
2633
2634   bzero(&desc,sizeof(desc));
2635
2636   uLevel = SVAL(p,0);
2637   cbBuf = SVAL(p,2);
2638
2639   DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2640
2641   /* check it's a supported varient */
2642   if (strcmp(str1,"WrLeh") != 0) return False;
2643   if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2644
2645   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2646   desc.base = *rdata;
2647   desc.buflen = mdrcnt;
2648   if (init_package(&desc,1,0)) {
2649     PACKS(&desc,"B41","NULL");
2650   }
2651
2652   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2653
2654   *rdata_len = desc.usedlen;
2655
2656   *rparam_len = 8;
2657   *rparam = REALLOC(*rparam,*rparam_len);
2658   SSVALS(*rparam,0,desc.errcode);
2659   SSVAL(*rparam,2,0);
2660   SSVAL(*rparam,4,succnt);
2661   SSVAL(*rparam,6,1);
2662
2663   DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2664   return(True);
2665 }
2666
2667 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2668                                 int mdrcnt,int mprcnt,
2669                                 char **rdata,char **rparam,
2670                                 int *rdata_len,int *rparam_len)
2671 {
2672   char *str1 = param+2;
2673   char *str2 = skip_string(str1,1);
2674   char *p = skip_string(str2,1);
2675   int uLevel,cbBuf;
2676   int succnt;
2677   struct pack_desc desc;
2678
2679   bzero(&desc,sizeof(desc));
2680
2681   uLevel = SVAL(p,0);
2682   cbBuf = SVAL(p,2);
2683
2684   DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2685
2686   /* check it's a supported varient */
2687   if (strcmp(str1,"WrLeh") != 0) return False;
2688   if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2689
2690   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2691   desc.base = *rdata;
2692   desc.buflen = mdrcnt;
2693   desc.format = str2;
2694   if (init_package(&desc,1,0)) {
2695     PACKS(&desc,"B13","lpd");
2696   }
2697
2698   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2699
2700   *rdata_len = desc.usedlen;
2701
2702   *rparam_len = 8;
2703   *rparam = REALLOC(*rparam,*rparam_len);
2704   SSVALS(*rparam,0,desc.errcode);
2705   SSVAL(*rparam,2,0);
2706   SSVAL(*rparam,4,succnt);
2707   SSVAL(*rparam,6,1);
2708
2709   DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2710   return(True);
2711 }
2712
2713 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2714                                int mdrcnt,int mprcnt,
2715                                char **rdata,char **rparam,
2716                                int *rdata_len,int *rparam_len)
2717 {
2718   char *str1 = param+2;
2719   char *str2 = skip_string(str1,1);
2720   char *p = skip_string(str2,1);
2721   int uLevel,cbBuf;
2722   int succnt;
2723   struct pack_desc desc;
2724
2725   bzero(&desc,sizeof(desc));
2726
2727   uLevel = SVAL(p,0);
2728   cbBuf = SVAL(p,2);
2729
2730   DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2731
2732   /* check it's a supported varient */
2733   if (strcmp(str1,"WrLeh") != 0) return False;
2734   if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2735
2736   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2737   bzero(&desc,sizeof(desc));
2738   desc.base = *rdata;
2739   desc.buflen = mdrcnt;
2740   desc.format = str2;
2741   if (init_package(&desc,1,0)) {
2742     PACKS(&desc,"B13","lp0");
2743   }
2744
2745   succnt = (desc.errcode == NERR_Success ? 1 : 0);
2746
2747   *rdata_len = desc.usedlen;
2748
2749   *rparam_len = 8;
2750   *rparam = REALLOC(*rparam,*rparam_len);
2751   SSVALS(*rparam,0,desc.errcode);
2752   SSVAL(*rparam,2,0);
2753   SSVAL(*rparam,4,succnt);
2754   SSVAL(*rparam,6,1);
2755
2756   DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2757   return(True);
2758 }
2759
2760
2761 struct
2762 {
2763   char * name;
2764   char * pipename;
2765   int subcommand;
2766   BOOL (*fn) ();
2767 } api_fd_commands [] =
2768   {
2769 #ifdef NTDOMAIN
2770     { "SetNmdPpHndState",       "lsarpc",       1,      api_LsarpcSNPHS },
2771     { "SetNmdPpHndState",       "srvsvc",       1,      api_LsarpcSNPHS },
2772     { "SetNmdPpHndState",       "NETLOGON",     1,      api_LsarpcSNPHS },
2773     { "TransactNmPipe", "lsarpc",       0x26,   api_ntLsarpcTNP },
2774     { "TransactNmPipe", "srvsvc",       0x26,   api_srvsvcTNP },
2775     { "TransactNmPipe", "NETLOGON",     0x26,   api_netlogrpcTNP },
2776 #else
2777     { "SetNmdPpHndState",       "lsarpc",       1,      api_LsarpcSNPHS },
2778     { "TransactNmPipe"  ,       "lsarpc",       0x26,   api_LsarpcTNP },
2779 #endif
2780     { NULL,             NULL,           -1,     (BOOL (*)())api_Unsupported }
2781   };
2782
2783 /****************************************************************************
2784   handle remote api calls delivered to a named pipe already opened.
2785   ****************************************************************************/
2786 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2787                         uint16 *setup,char *data,char *params,
2788                         int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2789 {
2790   char *rdata = NULL;
2791   char *rparam = NULL;
2792   int rdata_len = 0;
2793   int rparam_len = 0;
2794   BOOL reply=False;
2795   int i;
2796   int fd;
2797   int subcommand;
2798   
2799   /* First find out the name of this file. */
2800   if (suwcnt != 2)
2801     {
2802       DEBUG(0,("Unexpected named pipe transaction.\n"));
2803       return(-1);
2804     }
2805   
2806   /* Get the file handle and hence the file name. */
2807   fd = setup[1];
2808   subcommand = setup[0];
2809   
2810   DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2811   DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
2812            tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
2813   
2814   for (i=0;api_fd_commands[i].name;i++)
2815   {
2816     if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2817             api_fd_commands[i].subcommand == subcommand &&
2818             api_fd_commands[i].fn)
2819     {
2820           DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2821           break;
2822     }
2823   }
2824   
2825   rdata  = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
2826   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2827   
2828   DEBUG(10,("calling api_fd_command\n"));
2829
2830   reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2831                                 &rdata,&rparam,&rdata_len,&rparam_len);
2832   
2833   DEBUG(10,("called api_fd_command\n"));
2834
2835   if (rdata_len > mdrcnt || rparam_len > mprcnt)
2836   {
2837     reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2838                            &rdata,&rparam,&rdata_len,&rparam_len);
2839   }
2840   
2841   
2842   /* if we get False back then it's actually unsupported */
2843   if (!reply)
2844     api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2845                     &rdata,&rparam,&rdata_len,&rparam_len);
2846   
2847   /* now send the reply */
2848   send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2849   
2850   if (rdata)
2851     free(rdata);
2852   if (rparam)
2853     free(rparam);
2854   
2855   return(-1);
2856 }
2857
2858
2859
2860 /****************************************************************************
2861   the buffer was too small
2862   ****************************************************************************/
2863 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2864                          int mdrcnt,int mprcnt,
2865                          char **rdata,char **rparam,
2866                          int *rdata_len,int *rparam_len)
2867 {
2868   *rparam_len = MIN(*rparam_len,mprcnt);
2869   *rparam = REALLOC(*rparam,*rparam_len);
2870
2871   *rdata_len = 0;
2872
2873   SSVAL(*rparam,0,NERR_BufTooSmall);
2874
2875   DEBUG(3,("Supplied buffer too small in API command\n"));
2876
2877   return(True);
2878 }
2879
2880
2881 /****************************************************************************
2882   the request is not supported
2883   ****************************************************************************/
2884 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2885                             int mdrcnt,int mprcnt,
2886                             char **rdata,char **rparam,
2887                             int *rdata_len,int *rparam_len)
2888 {
2889   *rparam_len = 4;
2890   *rparam = REALLOC(*rparam,*rparam_len);
2891
2892   *rdata_len = 0;
2893
2894   SSVAL(*rparam,0,NERR_notsupported);
2895   SSVAL(*rparam,2,0);           /* converter word */
2896
2897   DEBUG(3,("Unsupported API command\n"));
2898
2899   return(True);
2900 }
2901
2902
2903
2904
2905 struct
2906 {
2907   char *name;
2908   int id;
2909   BOOL (*fn)();
2910   int flags;
2911 } api_commands[] = {
2912   {"RNetShareEnum",     0,      (BOOL (*)())api_RNetShareEnum,0},
2913   {"RNetShareGetInfo",  1,      (BOOL (*)())api_RNetShareGetInfo,0},
2914   {"RNetServerGetInfo", 13,     (BOOL (*)())api_RNetServerGetInfo,0},
2915   {"RNetUserGetInfo",   56,     (BOOL (*)())api_RNetUserGetInfo,0},
2916   {"NetUserGetGroups",  59,     (BOOL (*)())api_NetUserGetGroups,0},
2917   {"NetWkstaGetInfo",   63,     (BOOL (*)())api_NetWkstaGetInfo,0},
2918   {"DosPrintQEnum",     69,     (BOOL (*)())api_DosPrintQEnum,0},
2919   {"DosPrintQGetInfo",  70,     (BOOL (*)())api_DosPrintQGetInfo,0},
2920   {"WPrintJobEnumerate",76,     (BOOL (*)())api_WPrintJobEnumerate,0},
2921   {"WPrintJobGetInfo",  77,     (BOOL (*)())api_WPrintJobGetInfo,0},
2922   {"RDosPrintJobDel",   81,     (BOOL (*)())api_RDosPrintJobDel,0},
2923   {"RDosPrintJobPause", 82,     (BOOL (*)())api_RDosPrintJobDel,0},
2924   {"RDosPrintJobResume",83,     (BOOL (*)())api_RDosPrintJobDel,0},
2925   {"WPrintDestEnum",    84,     (BOOL (*)())api_WPrintDestEnum,0},
2926   {"WPrintDestGetInfo", 85,     (BOOL (*)())api_WPrintDestGetInfo,0},
2927   {"NetRemoteTOD",      91,     (BOOL (*)())api_NetRemoteTOD,0},
2928   {"WPrintQueuePurge",  103,    (BOOL (*)())api_WPrintQueuePurge,0},
2929   {"NetServerEnum",     104,    (BOOL (*)())api_RNetServerEnum,0},
2930   {"WAccessGetUserPerms",105,   (BOOL (*)())api_WAccessGetUserPerms,0},
2931   {"SetUserPassword",   115,    (BOOL (*)())api_SetUserPassword,0},
2932   {"WWkstaUserLogon",   132,    (BOOL (*)())api_WWkstaUserLogon,0},
2933   {"PrintJobInfo",      147,    (BOOL (*)())api_PrintJobInfo,0},
2934   {"WPrintDriverEnum",  205,    (BOOL (*)())api_WPrintDriverEnum,0},
2935   {"WPrintQProcEnum",   206,    (BOOL (*)())api_WPrintQProcEnum,0},
2936   {"WPrintPortEnum",    207,    (BOOL (*)())api_WPrintPortEnum,0},
2937   {NULL,                -1,     (BOOL (*)())api_Unsupported,0}};
2938
2939
2940 /****************************************************************************
2941   handle remote api calls
2942   ****************************************************************************/
2943 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2944                      int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2945 {
2946   int api_command = SVAL(params,0);
2947   char *rdata = NULL;
2948   char *rparam = NULL;
2949   int rdata_len = 0;
2950   int rparam_len = 0;
2951   BOOL reply=False;
2952   int i;
2953
2954   DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2955            api_command,params+2,skip_string(params+2,1),
2956            tdscnt,tpscnt,mdrcnt,mprcnt));
2957
2958   for (i=0;api_commands[i].name;i++)
2959     if (api_commands[i].id == api_command && api_commands[i].fn)
2960       {
2961         DEBUG(3,("Doing %s\n",api_commands[i].name));
2962         break;
2963       }
2964
2965   rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2966   rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2967
2968   reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2969                              &rdata,&rparam,&rdata_len,&rparam_len);
2970
2971
2972   if (rdata_len > mdrcnt ||
2973       rparam_len > mprcnt)
2974     {
2975       reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2976                            &rdata,&rparam,&rdata_len,&rparam_len);
2977     }
2978             
2979
2980   /* if we get False back then it's actually unsupported */
2981   if (!reply)
2982     api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2983                     &rdata,&rparam,&rdata_len,&rparam_len);
2984
2985       
2986
2987   /* now send the reply */
2988   send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2989
2990   if (rdata)
2991     free(rdata);
2992   if (rparam)
2993     free(rparam);
2994   
2995   return(-1);
2996 }
2997
2998 /****************************************************************************
2999   handle named pipe commands
3000   ****************************************************************************/
3001 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3002                       uint16 *setup,char *data,char *params,
3003                       int suwcnt,int tdscnt,int tpscnt,
3004                       int msrcnt,int mdrcnt,int mprcnt)
3005 {
3006
3007   if (strequal(name,"LANMAN"))
3008     return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
3009
3010 if (strlen(name) < 1)
3011   return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
3012
3013
3014   DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
3015            name,(int)setup[0],(int)setup[1]));
3016   
3017   return(0);
3018 }
3019
3020
3021 /****************************************************************************
3022   reply to a SMBtrans
3023   ****************************************************************************/
3024 int reply_trans(char *inbuf,char *outbuf)
3025 {
3026   fstring name;
3027
3028   char *data=NULL,*params=NULL;
3029   uint16 *setup=NULL;
3030
3031   int outsize = 0;
3032   int cnum = SVAL(inbuf,smb_tid);
3033   uint16 vuid = SVAL(inbuf,smb_uid);
3034
3035   int tpscnt = SVAL(inbuf,smb_vwv0);
3036   int tdscnt = SVAL(inbuf,smb_vwv1);
3037   int mprcnt = SVAL(inbuf,smb_vwv2);
3038   int mdrcnt = SVAL(inbuf,smb_vwv3);
3039   int msrcnt = CVAL(inbuf,smb_vwv4);
3040   BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3041   BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3042   int pscnt = SVAL(inbuf,smb_vwv9);
3043   int psoff = SVAL(inbuf,smb_vwv10);
3044   int dscnt = SVAL(inbuf,smb_vwv11);
3045   int dsoff = SVAL(inbuf,smb_vwv12);
3046   int suwcnt = CVAL(inbuf,smb_vwv13);
3047
3048   fstrcpy(name,smb_buf(inbuf));
3049
3050   if (dscnt > tdscnt || pscnt > tpscnt) {
3051           exit_server("invalid trans parameters\n");
3052   }
3053   
3054   if (tdscnt)
3055     {
3056       data = (char *)malloc(tdscnt);
3057       memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3058     }
3059   if (tpscnt)
3060     {
3061       params = (char *)malloc(tpscnt);
3062       memcpy(params,smb_base(inbuf)+psoff,pscnt);
3063     }
3064
3065   if (suwcnt)
3066     {
3067       int i;
3068       setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3069       for (i=0;i<suwcnt;i++)
3070         setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3071     }
3072
3073
3074   if (pscnt < tpscnt || dscnt < tdscnt)
3075     {
3076       /* We need to send an interim response then receive the rest
3077          of the parameter/data bytes */
3078       outsize = set_message(outbuf,0,0,True);
3079       show_msg(outbuf);
3080       send_smb(Client,outbuf);
3081     }
3082
3083   /* receive the rest of the trans packet */
3084   while (pscnt < tpscnt || dscnt < tdscnt)
3085     {
3086       int pcnt,poff,dcnt,doff,pdisp,ddisp;
3087       
3088       if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3089           CVAL(inbuf, smb_com) != SMBtrans)
3090         {
3091           DEBUG(2,("Invalid secondary trans2 packet\n"));
3092           if (params) free(params);
3093           if (data) free(data);
3094           if (setup) free(setup);
3095           return(ERROR(ERRSRV,ERRerror));
3096         }
3097
3098       show_msg(inbuf);
3099       
3100       tpscnt = SVAL(inbuf,smb_vwv0);
3101       tdscnt = SVAL(inbuf,smb_vwv1);
3102
3103       pcnt = SVAL(inbuf,smb_vwv2);
3104       poff = SVAL(inbuf,smb_vwv3);
3105       pdisp = SVAL(inbuf,smb_vwv4);
3106       
3107       dcnt = SVAL(inbuf,smb_vwv5);
3108       doff = SVAL(inbuf,smb_vwv6);
3109       ddisp = SVAL(inbuf,smb_vwv7);
3110       
3111       pscnt += pcnt;
3112       dscnt += dcnt;
3113
3114       if (dscnt > tdscnt || pscnt > tpscnt) {
3115               exit_server("invalid trans parameters\n");
3116       }
3117
3118       if (pcnt)
3119         memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3120       if (dcnt)
3121         memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);      
3122     }
3123
3124
3125   DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3126   
3127
3128   if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3129     outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3130                          suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3131
3132
3133   if (data) free(data);
3134   if (params) free(params);
3135   if (setup) free(setup);
3136
3137   if (close_on_completion)
3138     close_cnum(cnum,vuid);
3139
3140   if (one_way)
3141     return(-1);
3142   
3143   if (outsize == 0)
3144     return(ERROR(ERRSRV,ERRnosupport));
3145
3146   return(outsize);
3147 }