added automount home directory support. contributed by simeon@bangor.co.uk
[Samba.git] / source / smbd / ipc.c
blob9a80a8d062d985551f61047c45d73e18e4aa957e
2 /*
3 Unix SMB/Netbios implementation.
4 Version 1.9.
5 Inter-process communication and named pipe handling
6 Copyright (C) Andrew Tridgell 1992-1995
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles the named pipe and mailslot calls
24 in the SMBtrans protocol
27 #include "includes.h"
29 #ifdef CHECK_TYPES
30 #undef CHECK_TYPES
31 #endif
32 #define CHECK_TYPES 0
34 extern int DEBUGLEVEL;
35 extern int max_send;
36 extern files_struct Files[];
37 extern connection_struct Connections[];
39 extern fstring local_machine;
41 #define NERR_Success 0
42 #define NERR_badpass 86
43 #define NERR_notsupported 50
45 #define NERR_BASE (2100)
46 #define NERR_BufTooSmall (NERR_BASE+23)
47 #define NERR_JobNotFound (NERR_BASE+51)
48 #define NERR_DestNotFound (NERR_BASE+52)
49 #define ERROR_INVALID_LEVEL 124
50 #define ERROR_MORE_DATA 234
52 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
54 #define ACCESS_READ 0x01
55 #define ACCESS_WRITE 0x02
56 #define ACCESS_CREATE 0x04
58 #define SHPWLEN 8 /* share password length */
59 #define NNLEN 12 /* 8.3 net name length */
60 #define SNLEN 15 /* service name length */
61 #define QNLEN 12 /* queue name maximum length */
63 extern int Client;
65 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
66 int mdrcnt,int mprcnt,
67 char **rdata,char **rparam,
68 int *rdata_len,int *rparam_len);
69 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
70 int mdrcnt,int mprcnt,
71 char **rdata,char **rparam,
72 int *rdata_len,int *rparam_len);
75 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
77 pstring buf;
78 int l;
80 if (!src || !dst || !n || !(*dst)) return(0);
82 StrnCpy(buf,src,sizeof(buf)/2);
83 string_sub(buf,"%S",lp_servicename(snum));
84 standard_sub(cnum,buf);
85 StrnCpy(*dst,buf,*n);
86 l = strlen(*dst) + 1;
87 (*dst) += l;
88 (*n) -= l;
89 return l;
92 static int CopyAndAdvance(char** dst, char* src, int* n)
94 int l;
95 if (!src || !dst || !n || !(*dst)) return(0);
96 StrnCpy(*dst,src,*n);
97 l = strlen(*dst) + 1;
98 (*dst) += l;
99 (*n) -= l;
100 return l;
103 static int StrlenExpanded(int cnum, int snum, char* s)
105 pstring buf;
106 if (!s) return(0);
107 StrnCpy(buf,s,sizeof(buf)/2);
108 string_sub(buf,"%S",lp_servicename(snum));
109 standard_sub(cnum,buf);
110 return strlen(buf) + 1;
113 static char* Expand(int cnum, int snum, char* s)
115 static pstring buf;
116 if (!s) return(NULL);
117 StrnCpy(buf,s,sizeof(buf)/2);
118 string_sub(buf,"%S",lp_servicename(snum));
119 standard_sub(cnum,buf);
120 return &buf[0];
123 /*******************************************************************
124 check a API string for validity when we only need to check the prefix
125 ******************************************************************/
126 static BOOL prefix_ok(char *str,char *prefix)
128 return(strncmp(str,prefix,strlen(prefix)) == 0);
132 /****************************************************************************
133 send a trans reply
134 ****************************************************************************/
135 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
136 int ldata,int lparam,int lsetup)
138 int i;
139 int this_ldata,this_lparam;
140 int tot_data=0,tot_param=0;
141 int align;
143 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
144 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
146 align = (this_lparam%4);
148 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
149 if (this_lparam)
150 memcpy(smb_buf(outbuf),param,this_lparam);
151 if (this_ldata)
152 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
154 SSVAL(outbuf,smb_vwv0,lparam);
155 SSVAL(outbuf,smb_vwv1,ldata);
156 SSVAL(outbuf,smb_vwv3,this_lparam);
157 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
158 SSVAL(outbuf,smb_vwv5,0);
159 SSVAL(outbuf,smb_vwv6,this_ldata);
160 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
161 SSVAL(outbuf,smb_vwv8,0);
162 SSVAL(outbuf,smb_vwv9,lsetup);
163 for (i=0;i<lsetup;i++)
164 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
166 show_msg(outbuf);
167 send_smb(Client,outbuf);
169 tot_data = this_ldata;
170 tot_param = this_lparam;
172 while (tot_data < ldata || tot_param < lparam)
174 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
175 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
177 align = (this_lparam%4);
179 set_message(outbuf,10,this_ldata+this_lparam+align,False);
180 if (this_lparam)
181 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
182 if (this_ldata)
183 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
185 SSVAL(outbuf,smb_vwv3,this_lparam);
186 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
187 SSVAL(outbuf,smb_vwv5,tot_param);
188 SSVAL(outbuf,smb_vwv6,this_ldata);
189 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
190 SSVAL(outbuf,smb_vwv8,tot_data);
191 SSVAL(outbuf,smb_vwv9,0);
193 show_msg(outbuf);
194 send_smb(Client,outbuf);
196 tot_data += this_ldata;
197 tot_param += this_lparam;
201 struct pack_desc {
202 char* format; /* formatstring for structure */
203 char* subformat; /* subformat for structure */
204 char* base; /* baseaddress of buffer */
205 int buflen; /* remaining size for fixed part; on init: length of base */
206 int subcount; /* count of substructures */
207 char* structbuf; /* pointer into buffer for remaining fixed part */
208 int stringlen; /* remaining size for variable part */
209 char* stringbuf; /* pointer into buffer for remaining variable part */
210 int neededlen; /* total needed size */
211 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
212 char* curpos; /* current position; pointer into format or subformat */
213 int errcode;
216 static int get_counter(char** p)
218 int i, n;
219 if (!p || !(*p)) return(1);
220 if (!isdigit(**p)) return 1;
221 for (n = 0;;) {
222 i = **p;
223 if (isdigit(i))
224 n = 10 * n + (i - '0');
225 else
226 return n;
227 (*p)++;
231 static int getlen(char* p)
233 int n = 0;
234 if (!p) return(0);
235 while (*p) {
236 switch( *p++ ) {
237 case 'W': /* word (2 byte) */
238 n += 2;
239 break;
240 case 'N': /* count of substructures (word) at end */
241 n += 2;
242 break;
243 case 'D': /* double word (4 byte) */
244 case 'z': /* offset to zero terminated string (4 byte) */
245 case 'l': /* offset to user data (4 byte) */
246 n += 4;
247 break;
248 case 'b': /* offset to data (with counter) (4 byte) */
249 n += 4;
250 get_counter(&p);
251 break;
252 case 'B': /* byte (with optional counter) */
253 n += get_counter(&p);
254 break;
257 return n;
260 static BOOL init_package(struct pack_desc* p, int count, int subcount)
262 int n = p->buflen;
263 int i;
265 if (!p->format || !p->base) return(False);
267 i = count * getlen(p->format);
268 if (p->subformat) i += subcount * getlen(p->subformat);
269 p->structbuf = p->base;
270 p->neededlen = 0;
271 p->usedlen = 0;
272 p->subcount = 0;
273 p->curpos = p->format;
274 if (i > n) {
275 i = n = 0;
276 p->errcode = NERR_BufTooSmall;
279 p->errcode = NERR_Success;
280 p->buflen = i;
281 n -= i;
282 p->stringbuf = p->base + i;
283 p->stringlen = n;
284 return(p->errcode == NERR_Success);
287 #ifdef __STDC__
288 static int package(struct pack_desc* p, ...)
290 #else
291 static int package(va_alist)
292 va_dcl
294 struct pack_desc* p;
295 #endif
296 va_list args;
297 int needed=0, stringneeded;
298 char* str=NULL;
299 int is_string=0, stringused;
300 int32 temp;
302 #ifdef __STDC__
303 va_start(args,p);
304 #else
305 va_start(args);
306 p = va_arg(args,struct pack_desc *);
307 #endif
309 if (!*p->curpos) {
310 if (!p->subcount)
311 p->curpos = p->format;
312 else {
313 p->curpos = p->subformat;
314 p->subcount--;
317 #if CHECK_TYPES
318 str = va_arg(args,char*);
319 if (strncmp(str,p->curpos,strlen(str)) != 0) {
320 DEBUG(2,("type error in package: %s instead of %*s\n",str,
321 strlen(str),p->curpos));
322 va_end(args);
323 #if AJT
324 ajt_panic();
325 #endif
326 return 0;
328 #endif
329 stringneeded = -1;
331 if (!p->curpos) return(0);
333 switch( *p->curpos++ ) {
334 case 'W': /* word (2 byte) */
335 needed = 2;
336 temp = va_arg(args,int);
337 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
338 break;
339 case 'N': /* count of substructures (word) at end */
340 needed = 2;
341 p->subcount = va_arg(args,int);
342 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
343 break;
344 case 'D': /* double word (4 byte) */
345 needed = 4;
346 temp = va_arg(args,int);
347 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
348 break;
349 case 'B': /* byte (with optional counter) */
350 needed = get_counter(&p->curpos);
352 char *s = va_arg(args,char*);
353 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
355 break;
356 case 'z': /* offset to zero terminated string (4 byte) */
357 str = va_arg(args,char*);
358 stringneeded = (str ? strlen(str)+1 : 0);
359 is_string = 1;
360 break;
361 case 'l': /* offset to user data (4 byte) */
362 str = va_arg(args,char*);
363 stringneeded = va_arg(args,int);
364 is_string = 0;
365 break;
366 case 'b': /* offset to data (with counter) (4 byte) */
367 str = va_arg(args,char*);
368 stringneeded = get_counter(&p->curpos);
369 is_string = 0;
370 break;
372 va_end(args);
373 if (stringneeded >= 0) {
374 needed = 4;
375 if (p->buflen >= needed) {
376 stringused = stringneeded;
377 if (stringused > p->stringlen) {
378 stringused = (is_string ? p->stringlen : 0);
379 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
381 if (!stringused)
382 SIVAL(p->structbuf,0,0);
383 else {
384 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
385 memcpy(p->stringbuf,str?str:"",stringused);
386 if (is_string) p->stringbuf[stringused-1] = '\0';
387 p->stringbuf += stringused;
388 p->stringlen -= stringused;
389 p->usedlen += stringused;
392 p->neededlen += stringneeded;
394 p->neededlen += needed;
395 if (p->buflen >= needed) {
396 p->structbuf += needed;
397 p->buflen -= needed;
398 p->usedlen += needed;
400 else {
401 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
403 return 1;
406 #if CHECK_TYPES
407 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
408 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
409 #else
410 #define PACK(desc,t,v) package(desc,v)
411 #define PACKl(desc,t,v,l) package(desc,v,l)
412 #endif
414 static void PACKI(struct pack_desc* desc,char *t,int v)
416 PACK(desc,t,v);
419 static void PACKS(struct pack_desc* desc,char *t,char *v)
421 PACK(desc,t,v);
425 /****************************************************************************
426 get a print queue
427 ****************************************************************************/
429 static void PackDriverData(struct pack_desc* desc)
431 char drivdata[4+4+32];
432 SIVAL(drivdata,0,sizeof drivdata); /* cb */
433 SIVAL(drivdata,4,1000); /* lVersion */
434 memset(drivdata+8,0,32); /* szDeviceName */
435 strcpy(drivdata+8,"NULL");
436 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
439 static int check_printq_info(struct pack_desc* desc,
440 int uLevel, char *id1, const char* id2)
442 desc->subformat = NULL;
443 switch( uLevel ) {
444 case 0:
445 desc->format = "B13";
446 break;
447 case 1:
448 desc->format = "B13BWWWzzzzzWW";
449 break;
450 case 2:
451 desc->format = "B13BWWWzzzzzWN";
452 desc->subformat = "WB21BB16B10zWWzDDz";
453 break;
454 case 3:
455 desc->format = "zWWWWzzzzWWzzl";
456 break;
457 case 4:
458 desc->format = "zWWWWzzzzWNzzl";
459 desc->subformat = "WWzWWDDzz";
460 break;
461 case 5:
462 desc->format = "z";
463 break;
464 default: return False;
466 if (strcmp(desc->format,id1) != 0) return False;
467 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
468 return True;
471 static void fill_printjob_info(int cnum, int snum, int uLevel,
472 struct pack_desc* desc,
473 print_queue_struct* queue, int n)
475 time_t t = queue->time;
477 /* the client expects localtime */
478 t -= TimeDiff(t);
480 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
481 if (uLevel == 1) {
482 PACKS(desc,"B21",queue->user); /* szUserName */
483 PACKS(desc,"B",""); /* pad */
484 PACKS(desc,"B16",""); /* szNotifyName */
485 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
486 PACKS(desc,"z",""); /* pszParms */
487 PACKI(desc,"W",n+1); /* uPosition */
488 PACKI(desc,"W",queue->status); /* fsStatus */
489 PACKS(desc,"z",""); /* pszStatus */
490 PACKI(desc,"D",t); /* ulSubmitted */
491 PACKI(desc,"D",queue->size); /* ulSize */
492 PACKS(desc,"z",queue->file); /* pszComment */
494 if (uLevel == 2 || uLevel == 3) {
495 PACKI(desc,"W",queue->priority); /* uPriority */
496 PACKS(desc,"z",queue->user); /* pszUserName */
497 PACKI(desc,"W",n+1); /* uPosition */
498 PACKI(desc,"W",queue->status); /* fsStatus */
499 PACKI(desc,"D",t); /* ulSubmitted */
500 PACKI(desc,"D",queue->size); /* ulSize */
501 PACKS(desc,"z","Samba"); /* pszComment */
502 PACKS(desc,"z",queue->file); /* pszDocument */
503 if (uLevel == 3) {
504 PACKS(desc,"z",""); /* pszNotifyName */
505 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
506 PACKS(desc,"z",""); /* pszParms */
507 PACKS(desc,"z",""); /* pszStatus */
508 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
509 PACKS(desc,"z","lpd"); /* pszQProcName */
510 PACKS(desc,"z",""); /* pszQProcParms */
511 PACKS(desc,"z","NULL"); /* pszDriverName */
512 PackDriverData(desc); /* pDriverData */
513 PACKS(desc,"z",""); /* pszPrinterName */
518 static void fill_printq_info(int cnum, int snum, int uLevel,
519 struct pack_desc* desc,
520 int count, print_queue_struct* queue,
521 print_status_struct* status)
523 if (uLevel < 3) {
524 PACKS(desc,"B13",SERVICE(snum));
525 } else {
526 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
528 if (uLevel == 1 || uLevel == 2) {
529 PACKS(desc,"B",""); /* alignment */
530 PACKI(desc,"W",5); /* priority */
531 PACKI(desc,"W",0); /* start time */
532 PACKI(desc,"W",0); /* until time */
533 PACKS(desc,"z",""); /* pSepFile */
534 PACKS(desc,"z","lpd"); /* pPrProc */
535 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
536 PACKS(desc,"z",""); /* pParms */
537 if (snum < 0) {
538 PACKS(desc,"z","UNKNOWN PRINTER");
539 PACKI(desc,"W",LPSTAT_ERROR);
541 else if (!status || !status->message[0]) {
542 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
543 PACKI(desc,"W",LPSTAT_OK); /* status */
544 } else {
545 PACKS(desc,"z",status->message);
546 PACKI(desc,"W",status->status); /* status */
548 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
550 if (uLevel == 3 || uLevel == 4) {
551 PACKI(desc,"W",5); /* uPriority */
552 PACKI(desc,"W",0); /* uStarttime */
553 PACKI(desc,"W",0); /* uUntiltime */
554 PACKI(desc,"W",5); /* pad1 */
555 PACKS(desc,"z",""); /* pszSepFile */
556 PACKS(desc,"z","WinPrint"); /* pszPrProc */
557 PACKS(desc,"z",""); /* pszParms */
558 if (!status || !status->message[0]) {
559 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
560 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
561 } else {
562 PACKS(desc,"z",status->message); /* pszComment */
563 PACKI(desc,"W",status->status); /* fsStatus */
565 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
566 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
567 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
568 PackDriverData(desc); /* pDriverData */
570 if (uLevel == 2 || uLevel == 4) {
571 int i;
572 for (i=0;i<count;i++)
573 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
576 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
579 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
580 int mdrcnt,int mprcnt,
581 char **rdata,char **rparam,
582 int *rdata_len,int *rparam_len)
584 char *str1 = param+2;
585 char *str2 = skip_string(str1,1);
586 char *p = skip_string(str2,1);
587 char *QueueName = p;
588 int uLevel,cbBuf;
589 int count=0;
590 int snum;
591 char* str3;
592 struct pack_desc desc;
593 print_queue_struct *queue=NULL;
594 print_status_struct status;
596 bzero(&status,sizeof(status));
597 bzero(&desc,sizeof(desc));
599 p = skip_string(p,1);
600 uLevel = SVAL(p,0);
601 cbBuf = SVAL(p,2);
602 str3 = p + 4;
604 /* remove any trailing username */
605 if ((p = strchr(QueueName,'%'))) *p = 0;
607 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
609 /* check it's a supported varient */
610 if (!prefix_ok(str1,"zWrLh")) return False;
611 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
613 snum = lp_servicenumber(QueueName);
614 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
615 int pnum = lp_servicenumber(PRINTERS_NAME);
616 if (pnum >= 0) {
617 lp_add_printer(QueueName,pnum);
618 snum = lp_servicenumber(QueueName);
622 if (snum < 0 || !VALID_SNUM(snum)) return(False);
624 count = get_printqueue(snum,cnum,&queue,&status);
625 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
626 desc.base = *rdata;
627 desc.buflen = mdrcnt;
628 if (init_package(&desc,1,count)) {
629 desc.subcount = count;
630 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
633 *rdata_len = desc.usedlen;
635 *rparam_len = 6;
636 *rparam = REALLOC(*rparam,*rparam_len);
637 SSVALS(*rparam,0,desc.errcode);
638 SSVAL(*rparam,2,0);
639 SSVAL(*rparam,4,desc.neededlen);
641 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
643 if (queue) free(queue);
645 return(True);
649 /****************************************************************************
650 view list of all print jobs on all queues
651 ****************************************************************************/
652 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
653 int mdrcnt, int mprcnt,
654 char **rdata, char** rparam,
655 int *rdata_len, int *rparam_len)
657 char *param_format = param+2;
658 char *output_format1 = skip_string(param_format,1);
659 char *p = skip_string(output_format1,1);
660 int uLevel = SVAL(p,0);
661 char *output_format2 = p + 4;
662 int services = lp_numservices();
663 int i, n;
664 struct pack_desc desc;
665 print_queue_struct **queue = NULL;
666 print_status_struct *status = NULL;
667 int* subcntarr = NULL;
668 int queuecnt, subcnt=0, succnt=0;
670 bzero(&desc,sizeof(desc));
672 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
674 if (!prefix_ok(param_format,"WrLeh")) return False;
675 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
676 return False;
677 queuecnt = 0;
678 for (i = 0; i < services; i++)
679 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
680 queuecnt++;
681 if (uLevel > 0) {
682 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
683 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
684 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
685 memset(status,0,queuecnt*sizeof(print_status_struct));
686 subcntarr = (int*)malloc(queuecnt*sizeof(int));
687 subcnt = 0;
688 n = 0;
689 for (i = 0; i < services; i++)
690 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
691 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
692 subcnt += subcntarr[n];
693 n++;
696 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
697 desc.base = *rdata;
698 desc.buflen = mdrcnt;
700 if (init_package(&desc,queuecnt,subcnt)) {
701 n = 0;
702 succnt = 0;
703 for (i = 0; i < services; i++)
704 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
705 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
706 n++;
707 if (desc.errcode == NERR_Success) succnt = n;
711 if (subcntarr) free(subcntarr);
713 *rdata_len = desc.usedlen;
714 *rparam_len = 8;
715 *rparam = REALLOC(*rparam,*rparam_len);
716 SSVALS(*rparam,0,desc.errcode);
717 SSVAL(*rparam,2,0);
718 SSVAL(*rparam,4,succnt);
719 SSVAL(*rparam,6,queuecnt);
721 for (i = 0; i < queuecnt; i++) {
722 if (queue && queue[i]) free(queue[i]);
725 if (queue) free(queue);
726 if (status) free(status);
728 return True;
731 /****************************************************************************
732 get info level for a server list query
733 ****************************************************************************/
734 static BOOL check_server_info(int uLevel, char* id)
736 switch( uLevel ) {
737 case 0:
738 if (strcmp(id,"B16") != 0) return False;
739 break;
740 case 1:
741 if (strcmp(id,"B16BBDz") != 0) return False;
742 break;
743 default:
744 return False;
746 return True;
749 struct srv_info_struct
751 fstring name;
752 uint32 type;
753 fstring comment;
754 fstring domain;
755 BOOL server_added;
759 /*******************************************************************
760 get server info lists from the files saved by nmbd. Return the
761 number of entries
762 ******************************************************************/
763 static int get_server_info(uint32 servertype,
764 struct srv_info_struct **servers,
765 char *domain)
767 FILE *f;
768 pstring fname;
769 int count=0;
770 int alloced=0;
771 pstring line;
773 strcpy(fname,lp_lockdir());
774 trim_string(fname,NULL,"/");
775 strcat(fname,"/");
776 strcat(fname,SERVER_LIST);
778 f = fopen(fname,"r");
780 if (!f) {
781 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
782 return(0);
785 /* request for everything is code for request all servers */
786 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
788 DEBUG(4,("Servertype search: %8x\n",servertype));
790 while (!feof(f))
792 fstring stype;
793 struct srv_info_struct *s;
794 char *ptr = line;
795 BOOL ok = True;
796 *ptr = 0;
798 fgets(line,sizeof(line)-1,f);
799 if (!*line) continue;
801 if (count == alloced) {
802 alloced += 10;
803 (*servers) = (struct srv_info_struct *)
804 Realloc(*servers,sizeof(**servers)*alloced);
805 if (!(*servers)) return(0);
806 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
808 s = &(*servers)[count];
810 if (!next_token(&ptr,s->name , NULL)) continue;
811 if (!next_token(&ptr,stype , NULL)) continue;
812 if (!next_token(&ptr,s->comment, NULL)) continue;
813 if (!next_token(&ptr,s->domain , NULL)) {
814 /* this allows us to cope with an old nmbd */
815 strcpy(s->domain,lp_workgroup());
818 if (sscanf(stype,"%X",&s->type) != 1) {
819 DEBUG(4,("r:host file "));
820 ok = False;
823 /* doesn't match up: don't want it */
824 if (!(servertype & s->type)) {
825 DEBUG(4,("r:serv type "));
826 ok = False;
829 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
830 (s->type & SV_TYPE_DOMAIN_ENUM))
832 DEBUG(4,("s: dom mismatch "));
833 ok = False;
836 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
838 ok = False;
841 if (ok)
843 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
844 s->name, s->type, s->comment, s->domain));
846 s->server_added = True;
847 count++;
849 else
851 DEBUG(4,("%20s %8x %25s %15s\n",
852 s->name, s->type, s->comment, s->domain));
856 fclose(f);
857 return(count);
861 /*******************************************************************
862 fill in a server info structure
863 ******************************************************************/
864 static int fill_srv_info(struct srv_info_struct *service,
865 int uLevel, char **buf, int *buflen,
866 char **stringbuf, int *stringspace, char *baseaddr)
868 int struct_len;
869 char* p;
870 char* p2;
871 int l2;
872 int len;
874 switch (uLevel) {
875 case 0: struct_len = 16; break;
876 case 1: struct_len = 26; break;
877 default: return -1;
880 if (!buf)
882 len = 0;
883 switch (uLevel)
885 case 1:
886 len = strlen(service->comment)+1;
887 break;
890 if (buflen) *buflen = struct_len;
891 if (stringspace) *stringspace = len;
892 return struct_len + len;
895 len = struct_len;
896 p = *buf;
897 if (*buflen < struct_len) return -1;
898 if (stringbuf)
900 p2 = *stringbuf;
901 l2 = *stringspace;
903 else
905 p2 = p + struct_len;
906 l2 = *buflen - struct_len;
908 if (!baseaddr) baseaddr = p;
910 switch (uLevel)
912 case 0:
913 StrnCpy(p,service->name,15);
914 break;
916 case 1:
917 StrnCpy(p,service->name,15);
918 SIVAL(p,18,service->type);
919 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
920 len += CopyAndAdvance(&p2,service->comment,&l2);
921 break;
924 if (stringbuf)
926 *buf = p + struct_len;
927 *buflen -= struct_len;
928 *stringbuf = p2;
929 *stringspace = l2;
931 else
933 *buf = p2;
934 *buflen -= len;
936 return len;
940 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
942 return(strcmp(s1->name,s2->name));
945 /****************************************************************************
946 view list of servers available (or possibly domains). The info is
947 extracted from lists saved by nmbd on the local host
948 ****************************************************************************/
949 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
950 int mdrcnt, int mprcnt, char **rdata,
951 char **rparam, int *rdata_len, int *rparam_len)
953 char *str1 = param+2;
954 char *str2 = skip_string(str1,1);
955 char *p = skip_string(str2,1);
956 int uLevel = SVAL(p,0);
957 int buf_len = SVAL(p,2);
958 uint32 servertype = IVAL(p,4);
959 char *p2;
960 int data_len, fixed_len, string_len;
961 int f_len, s_len;
962 struct srv_info_struct *servers=NULL;
963 int counted=0,total=0;
964 int i,missed;
965 fstring domain;
966 BOOL domain_request;
967 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
969 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
971 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
973 p += 8;
975 if (!prefix_ok(str1,"WrLehD")) return False;
976 if (!check_server_info(uLevel,str2)) return False;
978 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
979 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
980 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
982 if (strcmp(str1, "WrLehDz") == 0) {
983 StrnCpy(domain, p, sizeof(fstring)-1);
984 } else {
985 StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
988 if (lp_browse_list())
989 total = get_server_info(servertype,&servers,domain);
991 data_len = fixed_len = string_len = 0;
992 missed = 0;
994 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
997 char *lastname=NULL;
999 for (i=0;i<total;i++)
1001 struct srv_info_struct *s = &servers[i];
1002 if (lastname && strequal(lastname,s->name)) continue;
1003 lastname = s->name;
1004 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1005 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1006 s->name, s->type, s->comment, s->domain));
1008 if (data_len <= buf_len) {
1009 counted++;
1010 fixed_len += f_len;
1011 string_len += s_len;
1012 } else {
1013 missed++;
1018 *rdata_len = fixed_len + string_len;
1019 *rdata = REALLOC(*rdata,*rdata_len);
1020 bzero(*rdata,*rdata_len);
1022 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1023 p = *rdata;
1024 f_len = fixed_len;
1025 s_len = string_len;
1028 char *lastname=NULL;
1029 int count2 = counted;
1030 for (i = 0; i < total && count2;i++)
1032 struct srv_info_struct *s = &servers[i];
1033 if (lastname && strequal(lastname,s->name)) continue;
1034 lastname = s->name;
1035 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1036 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1037 s->name, s->type, s->comment, s->domain));
1038 count2--;
1042 *rparam_len = 8;
1043 *rparam = REALLOC(*rparam,*rparam_len);
1044 SSVAL(*rparam,0,NERR_Success);
1045 SSVAL(*rparam,2,0);
1046 SSVAL(*rparam,4,counted);
1047 SSVAL(*rparam,6,counted+missed);
1049 if (servers) free(servers);
1051 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1052 domain,uLevel,counted,counted+missed));
1054 return(True);
1058 /****************************************************************************
1059 get info about a share
1060 ****************************************************************************/
1061 static BOOL check_share_info(int uLevel, char* id)
1063 switch( uLevel ) {
1064 case 0:
1065 if (strcmp(id,"B13") != 0) return False;
1066 break;
1067 case 1:
1068 if (strcmp(id,"B13BWz") != 0) return False;
1069 break;
1070 case 2:
1071 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1072 break;
1073 case 91:
1074 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1075 break;
1076 default: return False;
1078 return True;
1081 static int fill_share_info(int cnum, int snum, int uLevel,
1082 char** buf, int* buflen,
1083 char** stringbuf, int* stringspace, char* baseaddr)
1085 int struct_len;
1086 char* p;
1087 char* p2;
1088 int l2;
1089 int len;
1091 switch( uLevel ) {
1092 case 0: struct_len = 13; break;
1093 case 1: struct_len = 20; break;
1094 case 2: struct_len = 40; break;
1095 case 91: struct_len = 68; break;
1096 default: return -1;
1100 if (!buf)
1102 len = 0;
1103 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1104 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1105 if (buflen) *buflen = struct_len;
1106 if (stringspace) *stringspace = len;
1107 return struct_len + len;
1110 len = struct_len;
1111 p = *buf;
1112 if ((*buflen) < struct_len) return -1;
1113 if (stringbuf)
1115 p2 = *stringbuf;
1116 l2 = *stringspace;
1118 else
1120 p2 = p + struct_len;
1121 l2 = (*buflen) - struct_len;
1123 if (!baseaddr) baseaddr = p;
1125 StrnCpy(p,lp_servicename(snum),13);
1127 if (uLevel > 0)
1129 int type;
1130 CVAL(p,13) = 0;
1131 type = STYPE_DISKTREE;
1132 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1133 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1134 SSVAL(p,14,type); /* device type */
1135 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1136 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1139 if (uLevel > 1)
1141 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1142 SSVALS(p,22,-1); /* max uses */
1143 SSVAL(p,24,1); /* current uses */
1144 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1145 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1146 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1149 if (uLevel > 2)
1151 memset(p+40,0,SHPWLEN+2);
1152 SSVAL(p,50,0);
1153 SIVAL(p,52,0);
1154 SSVAL(p,56,0);
1155 SSVAL(p,58,0);
1156 SIVAL(p,60,0);
1157 SSVAL(p,64,0);
1158 SSVAL(p,66,0);
1161 if (stringbuf)
1163 (*buf) = p + struct_len;
1164 (*buflen) -= struct_len;
1165 (*stringbuf) = p2;
1166 (*stringspace) = l2;
1168 else
1170 (*buf) = p2;
1171 (*buflen) -= len;
1173 return len;
1176 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1177 int mdrcnt,int mprcnt,
1178 char **rdata,char **rparam,
1179 int *rdata_len,int *rparam_len)
1181 char *str1 = param+2;
1182 char *str2 = skip_string(str1,1);
1183 char *netname = skip_string(str2,1);
1184 char *p = skip_string(netname,1);
1185 int uLevel = SVAL(p,0);
1186 int snum = find_service(netname);
1188 if (snum < 0) return False;
1190 /* check it's a supported varient */
1191 if (!prefix_ok(str1,"zWrLh")) return False;
1192 if (!check_share_info(uLevel,str2)) return False;
1194 *rdata = REALLOC(*rdata,mdrcnt);
1195 p = *rdata;
1196 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1197 if (*rdata_len < 0) return False;
1199 *rparam_len = 6;
1200 *rparam = REALLOC(*rparam,*rparam_len);
1201 SSVAL(*rparam,0,NERR_Success);
1202 SSVAL(*rparam,2,0); /* converter word */
1203 SSVAL(*rparam,4,*rdata_len);
1205 return(True);
1208 /****************************************************************************
1209 view list of shares available
1210 ****************************************************************************/
1211 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1212 int mdrcnt,int mprcnt,
1213 char **rdata,char **rparam,
1214 int *rdata_len,int *rparam_len)
1216 char *str1 = param+2;
1217 char *str2 = skip_string(str1,1);
1218 char *p = skip_string(str2,1);
1219 int uLevel = SVAL(p,0);
1220 int buf_len = SVAL(p,2);
1221 char *p2;
1222 int count=lp_numservices();
1223 int total=0,counted=0;
1224 int i;
1225 int data_len, fixed_len, string_len;
1226 int f_len, s_len;
1228 if (!prefix_ok(str1,"WrLeh")) return False;
1229 if (!check_share_info(uLevel,str2)) return False;
1231 data_len = fixed_len = string_len = 0;
1232 for (i=0;i<count;i++)
1233 if (lp_browseable(i) && lp_snum_ok(i))
1235 total++;
1236 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1237 if (data_len <= buf_len)
1239 counted++;
1240 fixed_len += f_len;
1241 string_len += s_len;
1244 *rdata_len = fixed_len + string_len;
1245 *rdata = REALLOC(*rdata,*rdata_len);
1246 memset(*rdata,0,*rdata_len);
1248 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1249 p = *rdata;
1250 f_len = fixed_len;
1251 s_len = string_len;
1252 for (i = 0; i < count;i++)
1253 if (lp_browseable(i) && lp_snum_ok(i))
1254 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1255 break;
1257 *rparam_len = 8;
1258 *rparam = REALLOC(*rparam,*rparam_len);
1259 SSVAL(*rparam,0,NERR_Success);
1260 SSVAL(*rparam,2,0);
1261 SSVAL(*rparam,4,counted);
1262 SSVAL(*rparam,6,total);
1264 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1265 counted,total,uLevel,
1266 buf_len,*rdata_len,mdrcnt));
1267 return(True);
1272 /****************************************************************************
1273 get the time of day info
1274 ****************************************************************************/
1275 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1276 int mdrcnt,int mprcnt,
1277 char **rdata,char **rparam,
1278 int *rdata_len,int *rparam_len)
1280 char *p;
1281 *rparam_len = 4;
1282 *rparam = REALLOC(*rparam,*rparam_len);
1284 *rdata_len = 21;
1285 *rdata = REALLOC(*rdata,*rdata_len);
1287 SSVAL(*rparam,0,NERR_Success);
1288 SSVAL(*rparam,2,0); /* converter word */
1290 p = *rdata;
1293 struct tm *t;
1294 time_t unixdate = time(NULL);
1296 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1297 by NT in a "net time" operation,
1298 it seems to ignore the one below */
1300 /* the client expects to get localtime, not GMT, in this bit
1301 (I think, this needs testing) */
1302 t = LocalTime(&unixdate);
1304 SIVAL(p,4,0); /* msecs ? */
1305 CVAL(p,8) = t->tm_hour;
1306 CVAL(p,9) = t->tm_min;
1307 CVAL(p,10) = t->tm_sec;
1308 CVAL(p,11) = 0; /* hundredths of seconds */
1309 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1310 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1311 CVAL(p,16) = t->tm_mday;
1312 CVAL(p,17) = t->tm_mon + 1;
1313 SSVAL(p,18,1900+t->tm_year);
1314 CVAL(p,20) = t->tm_wday;
1318 return(True);
1321 /****************************************************************************
1322 set the user password
1323 ****************************************************************************/
1324 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1325 int mdrcnt,int mprcnt,
1326 char **rdata,char **rparam,
1327 int *rdata_len,int *rparam_len)
1329 char *p = skip_string(param+2,2);
1330 fstring user;
1331 fstring pass1,pass2;
1333 strcpy(user,p);
1335 p = skip_string(p,1);
1337 StrnCpy(pass1,p,16);
1338 StrnCpy(pass2,p+16,16);
1340 *rparam_len = 4;
1341 *rparam = REALLOC(*rparam,*rparam_len);
1343 *rdata_len = 0;
1345 SSVAL(*rparam,0,NERR_badpass);
1346 SSVAL(*rparam,2,0); /* converter word */
1348 DEBUG(3,("Set password for <%s>\n",user));
1350 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1351 chgpasswd(user,pass1,pass2))
1353 SSVAL(*rparam,0,NERR_Success);
1356 bzero(pass1,sizeof(fstring));
1357 bzero(pass2,sizeof(fstring));
1359 return(True);
1362 /****************************************************************************
1363 delete a print job
1364 Form: <W> <>
1365 ****************************************************************************/
1366 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1367 int mdrcnt,int mprcnt,
1368 char **rdata,char **rparam,
1369 int *rdata_len,int *rparam_len)
1371 int function = SVAL(param,0);
1372 char *str1 = param+2;
1373 char *str2 = skip_string(str1,1);
1374 char *p = skip_string(str2,1);
1375 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1376 by the print queue api */
1377 int snum = (SVAL(p,0)>>8);
1378 int i, count;
1381 /* check it's a supported varient */
1382 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1383 return(False);
1385 *rparam_len = 4;
1386 *rparam = REALLOC(*rparam,*rparam_len);
1388 *rdata_len = 0;
1390 SSVAL(*rparam,0,NERR_Success);
1392 if (snum >= 0 && VALID_SNUM(snum))
1394 print_queue_struct *queue=NULL;
1395 lpq_reset(snum);
1396 count = get_printqueue(snum,cnum,&queue,NULL);
1398 for (i=0;i<count;i++)
1399 if ((queue[i].job%0xFF) == jobid)
1401 switch (function) {
1402 case 81: /* delete */
1403 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1404 del_printqueue(cnum,snum,queue[i].job);
1405 break;
1406 case 82: /* pause */
1407 case 83: /* resume */
1408 DEBUG(3,("%s queue entry %d\n",
1409 (function==82?"pausing":"resuming"),queue[i].job));
1410 status_printjob(cnum,snum,queue[i].job,
1411 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1412 break;
1414 break;
1417 if (i==count)
1418 SSVAL(*rparam,0,NERR_JobNotFound);
1420 if (queue) free(queue);
1423 SSVAL(*rparam,2,0); /* converter word */
1425 return(True);
1428 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1429 int mdrcnt,int mprcnt,
1430 char **rdata,char **rparam,
1431 int *rdata_len,int *rparam_len)
1433 char *str1 = param+2;
1434 char *str2 = skip_string(str1,1);
1435 char *QueueName = skip_string(str2,1);
1436 int snum;
1438 /* check it's a supported varient */
1439 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1440 return(False);
1442 *rparam_len = 4;
1443 *rparam = REALLOC(*rparam,*rparam_len);
1445 *rdata_len = 0;
1447 SSVAL(*rparam,0,NERR_Success);
1448 SSVAL(*rparam,2,0); /* converter word */
1450 snum = lp_servicenumber(QueueName);
1451 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1452 int pnum = lp_servicenumber(PRINTERS_NAME);
1453 if (pnum >= 0) {
1454 lp_add_printer(QueueName,pnum);
1455 snum = lp_servicenumber(QueueName);
1459 if (snum >= 0 && VALID_SNUM(snum)) {
1460 print_queue_struct *queue=NULL;
1461 int i, count;
1462 lpq_reset(snum);
1464 count = get_printqueue(snum,cnum,&queue,NULL);
1465 for (i = 0; i < count; i++)
1466 del_printqueue(cnum,snum,queue[i].job);
1468 if (queue) free(queue);
1471 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1473 return(True);
1477 /****************************************************************************
1478 set the property of a print job (undocumented?)
1479 ? function = 0xb -> set name of print job
1480 ? function = 0x6 -> move print job up/down
1481 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1482 or <WWsTP> <WB21BB16B10zWWzDDz>
1483 ****************************************************************************/
1484 static int check_printjob_info(struct pack_desc* desc,
1485 int uLevel, char* id)
1487 desc->subformat = NULL;
1488 switch( uLevel ) {
1489 case 0: desc->format = "W"; break;
1490 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1491 case 2: desc->format = "WWzWWDDzz"; break;
1492 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1493 default: return False;
1495 if (strcmp(desc->format,id) != 0) return False;
1496 return True;
1499 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1500 int mdrcnt,int mprcnt,
1501 char **rdata,char **rparam,
1502 int *rdata_len,int *rparam_len)
1504 struct pack_desc desc;
1505 char *str1 = param+2;
1506 char *str2 = skip_string(str1,1);
1507 char *p = skip_string(str2,1);
1508 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1509 by the print queue api */
1510 int snum = (SVAL(p,0)>>8);
1511 int uLevel = SVAL(p,2);
1512 int function = SVAL(p,4); /* what is this ?? */
1513 int i;
1514 char *s = data;
1516 *rparam_len = 4;
1517 *rparam = REALLOC(*rparam,*rparam_len);
1519 *rdata_len = 0;
1521 /* check it's a supported varient */
1522 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1523 return(False);
1525 switch (function) {
1526 case 0x6: /* change job place in the queue, data gives the new place */
1527 if (snum >= 0 && VALID_SNUM(snum))
1529 print_queue_struct *queue=NULL;
1530 int count;
1532 lpq_reset(snum);
1533 count = get_printqueue(snum,cnum,&queue,NULL);
1534 for (i=0;i<count;i++) /* find job */
1535 if ((queue[i].job%0xFF) == jobid) break;
1537 if (i==count) {
1538 desc.errcode=NERR_JobNotFound;
1539 if (queue) free(queue);
1541 else {
1542 desc.errcode=NERR_Success;
1543 i++;
1544 #if 0
1546 int place= SVAL(data,0);
1547 /* we currently have no way of doing this. Can any unix do it? */
1548 if (i < place) /* move down */;
1549 else if (i > place ) /* move up */;
1551 #endif
1552 desc.errcode=NERR_notsupported; /* not yet supported */
1553 if (queue) free(queue);
1556 else desc.errcode=NERR_JobNotFound;
1557 break;
1558 case 0xb: /* change print job name, data gives the name */
1559 /* jobid, snum should be zero */
1560 if (isalpha(*s))
1562 pstring name;
1563 int l = 0;
1564 while (l<64 && *s)
1566 if (issafe(*s)) name[l++] = *s;
1567 s++;
1569 name[l] = 0;
1571 DEBUG(3,("Setting print name to %s\n",name));
1573 for (i=0;i<MAX_OPEN_FILES;i++)
1574 if (Files[i].open && Files[i].print_file)
1576 pstring wd;
1577 GetWd(wd);
1578 unbecome_user();
1580 if (!become_user(Files[i].cnum,vuid) ||
1581 !become_service(Files[i].cnum,True))
1582 break;
1584 if (sys_rename(Files[i].name,name) == 0)
1585 string_set(&Files[i].name,name);
1586 break;
1589 desc.errcode=NERR_Success;
1591 break;
1592 default: /* not implemented */
1593 return False;
1596 SSVALS(*rparam,0,desc.errcode);
1597 SSVAL(*rparam,2,0); /* converter word */
1599 return(True);
1603 /****************************************************************************
1604 get info about the server
1605 ****************************************************************************/
1606 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1607 int mdrcnt,int mprcnt,
1608 char **rdata,char **rparam,
1609 int *rdata_len,int *rparam_len)
1611 char *str1 = param+2;
1612 char *str2 = skip_string(str1,1);
1613 char *p = skip_string(str2,1);
1614 int uLevel = SVAL(p,0);
1615 char *p2;
1616 int struct_len;
1618 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1620 /* check it's a supported varient */
1621 if (!prefix_ok(str1,"WrLh")) return False;
1622 switch( uLevel ) {
1623 case 0:
1624 if (strcmp(str2,"B16") != 0) return False;
1625 struct_len = 16;
1626 break;
1627 case 1:
1628 if (strcmp(str2,"B16BBDz") != 0) return False;
1629 struct_len = 26;
1630 break;
1631 case 2:
1632 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1633 != 0) return False;
1634 struct_len = 134;
1635 break;
1636 case 3:
1637 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1638 != 0) return False;
1639 struct_len = 144;
1640 break;
1641 case 20:
1642 if (strcmp(str2,"DN") != 0) return False;
1643 struct_len = 6;
1644 break;
1645 case 50:
1646 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1647 struct_len = 42;
1648 break;
1649 default: return False;
1652 *rdata_len = mdrcnt;
1653 *rdata = REALLOC(*rdata,*rdata_len);
1655 p = *rdata;
1656 p2 = p + struct_len;
1657 if (uLevel != 20) {
1658 StrnCpy(p,local_machine,16);
1659 strupper(p);
1661 p += 16;
1662 if (uLevel > 0)
1664 struct srv_info_struct *servers=NULL;
1665 int i,count;
1666 pstring comment;
1667 uint32 servertype=DFLT_SERVER_TYPE;
1669 strcpy(comment,lp_serverstring());
1671 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
1672 for (i=0;i<count;i++)
1673 if (strequal(servers[i].name,local_machine))
1675 servertype = servers[i].type;
1676 strcpy(comment,servers[i].comment);
1679 if (servers) free(servers);
1681 SCVAL(p,0,MAJOR_VERSION);
1682 SCVAL(p,1,MINOR_VERSION);
1683 SIVAL(p,2,servertype);
1685 if (mdrcnt == struct_len) {
1686 SIVAL(p,6,0);
1687 } else {
1688 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1689 standard_sub(cnum,comment);
1690 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1691 p2 = skip_string(p2,1);
1694 if (uLevel > 1)
1696 return False; /* not yet implemented */
1699 *rdata_len = PTR_DIFF(p2,*rdata);
1701 *rparam_len = 6;
1702 *rparam = REALLOC(*rparam,*rparam_len);
1703 SSVAL(*rparam,0,NERR_Success);
1704 SSVAL(*rparam,2,0); /* converter word */
1705 SSVAL(*rparam,4,*rdata_len);
1707 return(True);
1711 /****************************************************************************
1712 get info about the server
1713 ****************************************************************************/
1714 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1715 int mdrcnt,int mprcnt,
1716 char **rdata,char **rparam,
1717 int *rdata_len,int *rparam_len)
1719 char *str1 = param+2;
1720 char *str2 = skip_string(str1,1);
1721 char *p = skip_string(str2,1);
1722 char *p2;
1723 extern pstring sesssetup_user;
1724 int level = SVAL(p,0);
1726 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1728 *rparam_len = 6;
1729 *rparam = REALLOC(*rparam,*rparam_len);
1731 /* check it's a supported varient */
1732 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1733 return(False);
1735 *rdata_len = mdrcnt + 1024;
1736 *rdata = REALLOC(*rdata,*rdata_len);
1738 SSVAL(*rparam,0,NERR_Success);
1739 SSVAL(*rparam,2,0); /* converter word */
1741 p = *rdata;
1742 p2 = p + 22;
1745 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1746 strcpy(p2,local_machine);
1747 strupper(p2);
1748 p2 = skip_string(p2,1);
1749 p += 4;
1751 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1752 strcpy(p2,sesssetup_user);
1753 p2 = skip_string(p2,1);
1754 p += 4;
1756 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1757 strcpy(p2,lp_workgroup());
1758 strupper(p2);
1759 p2 = skip_string(p2,1);
1760 p += 4;
1762 SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */
1763 SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */
1764 p += 2;
1766 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1767 strcpy(p2,lp_workgroup()); /* don't know. login domain?? */
1768 p2 = skip_string(p2,1);
1769 p += 4;
1771 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1772 strcpy(p2,"");
1773 p2 = skip_string(p2,1);
1774 p += 4;
1776 *rdata_len = PTR_DIFF(p2,*rdata);
1778 SSVAL(*rparam,4,*rdata_len);
1780 return(True);
1783 /****************************************************************************
1784 get info about a user
1786 struct user_info_11 {
1787 char usri11_name[21]; 0-20
1788 char usri11_pad; 21
1789 char *usri11_comment; 22-25
1790 char *usri11_usr_comment; 26-29
1791 unsigned short usri11_priv; 30-31
1792 unsigned long usri11_auth_flags; 32-35
1793 long usri11_password_age; 36-39
1794 char *usri11_homedir; 40-43
1795 char *usri11_parms; 44-47
1796 long usri11_last_logon; 48-51
1797 long usri11_last_logoff; 52-55
1798 unsigned short usri11_bad_pw_count; 56-57
1799 unsigned short usri11_num_logons; 58-59
1800 char *usri11_logon_server; 60-63
1801 unsigned short usri11_country_code; 64-65
1802 char *usri11_workstations; 66-69
1803 unsigned long usri11_max_storage; 70-73
1804 unsigned short usri11_units_per_week; 74-75
1805 unsigned char *usri11_logon_hours; 76-79
1806 unsigned short usri11_code_page; 80-81
1809 where:
1811 usri11_name specifies the user name for which information is retireved
1813 usri11_pad aligns the next data structure element to a word boundary
1815 usri11_comment is a null terminated ASCII comment
1817 usri11_user_comment is a null terminated ASCII comment about the user
1819 usri11_priv specifies the level of the privilege assigned to the user.
1820 The possible values are:
1822 Name Value Description
1823 USER_PRIV_GUEST 0 Guest privilege
1824 USER_PRIV_USER 1 User privilege
1825 USER_PRV_ADMIN 2 Administrator privilege
1827 usri11_auth_flags specifies the account operator privileges. The
1828 possible values are:
1830 Name Value Description
1831 AF_OP_PRINT 0 Print operator
1834 Leach, Naik [Page 28] \f
1837 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1840 AF_OP_COMM 1 Communications operator
1841 AF_OP_SERVER 2 Server operator
1842 AF_OP_ACCOUNTS 3 Accounts operator
1845 usri11_password_age specifies how many seconds have elapsed since the
1846 password was last changed.
1848 usri11_home_dir points to a null terminated ASCII string that contains
1849 the path name of the user's home directory.
1851 usri11_parms points to a null terminated ASCII string that is set
1852 aside for use by applications.
1854 usri11_last_logon specifies the time when the user last logged on.
1855 This value is stored as the number of seconds elapsed since
1856 00:00:00, January 1, 1970.
1858 usri11_last_logoff specifies the time when the user last logged off.
1859 This value is stored as the number of seconds elapsed since
1860 00:00:00, January 1, 1970. A value of 0 means the last logoff
1861 time is unknown.
1863 usri11_bad_pw_count specifies the number of incorrect passwords
1864 entered since the last successful logon.
1866 usri11_log1_num_logons specifies the number of times this user has
1867 logged on. A value of -1 means the number of logons is unknown.
1869 usri11_logon_server points to a null terminated ASCII string that
1870 contains the name of the server to which logon requests are sent.
1871 A null string indicates logon requests should be sent to the
1872 domain controller.
1874 usri11_country_code specifies the country code for the user's language
1875 of choice.
1877 usri11_workstations points to a null terminated ASCII string that
1878 contains the names of workstations the user may log on from.
1879 There may be up to 8 workstations, with the names separated by
1880 commas. A null strings indicates there are no restrictions.
1882 usri11_max_storage specifies the maximum amount of disk space the user
1883 can occupy. A value of 0xffffffff indicates there are no
1884 restrictions.
1886 usri11_units_per_week specifies the equal number of time units into
1887 which a week is divided. This value must be equal to 168.
1889 usri11_logon_hours points to a 21 byte (168 bits) string that
1890 specifies the time during which the user can log on. Each bit
1891 represents one unique hour in a week. The first bit (bit 0, word
1892 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1896 Leach, Naik [Page 29] \f
1899 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1902 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1903 are no restrictions.
1905 usri11_code_page specifies the code page for the user's language of
1906 choice
1908 All of the pointers in this data structure need to be treated
1909 specially. The pointer is a 32 bit pointer. The higher 16 bits need
1910 to be ignored. The converter word returned in the parameters section
1911 needs to be subtracted from the lower 16 bits to calculate an offset
1912 into the return buffer where this ASCII string resides.
1914 There is no auxiliary data in the response.
1916 ****************************************************************************/
1918 #define usri11_name 0
1919 #define usri11_pad 21
1920 #define usri11_comment 22
1921 #define usri11_usr_comment 26
1922 #define usri11_full_name 30
1923 #define usri11_priv 34
1924 #define usri11_auth_flags 36
1925 #define usri11_password_age 40
1926 #define usri11_homedir 44
1927 #define usri11_parms 48
1928 #define usri11_last_logon 52
1929 #define usri11_last_logoff 56
1930 #define usri11_bad_pw_count 60
1931 #define usri11_num_logons 62
1932 #define usri11_logon_server 64
1933 #define usri11_country_code 68
1934 #define usri11_workstations 70
1935 #define usri11_max_storage 74
1936 #define usri11_units_per_week 78
1937 #define usri11_logon_hours 80
1938 #define usri11_code_page 84
1939 #define usri11_end 86
1941 #define USER_PRIV_GUEST 0
1942 #define USER_PRIV_USER 1
1943 #define USER_PRIV_ADMIN 2
1945 #define AF_OP_PRINT 0
1946 #define AF_OP_COMM 1
1947 #define AF_OP_SERVER 2
1948 #define AF_OP_ACCOUNTS 3
1951 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1952 int mdrcnt,int mprcnt,
1953 char **rdata,char **rparam,
1954 int *rdata_len,int *rparam_len)
1956 char *str1 = param+2;
1957 char *str2 = skip_string(str1,1);
1958 char *UserName = skip_string(str2,1);
1959 char *p = skip_string(UserName,1);
1960 int uLevel = SVAL(p,0);
1961 char *p2;
1963 /* get NIS home of a previously validated user - simeon */
1964 user_struct *vuser = get_valid_user_struct(vuid);
1965 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
1966 #if (defined(NETGROUP) && defined(AUTOMOUNT))
1967 DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
1968 #endif
1970 *rparam_len = 6;
1971 *rparam = REALLOC(*rparam,*rparam_len);
1973 /* check it's a supported variant */
1974 if (strcmp(str1,"zWrLh") != 0) return False;
1975 switch( uLevel )
1977 case 0: p2 = "B21"; break;
1978 case 1: p2 = "B21BB16DWzzWz"; break;
1979 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1980 case 10: p2 = "B21Bzzz"; break;
1981 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1982 default: return False;
1985 if (strcmp(p2,str2) != 0) return False;
1987 *rdata_len = mdrcnt + 1024;
1988 *rdata = REALLOC(*rdata,*rdata_len);
1990 SSVAL(*rparam,0,NERR_Success);
1991 SSVAL(*rparam,2,0); /* converter word */
1993 p = *rdata;
1994 p2 = p + usri11_end;
1996 memset(p,0,21);
1997 strcpy(p+usri11_name,UserName); /* 21 bytes - user name */
1999 if (uLevel > 0)
2001 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2002 *p2 = 0;
2004 if (uLevel >= 10)
2006 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2007 strcpy(p2,"Comment");
2008 p2 = skip_string(p2,1);
2010 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2011 strcpy(p2,"UserComment");
2012 p2 = skip_string(p2,1);
2014 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2015 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2016 strcpy(p2,vuser->real_name); /* simeon */
2017 p2 = skip_string(p2,1);
2020 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2022 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2023 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2024 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2025 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2026 if (*lp_logon_path())
2028 strcpy(p2,lp_logon_path());
2030 else
2032 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2033 strcpy(p2, vuser->home_share);
2034 #else
2035 strcpy(p2,"\\\\%L\\%U");
2036 #endif
2038 standard_sub_basic(p2);
2039 p2 = skip_string(p2,1);
2040 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2041 strcpy(p2,"");
2042 p2 = skip_string(p2,1);
2043 SIVAL(p,usri11_last_logon,0); /* last logon */
2044 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2045 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2046 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2047 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2048 strcpy(p2,"\\\\*");
2049 p2 = skip_string(p2,1);
2050 SSVAL(p,usri11_country_code,0); /* country code */
2052 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2053 strcpy(p2,"");
2054 p2 = skip_string(p2,1);
2056 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2057 SSVAL(p,usri11_units_per_week,168); /* units per week */
2058 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2060 /* a simple way to get logon hours at all times. */
2061 memset(p2,0xff,21);
2062 SCVAL(p2,21,0); /* fix zero termination */
2063 p2 = skip_string(p2,1);
2065 SSVAL(p,usri11_code_page,0); /* code page */
2067 if (uLevel == 1 || uLevel == 2)
2069 memset(p+22,' ',16); /* password */
2070 SIVALS(p,38,-1); /* password age */
2071 SSVAL(p,42,
2072 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2073 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2074 if (*lp_logon_path())
2076 strcpy(p2,lp_logon_path());
2078 else
2080 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2081 strcpy(p2, vuser->home_share);
2082 #else
2083 strcpy(p2,"\\\\%L\\%U");
2084 #endif
2086 standard_sub_basic(p2);
2087 p2 = skip_string(p2,1);
2088 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2089 *p2++ = 0;
2090 SSVAL(p,52,0); /* flags */
2091 SIVAL(p,54,0); /* script_path */
2092 if (uLevel == 2)
2094 SIVAL(p,60,0); /* auth_flags */
2095 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2096 strcpy(p2,vuser->real_name); /* simeon */
2097 p2 = skip_string(p2,1);
2098 SIVAL(p,68,0); /* urs_comment */
2099 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2100 strcpy(p2,"");
2101 p2 = skip_string(p2,1);
2102 SIVAL(p,76,0); /* workstations */
2103 SIVAL(p,80,0); /* last_logon */
2104 SIVAL(p,84,0); /* last_logoff */
2105 SIVALS(p,88,-1); /* acct_expires */
2106 SIVALS(p,92,-1); /* max_storage */
2107 SSVAL(p,96,168); /* units_per_week */
2108 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2109 memset(p2,-1,21);
2110 p2 += 21;
2111 SSVALS(p,102,-1); /* bad_pw_count */
2112 SSVALS(p,104,-1); /* num_logons */
2113 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2114 strcpy(p2,"\\\\%L");
2115 standard_sub_basic(p2);
2116 p2 = skip_string(p2,1);
2117 SSVAL(p,110,49); /* country_code */
2118 SSVAL(p,112,860); /* code page */
2122 *rdata_len = PTR_DIFF(p2,*rdata);
2124 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2126 return(True);
2129 /*******************************************************************
2130 get groups that a user is a member of
2131 ******************************************************************/
2132 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2133 int mdrcnt,int mprcnt,
2134 char **rdata,char **rparam,
2135 int *rdata_len,int *rparam_len)
2137 char *str1 = param+2;
2138 char *str2 = skip_string(str1,1);
2139 char *UserName = skip_string(str2,1);
2140 char *p = skip_string(UserName,1);
2141 int uLevel = SVAL(p,0);
2142 char *p2;
2143 int count=0;
2145 *rparam_len = 8;
2146 *rparam = REALLOC(*rparam,*rparam_len);
2148 /* check it's a supported varient */
2149 if (strcmp(str1,"zWrLeh") != 0) return False;
2150 switch( uLevel ) {
2151 case 0: p2 = "B21"; break;
2152 default: return False;
2154 if (strcmp(p2,str2) != 0) return False;
2156 *rdata_len = mdrcnt + 1024;
2157 *rdata = REALLOC(*rdata,*rdata_len);
2159 SSVAL(*rparam,0,NERR_Success);
2160 SSVAL(*rparam,2,0); /* converter word */
2162 p = *rdata;
2164 /* XXXX we need a real SAM database some day */
2165 strcpy(p,"Users"); p += 21; count++;
2166 strcpy(p,"Domain Users"); p += 21; count++;
2167 strcpy(p,"Guests"); p += 21; count++;
2168 strcpy(p,"Domain Guests"); p += 21; count++;
2170 *rdata_len = PTR_DIFF(p,*rdata);
2172 SSVAL(*rparam,4,count); /* is this right?? */
2173 SSVAL(*rparam,6,count); /* is this right?? */
2175 return(True);
2179 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2180 int mdrcnt,int mprcnt,
2181 char **rdata,char **rparam,
2182 int *rdata_len,int *rparam_len)
2184 char *str1 = param+2;
2185 char *str2 = skip_string(str1,1);
2186 char *p = skip_string(str2,1);
2187 int uLevel;
2188 struct pack_desc desc;
2189 char* name;
2191 uLevel = SVAL(p,0);
2192 name = p + 2;
2194 bzero(&desc,sizeof(desc));
2196 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2198 /* check it's a supported varient */
2199 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2200 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2201 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2202 desc.base = *rdata;
2203 desc.buflen = mdrcnt;
2204 desc.subformat = NULL;
2205 desc.format = str2;
2207 if (init_package(&desc,1,0))
2209 PACKI(&desc,"W",0); /* code */
2210 PACKS(&desc,"B21",name); /* eff. name */
2211 PACKS(&desc,"B",""); /* pad */
2212 PACKI(&desc,"W",
2213 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2214 PACKI(&desc,"D",0); /* auth flags XXX */
2215 PACKI(&desc,"W",0); /* num logons */
2216 PACKI(&desc,"W",0); /* bad pw count */
2217 PACKI(&desc,"D",0); /* last logon */
2218 PACKI(&desc,"D",-1); /* last logoff */
2219 PACKI(&desc,"D",-1); /* logoff time */
2220 PACKI(&desc,"D",-1); /* kickoff time */
2221 PACKI(&desc,"D",0); /* password age */
2222 PACKI(&desc,"D",0); /* password can change */
2223 PACKI(&desc,"D",-1); /* password must change */
2225 fstring mypath;
2226 strcpy(mypath,"\\\\");
2227 strcat(mypath,local_machine);
2228 strupper(mypath);
2229 PACKS(&desc,"z",mypath); /* computer */
2231 PACKS(&desc,"z",lp_workgroup());/* domain */
2232 PACKS(&desc,"z",lp_logon_script()); /* script path */
2233 PACKI(&desc,"D",0x00000000); /* reserved */
2236 *rdata_len = desc.usedlen;
2237 *rparam_len = 6;
2238 *rparam = REALLOC(*rparam,*rparam_len);
2239 SSVALS(*rparam,0,desc.errcode);
2240 SSVAL(*rparam,2,0);
2241 SSVAL(*rparam,4,desc.neededlen);
2243 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2244 return(True);
2248 /****************************************************************************
2249 api_WAccessGetUserPerms
2250 ****************************************************************************/
2251 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2252 int mdrcnt,int mprcnt,
2253 char **rdata,char **rparam,
2254 int *rdata_len,int *rparam_len)
2256 char *str1 = param+2;
2257 char *str2 = skip_string(str1,1);
2258 char *user = skip_string(str2,1);
2259 char *resource = skip_string(user,1);
2261 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2263 /* check it's a supported varient */
2264 if (strcmp(str1,"zzh") != 0) return False;
2265 if (strcmp(str2,"") != 0) return False;
2267 *rparam_len = 6;
2268 *rparam = REALLOC(*rparam,*rparam_len);
2269 SSVALS(*rparam,0,0); /* errorcode */
2270 SSVAL(*rparam,2,0); /* converter word */
2271 SSVAL(*rparam,4,0x7f); /* permission flags */
2273 return(True);
2276 /****************************************************************************
2277 api_WPrintJobEnumerate
2278 ****************************************************************************/
2279 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2280 int mdrcnt,int mprcnt,
2281 char **rdata,char **rparam,
2282 int *rdata_len,int *rparam_len)
2284 char *str1 = param+2;
2285 char *str2 = skip_string(str1,1);
2286 char *p = skip_string(str2,1);
2287 int uJobId = SVAL(p,0);
2288 int uLevel,cbBuf;
2289 int count;
2290 int i;
2291 int snum;
2292 int job;
2293 struct pack_desc desc;
2294 print_queue_struct *queue=NULL;
2295 print_status_struct status;
2297 uLevel = SVAL(p,2);
2298 cbBuf = SVAL(p,4);
2300 bzero(&desc,sizeof(desc));
2301 bzero(&status,sizeof(status));
2303 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2305 /* check it's a supported varient */
2306 if (strcmp(str1,"WWrLh") != 0) return False;
2307 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2309 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2310 job = uJobId & 0xFF;
2312 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2314 count = get_printqueue(snum,cnum,&queue,&status);
2315 for (i = 0; i < count; i++) {
2316 if ((queue[i].job % 0xFF) == job) break;
2318 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2319 desc.base = *rdata;
2320 desc.buflen = mdrcnt;
2322 if (init_package(&desc,1,0)) {
2323 if (i < count) {
2324 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2325 *rdata_len = desc.usedlen;
2327 else {
2328 desc.errcode = NERR_JobNotFound;
2329 *rdata_len = 0;
2333 *rparam_len = 6;
2334 *rparam = REALLOC(*rparam,*rparam_len);
2335 SSVALS(*rparam,0,desc.errcode);
2336 SSVAL(*rparam,2,0);
2337 SSVAL(*rparam,4,desc.neededlen);
2339 if (queue) free(queue);
2341 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2342 return(True);
2345 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2346 int mdrcnt,int mprcnt,
2347 char **rdata,char **rparam,
2348 int *rdata_len,int *rparam_len)
2350 char *str1 = param+2;
2351 char *str2 = skip_string(str1,1);
2352 char *p = skip_string(str2,1);
2353 char* name = p;
2354 int uLevel,cbBuf;
2355 int count;
2356 int i, succnt=0;
2357 int snum;
2358 struct pack_desc desc;
2359 print_queue_struct *queue=NULL;
2360 print_status_struct status;
2362 bzero(&desc,sizeof(desc));
2363 bzero(&status,sizeof(status));
2365 p = skip_string(p,1);
2366 uLevel = SVAL(p,0);
2367 cbBuf = SVAL(p,2);
2369 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2371 /* check it's a supported varient */
2372 if (strcmp(str1,"zWrLeh") != 0) return False;
2373 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2374 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2376 snum = lp_servicenumber(name);
2377 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2378 int pnum = lp_servicenumber(PRINTERS_NAME);
2379 if (pnum >= 0) {
2380 lp_add_printer(name,pnum);
2381 snum = lp_servicenumber(name);
2385 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2387 count = get_printqueue(snum,cnum,&queue,&status);
2388 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2389 desc.base = *rdata;
2390 desc.buflen = mdrcnt;
2392 if (init_package(&desc,count,0)) {
2393 succnt = 0;
2394 for (i = 0; i < count; i++) {
2395 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2396 if (desc.errcode == NERR_Success) succnt = i+1;
2400 *rdata_len = desc.usedlen;
2402 *rparam_len = 8;
2403 *rparam = REALLOC(*rparam,*rparam_len);
2404 SSVALS(*rparam,0,desc.errcode);
2405 SSVAL(*rparam,2,0);
2406 SSVAL(*rparam,4,succnt);
2407 SSVAL(*rparam,6,count);
2409 if (queue) free(queue);
2411 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2412 return(True);
2415 static int check_printdest_info(struct pack_desc* desc,
2416 int uLevel, char* id)
2418 desc->subformat = NULL;
2419 switch( uLevel ) {
2420 case 0: desc->format = "B9"; break;
2421 case 1: desc->format = "B9B21WWzW"; break;
2422 case 2: desc->format = "z"; break;
2423 case 3: desc->format = "zzzWWzzzWW"; break;
2424 default: return False;
2426 if (strcmp(desc->format,id) != 0) return False;
2427 return True;
2430 static void fill_printdest_info(int cnum, int snum, int uLevel,
2431 struct pack_desc* desc)
2433 char buf[100];
2434 strcpy(buf,SERVICE(snum));
2435 strupper(buf);
2436 if (uLevel <= 1) {
2437 PACKS(desc,"B9",buf); /* szName */
2438 if (uLevel == 1) {
2439 PACKS(desc,"B21",""); /* szUserName */
2440 PACKI(desc,"W",0); /* uJobId */
2441 PACKI(desc,"W",0); /* fsStatus */
2442 PACKS(desc,"z",""); /* pszStatus */
2443 PACKI(desc,"W",0); /* time */
2446 if (uLevel == 2 || uLevel == 3) {
2447 PACKS(desc,"z",buf); /* pszPrinterName */
2448 if (uLevel == 3) {
2449 PACKS(desc,"z",""); /* pszUserName */
2450 PACKS(desc,"z",""); /* pszLogAddr */
2451 PACKI(desc,"W",0); /* uJobId */
2452 PACKI(desc,"W",0); /* fsStatus */
2453 PACKS(desc,"z",""); /* pszStatus */
2454 PACKS(desc,"z",""); /* pszComment */
2455 PACKS(desc,"z","NULL"); /* pszDrivers */
2456 PACKI(desc,"W",0); /* time */
2457 PACKI(desc,"W",0); /* pad1 */
2462 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2463 int mdrcnt,int mprcnt,
2464 char **rdata,char **rparam,
2465 int *rdata_len,int *rparam_len)
2467 char *str1 = param+2;
2468 char *str2 = skip_string(str1,1);
2469 char *p = skip_string(str2,1);
2470 char* PrinterName = p;
2471 int uLevel,cbBuf;
2472 struct pack_desc desc;
2473 int snum;
2475 bzero(&desc,sizeof(desc));
2477 p = skip_string(p,1);
2478 uLevel = SVAL(p,0);
2479 cbBuf = SVAL(p,2);
2481 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2483 /* check it's a supported varient */
2484 if (strcmp(str1,"zWrLh") != 0) return False;
2485 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2487 snum = lp_servicenumber(PrinterName);
2488 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2489 int pnum = lp_servicenumber(PRINTERS_NAME);
2490 if (pnum >= 0) {
2491 lp_add_printer(PrinterName,pnum);
2492 snum = lp_servicenumber(PrinterName);
2496 if (snum < 0) {
2497 *rdata_len = 0;
2498 desc.errcode = NERR_DestNotFound;
2499 desc.neededlen = 0;
2501 else {
2502 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2503 desc.base = *rdata;
2504 desc.buflen = mdrcnt;
2505 if (init_package(&desc,1,0)) {
2506 fill_printdest_info(cnum,snum,uLevel,&desc);
2508 *rdata_len = desc.usedlen;
2511 *rparam_len = 6;
2512 *rparam = REALLOC(*rparam,*rparam_len);
2513 SSVALS(*rparam,0,desc.errcode);
2514 SSVAL(*rparam,2,0);
2515 SSVAL(*rparam,4,desc.neededlen);
2517 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2518 return(True);
2521 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2522 int mdrcnt,int mprcnt,
2523 char **rdata,char **rparam,
2524 int *rdata_len,int *rparam_len)
2526 char *str1 = param+2;
2527 char *str2 = skip_string(str1,1);
2528 char *p = skip_string(str2,1);
2529 int uLevel,cbBuf;
2530 int queuecnt;
2531 int i, n, succnt=0;
2532 struct pack_desc desc;
2533 int services = lp_numservices();
2535 bzero(&desc,sizeof(desc));
2537 uLevel = SVAL(p,0);
2538 cbBuf = SVAL(p,2);
2540 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2542 /* check it's a supported varient */
2543 if (strcmp(str1,"WrLeh") != 0) return False;
2544 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2546 queuecnt = 0;
2547 for (i = 0; i < services; i++)
2548 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2549 queuecnt++;
2551 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2552 desc.base = *rdata;
2553 desc.buflen = mdrcnt;
2554 if (init_package(&desc,queuecnt,0)) {
2555 succnt = 0;
2556 n = 0;
2557 for (i = 0; i < services; i++) {
2558 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2559 fill_printdest_info(cnum,i,uLevel,&desc);
2560 n++;
2561 if (desc.errcode == NERR_Success) succnt = n;
2566 *rdata_len = desc.usedlen;
2568 *rparam_len = 8;
2569 *rparam = REALLOC(*rparam,*rparam_len);
2570 SSVALS(*rparam,0,desc.errcode);
2571 SSVAL(*rparam,2,0);
2572 SSVAL(*rparam,4,succnt);
2573 SSVAL(*rparam,6,queuecnt);
2575 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2576 return(True);
2579 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2580 int mdrcnt,int mprcnt,
2581 char **rdata,char **rparam,
2582 int *rdata_len,int *rparam_len)
2584 char *str1 = param+2;
2585 char *str2 = skip_string(str1,1);
2586 char *p = skip_string(str2,1);
2587 int uLevel,cbBuf;
2588 int succnt;
2589 struct pack_desc desc;
2591 bzero(&desc,sizeof(desc));
2593 uLevel = SVAL(p,0);
2594 cbBuf = SVAL(p,2);
2596 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2598 /* check it's a supported varient */
2599 if (strcmp(str1,"WrLeh") != 0) return False;
2600 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2602 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2603 desc.base = *rdata;
2604 desc.buflen = mdrcnt;
2605 if (init_package(&desc,1,0)) {
2606 PACKS(&desc,"B41","NULL");
2609 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2611 *rdata_len = desc.usedlen;
2613 *rparam_len = 8;
2614 *rparam = REALLOC(*rparam,*rparam_len);
2615 SSVALS(*rparam,0,desc.errcode);
2616 SSVAL(*rparam,2,0);
2617 SSVAL(*rparam,4,succnt);
2618 SSVAL(*rparam,6,1);
2620 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2621 return(True);
2624 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2625 int mdrcnt,int mprcnt,
2626 char **rdata,char **rparam,
2627 int *rdata_len,int *rparam_len)
2629 char *str1 = param+2;
2630 char *str2 = skip_string(str1,1);
2631 char *p = skip_string(str2,1);
2632 int uLevel,cbBuf;
2633 int succnt;
2634 struct pack_desc desc;
2636 bzero(&desc,sizeof(desc));
2638 uLevel = SVAL(p,0);
2639 cbBuf = SVAL(p,2);
2641 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2643 /* check it's a supported varient */
2644 if (strcmp(str1,"WrLeh") != 0) return False;
2645 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2647 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2648 desc.base = *rdata;
2649 desc.buflen = mdrcnt;
2650 desc.format = str2;
2651 if (init_package(&desc,1,0)) {
2652 PACKS(&desc,"B13","lpd");
2655 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2657 *rdata_len = desc.usedlen;
2659 *rparam_len = 8;
2660 *rparam = REALLOC(*rparam,*rparam_len);
2661 SSVALS(*rparam,0,desc.errcode);
2662 SSVAL(*rparam,2,0);
2663 SSVAL(*rparam,4,succnt);
2664 SSVAL(*rparam,6,1);
2666 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2667 return(True);
2670 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2671 int mdrcnt,int mprcnt,
2672 char **rdata,char **rparam,
2673 int *rdata_len,int *rparam_len)
2675 char *str1 = param+2;
2676 char *str2 = skip_string(str1,1);
2677 char *p = skip_string(str2,1);
2678 int uLevel,cbBuf;
2679 int succnt;
2680 struct pack_desc desc;
2682 bzero(&desc,sizeof(desc));
2684 uLevel = SVAL(p,0);
2685 cbBuf = SVAL(p,2);
2687 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2689 /* check it's a supported varient */
2690 if (strcmp(str1,"WrLeh") != 0) return False;
2691 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2693 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2694 bzero(&desc,sizeof(desc));
2695 desc.base = *rdata;
2696 desc.buflen = mdrcnt;
2697 desc.format = str2;
2698 if (init_package(&desc,1,0)) {
2699 PACKS(&desc,"B13","lp0");
2702 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2704 *rdata_len = desc.usedlen;
2706 *rparam_len = 8;
2707 *rparam = REALLOC(*rparam,*rparam_len);
2708 SSVALS(*rparam,0,desc.errcode);
2709 SSVAL(*rparam,2,0);
2710 SSVAL(*rparam,4,succnt);
2711 SSVAL(*rparam,6,1);
2713 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2714 return(True);
2718 struct
2720 char * name;
2721 char * pipename;
2722 int subcommand;
2723 BOOL (*fn) ();
2724 } api_fd_commands [] =
2726 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2727 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2728 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2731 /****************************************************************************
2732 handle remote api calls delivered to a named pipe already opened.
2733 ****************************************************************************/
2734 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2735 uint16 *setup,char *data,char *params,
2736 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2738 char *rdata = NULL;
2739 char *rparam = NULL;
2740 int rdata_len = 0;
2741 int rparam_len = 0;
2742 BOOL reply=False;
2743 int i;
2744 int fd;
2745 int subcommand;
2747 /* First find out the name of this file. */
2748 if (suwcnt != 2)
2750 DEBUG(0,("Unexpected named pipe transaction.\n"));
2751 return(-1);
2754 /* Get the file handle and hence the file name. */
2755 fd = setup[1];
2756 subcommand = setup[0];
2758 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2759 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2760 tdscnt,tpscnt,mdrcnt,mprcnt));
2762 for (i=0;api_fd_commands[i].name;i++)
2763 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2764 api_fd_commands[i].subcommand == subcommand &&
2765 api_fd_commands[i].fn)
2767 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2768 break;
2771 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2772 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2774 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2775 &rdata,&rparam,&rdata_len,&rparam_len);
2777 if (rdata_len > mdrcnt ||
2778 rparam_len > mprcnt)
2780 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2781 &rdata,&rparam,&rdata_len,&rparam_len);
2785 /* if we get False back then it's actually unsupported */
2786 if (!reply)
2787 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2788 &rdata,&rparam,&rdata_len,&rparam_len);
2790 /* now send the reply */
2791 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2793 if (rdata)
2794 free(rdata);
2795 if (rparam)
2796 free(rparam);
2798 return(-1);
2803 /****************************************************************************
2804 the buffer was too small
2805 ****************************************************************************/
2806 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2807 int mdrcnt,int mprcnt,
2808 char **rdata,char **rparam,
2809 int *rdata_len,int *rparam_len)
2811 *rparam_len = MIN(*rparam_len,mprcnt);
2812 *rparam = REALLOC(*rparam,*rparam_len);
2814 *rdata_len = 0;
2816 SSVAL(*rparam,0,NERR_BufTooSmall);
2818 DEBUG(3,("Supplied buffer too small in API command\n"));
2820 return(True);
2824 /****************************************************************************
2825 the request is not supported
2826 ****************************************************************************/
2827 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2828 int mdrcnt,int mprcnt,
2829 char **rdata,char **rparam,
2830 int *rdata_len,int *rparam_len)
2832 *rparam_len = 4;
2833 *rparam = REALLOC(*rparam,*rparam_len);
2835 *rdata_len = 0;
2837 SSVAL(*rparam,0,NERR_notsupported);
2838 SSVAL(*rparam,2,0); /* converter word */
2840 DEBUG(3,("Unsupported API command\n"));
2842 return(True);
2848 struct
2850 char *name;
2851 int id;
2852 BOOL (*fn)();
2853 int flags;
2854 } api_commands[] = {
2855 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
2856 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
2857 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
2858 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
2859 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
2860 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
2861 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
2862 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
2863 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
2864 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
2865 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
2866 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
2867 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
2868 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
2869 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
2870 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
2871 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
2872 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
2873 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
2874 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
2875 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
2876 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
2877 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
2878 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
2879 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
2880 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
2883 /****************************************************************************
2884 handle remote api calls
2885 ****************************************************************************/
2886 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2887 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2889 int api_command = SVAL(params,0);
2890 char *rdata = NULL;
2891 char *rparam = NULL;
2892 int rdata_len = 0;
2893 int rparam_len = 0;
2894 BOOL reply=False;
2895 int i;
2897 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2898 api_command,params+2,skip_string(params+2,1),
2899 tdscnt,tpscnt,mdrcnt,mprcnt));
2901 for (i=0;api_commands[i].name;i++)
2902 if (api_commands[i].id == api_command && api_commands[i].fn)
2904 DEBUG(3,("Doing %s\n",api_commands[i].name));
2905 break;
2908 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2909 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2911 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2912 &rdata,&rparam,&rdata_len,&rparam_len);
2915 if (rdata_len > mdrcnt ||
2916 rparam_len > mprcnt)
2918 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2919 &rdata,&rparam,&rdata_len,&rparam_len);
2923 /* if we get False back then it's actually unsupported */
2924 if (!reply)
2925 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2926 &rdata,&rparam,&rdata_len,&rparam_len);
2930 /* now send the reply */
2931 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2933 if (rdata)
2934 free(rdata);
2935 if (rparam)
2936 free(rparam);
2938 return(-1);
2941 /****************************************************************************
2942 handle named pipe commands
2943 ****************************************************************************/
2944 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
2945 uint16 *setup,char *data,char *params,
2946 int suwcnt,int tdscnt,int tpscnt,
2947 int msrcnt,int mdrcnt,int mprcnt)
2950 if (strequal(name,"LANMAN"))
2951 return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2953 if (strlen(name) < 1)
2954 return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2957 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2958 name,(int)setup[0],(int)setup[1]));
2960 return(0);
2964 /****************************************************************************
2965 reply to a SMBtrans
2966 ****************************************************************************/
2967 int reply_trans(char *inbuf,char *outbuf)
2969 fstring name;
2971 char *data=NULL,*params=NULL;
2972 uint16 *setup=NULL;
2974 int outsize = 0;
2975 int cnum = SVAL(inbuf,smb_tid);
2976 uint16 vuid = SVAL(inbuf,smb_uid);
2978 int tpscnt = SVAL(inbuf,smb_vwv0);
2979 int tdscnt = SVAL(inbuf,smb_vwv1);
2980 int mprcnt = SVAL(inbuf,smb_vwv2);
2981 int mdrcnt = SVAL(inbuf,smb_vwv3);
2982 int msrcnt = CVAL(inbuf,smb_vwv4);
2983 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2984 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2985 int pscnt = SVAL(inbuf,smb_vwv9);
2986 int psoff = SVAL(inbuf,smb_vwv10);
2987 int dscnt = SVAL(inbuf,smb_vwv11);
2988 int dsoff = SVAL(inbuf,smb_vwv12);
2989 int suwcnt = CVAL(inbuf,smb_vwv13);
2991 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2993 if (tdscnt)
2995 data = (char *)malloc(tdscnt);
2996 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2998 if (tpscnt)
3000 params = (char *)malloc(tpscnt);
3001 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3004 if (suwcnt)
3006 int i;
3007 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3008 for (i=0;i<suwcnt;i++)
3009 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3013 if (pscnt < tpscnt || dscnt < tdscnt)
3015 /* We need to send an interim response then receive the rest
3016 of the parameter/data bytes */
3017 outsize = set_message(outbuf,0,0,True);
3018 show_msg(outbuf);
3019 send_smb(Client,outbuf);
3022 /* receive the rest of the trans packet */
3023 while (pscnt < tpscnt || dscnt < tdscnt)
3025 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3027 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3028 CVAL(inbuf, smb_com) != SMBtrans)
3030 DEBUG(2,("Invalid secondary trans2 packet\n"));
3031 if (params) free(params);
3032 if (data) free(data);
3033 if (setup) free(setup);
3034 return(ERROR(ERRSRV,ERRerror));
3037 show_msg(inbuf);
3039 tpscnt = SVAL(inbuf,smb_vwv0);
3040 tdscnt = SVAL(inbuf,smb_vwv1);
3042 pcnt = SVAL(inbuf,smb_vwv2);
3043 poff = SVAL(inbuf,smb_vwv3);
3044 pdisp = SVAL(inbuf,smb_vwv4);
3046 dcnt = SVAL(inbuf,smb_vwv5);
3047 doff = SVAL(inbuf,smb_vwv6);
3048 ddisp = SVAL(inbuf,smb_vwv7);
3050 pscnt += pcnt;
3051 dscnt += dcnt;
3053 if (pcnt)
3054 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3055 if (dcnt)
3056 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3060 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3063 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3064 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3065 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3068 if (data) free(data);
3069 if (params) free(params);
3070 if (setup) free(setup);
3072 if (close_on_completion)
3073 close_cnum(cnum,vuid);
3075 if (one_way)
3076 return(-1);
3078 if (outsize == 0)
3079 return(ERROR(ERRSRV,ERRnosupport));
3081 return(outsize);