Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / samba / source / smbd / ipc.c
blob5aabed992e8812c70606e65a2092d128db6c0ce3
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
7 SMB Version handling
8 Copyright (C) John H Terpstra 1995-1998
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.
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.
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.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
29 #include "includes.h"
30 #include "nterr.h"
32 #ifdef CHECK_TYPES
33 #undef CHECK_TYPES
34 #endif
35 #define CHECK_TYPES 0
37 extern int DEBUGLEVEL;
38 extern int max_send;
40 extern fstring local_machine;
41 extern fstring global_myworkgroup;
43 #define NERR_Success 0
44 #define NERR_badpass 86
45 #define NERR_notsupported 50
47 #define NERR_BASE (2100)
48 #define NERR_BufTooSmall (NERR_BASE+23)
49 #define NERR_JobNotFound (NERR_BASE+51)
50 #define NERR_DestNotFound (NERR_BASE+52)
51 #define ERROR_INVALID_LEVEL 124
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
58 #define NNLEN 12 /* 8.3 net name length */
59 #define SNLEN 15 /* service name length */
60 #define QNLEN 12 /* queue name maximum length */
62 extern int Client;
63 extern int smb_read_error;
65 static BOOL api_Unsupported(connection_struct *conn,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(connection_struct *conn,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(connection_struct *conn,
76 int snum, char** dst, char* src, int* n)
78 pstring buf;
79 int l;
81 if (!src || !dst || !n || !(*dst)) return(0);
83 StrnCpy(buf,src,sizeof(buf)/2);
84 pstring_sub(buf,"%S",lp_servicename(snum));
85 standard_sub(conn,buf);
86 StrnCpy(*dst,buf,*n);
87 l = strlen(*dst) + 1;
88 (*dst) += l;
89 (*n) -= l;
90 return l;
93 static int CopyAndAdvance(char** dst, char* src, int* n)
95 int l;
96 if (!src || !dst || !n || !(*dst)) return(0);
97 StrnCpy(*dst,src,*n-1);
98 l = strlen(*dst) + 1;
99 (*dst) += l;
100 (*n) -= l;
101 return l;
104 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
106 pstring buf;
107 if (!s) return(0);
108 StrnCpy(buf,s,sizeof(buf)/2);
109 pstring_sub(buf,"%S",lp_servicename(snum));
110 standard_sub(conn,buf);
111 return strlen(buf) + 1;
114 static char* Expand(connection_struct *conn, int snum, char* s)
116 static pstring buf;
117 if (!s) return(NULL);
118 StrnCpy(buf,s,sizeof(buf)/2);
119 pstring_sub(buf,"%S",lp_servicename(snum));
120 standard_sub(conn,buf);
121 return &buf[0];
124 /*******************************************************************
125 check a API string for validity when we only need to check the prefix
126 ******************************************************************/
127 static BOOL prefix_ok(char *str,char *prefix)
129 return(strncmp(str,prefix,strlen(prefix)) == 0);
132 /*******************************************************************
133 copies parameters and data, as needed, into the smb buffer
135 *both* the data and params sections should be aligned. this
136 is fudged in the rpc pipes by
137 at present, only the data section is. this may be a possible
138 cause of some of the ipc problems being experienced. lkcl26dec97
140 ******************************************************************/
142 static void copy_trans_params_and_data(char *outbuf, int align,
143 char *rparam, int param_offset, int param_len,
144 char *rdata, int data_offset, int data_len)
146 char *copy_into = smb_buf(outbuf)+1;
148 if(param_len < 0)
149 param_len = 0;
151 if(data_len < 0)
152 data_len = 0;
154 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
155 param_offset, param_offset + param_len,
156 data_offset , data_offset + data_len));
158 if (param_len)
159 memcpy(copy_into, &rparam[param_offset], param_len);
161 copy_into += param_len + align;
163 if (data_len )
164 memcpy(copy_into, &rdata[data_offset], data_len);
167 /****************************************************************************
168 Send a trans reply.
169 ****************************************************************************/
171 static void send_trans_reply(char *outbuf,
172 char *rparam, int rparam_len,
173 char *rdata, int rdata_len,
174 BOOL buffer_too_large)
176 int this_ldata,this_lparam;
177 int tot_data_sent = 0;
178 int tot_param_sent = 0;
179 int align;
181 int ldata = rdata ? rdata_len : 0;
182 int lparam = rparam ? rparam_len : 0;
184 if (buffer_too_large)
185 DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
187 this_lparam = MIN(lparam,max_send - 500); /* hack */
188 this_ldata = MIN(ldata,max_send - (500+this_lparam));
190 align = ((this_lparam)%4);
192 set_message(outbuf,10,1+align+this_ldata+this_lparam,True);
194 if (buffer_too_large)
196 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
197 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
198 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
201 copy_trans_params_and_data(outbuf, align,
202 rparam, tot_param_sent, this_lparam,
203 rdata, tot_data_sent, this_ldata);
205 SSVAL(outbuf,smb_vwv0,lparam);
206 SSVAL(outbuf,smb_vwv1,ldata);
207 SSVAL(outbuf,smb_vwv3,this_lparam);
208 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
209 SSVAL(outbuf,smb_vwv5,0);
210 SSVAL(outbuf,smb_vwv6,this_ldata);
211 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
212 SSVAL(outbuf,smb_vwv8,0);
213 SSVAL(outbuf,smb_vwv9,0);
215 show_msg(outbuf);
216 send_smb(Client,outbuf);
218 tot_data_sent = this_ldata;
219 tot_param_sent = this_lparam;
221 while (tot_data_sent < ldata || tot_param_sent < lparam)
223 this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */
224 this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam));
226 if(this_lparam < 0)
227 this_lparam = 0;
229 if(this_ldata < 0)
230 this_ldata = 0;
232 align = (this_lparam%4);
234 set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
236 copy_trans_params_and_data(outbuf, align,
237 rparam, tot_param_sent, this_lparam,
238 rdata, tot_data_sent, this_ldata);
240 SSVAL(outbuf,smb_vwv3,this_lparam);
241 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
242 SSVAL(outbuf,smb_vwv5,tot_param_sent);
243 SSVAL(outbuf,smb_vwv6,this_ldata);
244 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
245 SSVAL(outbuf,smb_vwv8,tot_data_sent);
246 SSVAL(outbuf,smb_vwv9,0);
248 show_msg(outbuf);
249 send_smb(Client,outbuf);
251 tot_data_sent += this_ldata;
252 tot_param_sent += this_lparam;
256 struct pack_desc {
257 char* format; /* formatstring for structure */
258 char* subformat; /* subformat for structure */
259 char* base; /* baseaddress of buffer */
260 int buflen; /* remaining size for fixed part; on init: length of base */
261 int subcount; /* count of substructures */
262 char* structbuf; /* pointer into buffer for remaining fixed part */
263 int stringlen; /* remaining size for variable part */
264 char* stringbuf; /* pointer into buffer for remaining variable part */
265 int neededlen; /* total needed size */
266 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
267 char* curpos; /* current position; pointer into format or subformat */
268 int errcode;
271 static int get_counter(char** p)
273 int i, n;
274 if (!p || !(*p)) return(1);
275 if (!isdigit((int)**p)) return 1;
276 for (n = 0;;) {
277 i = **p;
278 if (isdigit(i))
279 n = 10 * n + (i - '0');
280 else
281 return n;
282 (*p)++;
286 static int getlen(char* p)
288 int n = 0;
289 if (!p) return(0);
290 while (*p) {
291 switch( *p++ ) {
292 case 'W': /* word (2 byte) */
293 n += 2;
294 break;
295 case 'N': /* count of substructures (word) at end */
296 n += 2;
297 break;
298 case 'D': /* double word (4 byte) */
299 case 'z': /* offset to zero terminated string (4 byte) */
300 case 'l': /* offset to user data (4 byte) */
301 n += 4;
302 break;
303 case 'b': /* offset to data (with counter) (4 byte) */
304 n += 4;
305 get_counter(&p);
306 break;
307 case 'B': /* byte (with optional counter) */
308 n += get_counter(&p);
309 break;
312 return n;
315 static BOOL init_package(struct pack_desc* p, int count, int subcount)
317 int n = p->buflen;
318 int i;
320 if (!p->format || !p->base) return(False);
322 i = count * getlen(p->format);
323 if (p->subformat) i += subcount * getlen(p->subformat);
324 p->structbuf = p->base;
325 p->neededlen = 0;
326 p->usedlen = 0;
327 p->subcount = 0;
328 p->curpos = p->format;
329 if (i > n) {
330 p->neededlen = i;
331 i = n = 0;
332 p->errcode = ERRmoredata;
334 else
335 p->errcode = NERR_Success;
336 p->buflen = i;
337 n -= i;
338 p->stringbuf = p->base + i;
339 p->stringlen = n;
340 return(p->errcode == NERR_Success);
343 #ifdef HAVE_STDARG_H
344 static int package(struct pack_desc* p, ...)
346 #else
347 static int package(va_alist)
348 va_dcl
350 struct pack_desc* p;
351 #endif
352 va_list args;
353 int needed=0, stringneeded;
354 char* str=NULL;
355 int is_string=0, stringused;
356 int32 temp;
358 #ifdef HAVE_STDARG_H
359 va_start(args,p);
360 #else
361 va_start(args);
362 p = va_arg(args,struct pack_desc *);
363 #endif
365 if (!*p->curpos) {
366 if (!p->subcount)
367 p->curpos = p->format;
368 else {
369 p->curpos = p->subformat;
370 p->subcount--;
373 #if CHECK_TYPES
374 str = va_arg(args,char*);
375 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
376 #endif
377 stringneeded = -1;
379 if (!p->curpos) {
380 va_end(args);
381 return(0);
384 switch( *p->curpos++ ) {
385 case 'W': /* word (2 byte) */
386 needed = 2;
387 temp = va_arg(args,int);
388 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
389 break;
390 case 'N': /* count of substructures (word) at end */
391 needed = 2;
392 p->subcount = va_arg(args,int);
393 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
394 break;
395 case 'D': /* double word (4 byte) */
396 needed = 4;
397 temp = va_arg(args,int);
398 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
399 break;
400 case 'B': /* byte (with optional counter) */
401 needed = get_counter(&p->curpos);
403 char *s = va_arg(args,char*);
404 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
406 break;
407 case 'z': /* offset to zero terminated string (4 byte) */
408 str = va_arg(args,char*);
409 stringneeded = (str ? strlen(str)+1 : 0);
410 is_string = 1;
411 break;
412 case 'l': /* offset to user data (4 byte) */
413 str = va_arg(args,char*);
414 stringneeded = va_arg(args,int);
415 is_string = 0;
416 break;
417 case 'b': /* offset to data (with counter) (4 byte) */
418 str = va_arg(args,char*);
419 stringneeded = get_counter(&p->curpos);
420 is_string = 0;
421 break;
423 va_end(args);
424 if (stringneeded >= 0) {
425 needed = 4;
426 if (p->buflen >= needed) {
427 stringused = stringneeded;
428 if (stringused > p->stringlen) {
429 stringused = (is_string ? p->stringlen : 0);
430 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
432 if (!stringused)
433 SIVAL(p->structbuf,0,0);
434 else {
435 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
436 memcpy(p->stringbuf,str?str:"",stringused);
437 if (is_string) p->stringbuf[stringused-1] = '\0';
438 p->stringbuf += stringused;
439 p->stringlen -= stringused;
440 p->usedlen += stringused;
443 p->neededlen += stringneeded;
445 p->neededlen += needed;
446 if (p->buflen >= needed) {
447 p->structbuf += needed;
448 p->buflen -= needed;
449 p->usedlen += needed;
451 else {
452 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
454 return 1;
457 #if CHECK_TYPES
458 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
459 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
460 #else
461 #define PACK(desc,t,v) package(desc,v)
462 #define PACKl(desc,t,v,l) package(desc,v,l)
463 #endif
465 static void PACKI(struct pack_desc* desc,char *t,int v)
467 PACK(desc,t,v);
470 static void PACKS(struct pack_desc* desc,char *t,char *v)
472 PACK(desc,t,v);
475 #ifdef PRINTING
476 /****************************************************************************
477 get a print queue
478 ****************************************************************************/
480 static void PackDriverData(struct pack_desc* desc)
482 char drivdata[4+4+32];
483 SIVAL(drivdata,0,sizeof drivdata); /* cb */
484 SIVAL(drivdata,4,1000); /* lVersion */
485 memset(drivdata+8,0,32); /* szDeviceName */
486 pstrcpy(drivdata+8,"NULL");
487 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
490 static int check_printq_info(struct pack_desc* desc,
491 int uLevel, char *id1, char *id2)
493 desc->subformat = NULL;
494 switch( uLevel ) {
495 case 0:
496 desc->format = "B13";
497 break;
498 case 1:
499 desc->format = "B13BWWWzzzzzWW";
500 break;
501 case 2:
502 desc->format = "B13BWWWzzzzzWN";
503 desc->subformat = "WB21BB16B10zWWzDDz";
504 break;
505 case 3:
506 desc->format = "zWWWWzzzzWWzzl";
507 break;
508 case 4:
509 desc->format = "zWWWWzzzzWNzzl";
510 desc->subformat = "WWzWWDDzz";
511 break;
512 case 5:
513 desc->format = "z";
514 break;
515 case 52:
516 desc->format = "WzzzzzzzzN";
517 desc->subformat = "z";
518 break;
519 default: return False;
521 if (strcmp(desc->format,id1) != 0) return False;
522 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
523 return True;
526 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
527 struct pack_desc* desc,
528 print_queue_struct* queue, int n)
530 time_t t = queue->time;
532 /* the client expects localtime */
533 t -= TimeDiff(t);
535 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
536 if (uLevel == 1) {
537 PACKS(desc,"B21",queue->user); /* szUserName */
538 PACKS(desc,"B",""); /* pad */
539 PACKS(desc,"B16",""); /* szNotifyName */
540 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
541 PACKS(desc,"z",""); /* pszParms */
542 PACKI(desc,"W",n+1); /* uPosition */
543 PACKI(desc,"W",queue->status); /* fsStatus */
544 PACKS(desc,"z",""); /* pszStatus */
545 PACKI(desc,"D",t); /* ulSubmitted */
546 PACKI(desc,"D",queue->size); /* ulSize */
547 PACKS(desc,"z",queue->file); /* pszComment */
549 if (uLevel == 2 || uLevel == 3) {
550 PACKI(desc,"W",queue->priority); /* uPriority */
551 PACKS(desc,"z",queue->user); /* pszUserName */
552 PACKI(desc,"W",n+1); /* uPosition */
553 PACKI(desc,"W",queue->status); /* fsStatus */
554 PACKI(desc,"D",t); /* ulSubmitted */
555 PACKI(desc,"D",queue->size); /* ulSize */
556 PACKS(desc,"z","Samba"); /* pszComment */
557 PACKS(desc,"z",queue->file); /* pszDocument */
558 if (uLevel == 3) {
559 PACKS(desc,"z",""); /* pszNotifyName */
560 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
561 PACKS(desc,"z",""); /* pszParms */
562 PACKS(desc,"z",""); /* pszStatus */
563 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
564 PACKS(desc,"z","lpd"); /* pszQProcName */
565 PACKS(desc,"z",""); /* pszQProcParms */
566 PACKS(desc,"z","NULL"); /* pszDriverName */
567 PackDriverData(desc); /* pDriverData */
568 PACKS(desc,"z",""); /* pszPrinterName */
573 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
574 struct pack_desc* desc,
575 int count, print_queue_struct* queue,
576 print_status_struct* status)
578 switch (uLevel) {
579 case 1:
580 case 2:
581 PACKS(desc,"B13",SERVICE(snum));
582 break;
583 case 3:
584 case 4:
585 case 5:
586 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
587 break;
590 if (uLevel == 1 || uLevel == 2) {
591 PACKS(desc,"B",""); /* alignment */
592 PACKI(desc,"W",5); /* priority */
593 PACKI(desc,"W",0); /* start time */
594 PACKI(desc,"W",0); /* until time */
595 PACKS(desc,"z",""); /* pSepFile */
596 PACKS(desc,"z","lpd"); /* pPrProc */
597 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
598 PACKS(desc,"z",""); /* pParms */
599 if (snum < 0) {
600 PACKS(desc,"z","UNKNOWN PRINTER");
601 PACKI(desc,"W",LPSTAT_ERROR);
603 else if (!status || !status->message[0]) {
604 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
605 PACKI(desc,"W",LPSTAT_OK); /* status */
606 } else {
607 PACKS(desc,"z",status->message);
608 PACKI(desc,"W",status->status); /* status */
610 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
612 if (uLevel == 3 || uLevel == 4) {
613 PACKI(desc,"W",5); /* uPriority */
614 PACKI(desc,"W",0); /* uStarttime */
615 PACKI(desc,"W",0); /* uUntiltime */
616 PACKI(desc,"W",5); /* pad1 */
617 PACKS(desc,"z",""); /* pszSepFile */
618 PACKS(desc,"z","WinPrint"); /* pszPrProc */
619 PACKS(desc,"z",""); /* pszParms */
620 if (!status || !status->message[0]) {
621 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
622 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
623 } else {
624 PACKS(desc,"z",status->message); /* pszComment */
625 PACKI(desc,"W",status->status); /* fsStatus */
627 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
628 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
629 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
630 PackDriverData(desc); /* pDriverData */
632 if (uLevel == 2 || uLevel == 4) {
633 int i;
634 for (i=0;i<count;i++)
635 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
638 if (uLevel==52) {
639 int i,ok=0;
640 pstring tok,driver,datafile,langmon,helpfile,datatype;
641 char *p,*q;
642 FILE *f;
643 pstring fname;
645 pstrcpy(fname,lp_driverfile());
646 f=sys_fopen(fname,"r");
647 if (!f) {
648 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
649 desc->errcode=NERR_notsupported;
650 return;
653 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
654 DEBUG(0,("fill_printq_info: malloc fail !\n"));
655 desc->errcode=NERR_notsupported;
656 fclose(f);
657 return;
660 memset(p, '\0',8192*sizeof(char));
661 q=p;
663 /* lookup the long printer driver name in the file description */
664 while (f && !feof(f) && !ok)
666 p = q; /* reset string pointer */
667 fgets(p,8191,f);
668 p[strlen(p)-1]='\0';
669 if (next_token(&p,tok,":",sizeof(tok)) &&
670 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
671 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
672 ok=1;
674 fclose(f);
676 /* driver file name */
677 if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
678 /* data file name */
679 if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
681 * for the next tokens - which may be empty - I have to check for empty
682 * tokens first because the next_token function will skip all empty
683 * token fields
685 if (ok) {
686 /* help file */
687 if (*p == ':') {
688 *helpfile = '\0';
689 p++;
690 } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
693 if (ok) {
694 /* language monitor */
695 if (*p == ':') {
696 *langmon = '\0';
697 p++;
698 } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0;
701 /* default data type */
702 if (ok && !next_token(&p,datatype,":",sizeof(datatype))) ok = 0;
704 if (ok) {
705 PACKI(desc,"W",0x0400); /* don't know */
706 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
707 PACKS(desc,"z",driver); /* Driverfile Name */
708 PACKS(desc,"z",datafile); /* Datafile name */
709 PACKS(desc,"z",langmon); /* language monitor */
710 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
711 PACKS(desc,"z",datatype); /* default data type */
712 PACKS(desc,"z",helpfile); /* helpfile name */
713 PACKS(desc,"z",driver); /* driver name */
714 DEBUG(3,("Driver:%s:\n",driver));
715 DEBUG(3,("Data File:%s:\n",datafile));
716 DEBUG(3,("Language Monitor:%s:\n",langmon));
717 DEBUG(3,("Data Type:%s:\n",datatype));
718 DEBUG(3,("Help File:%s:\n",helpfile));
719 PACKI(desc,"N",count); /* number of files to copy */
720 for (i=0;i<count;i++)
722 /* no need to check return value here - it was already tested in
723 * get_printerdrivernumber
725 next_token(&p,tok,",",sizeof(tok));
726 PACKS(desc,"z",tok); /* driver files to copy */
727 DEBUG(3,("file:%s:\n",tok));
730 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
731 SERVICE(snum),count));
732 } else {
733 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
734 desc->errcode=NERR_notsupported;
736 free(q);
740 /* This function returns the number of files for a given driver */
741 static int get_printerdrivernumber(int snum)
743 int i=0,ok=0;
744 pstring tok;
745 char *p,*q;
746 FILE *f;
747 pstring fname;
749 pstrcpy(fname,lp_driverfile());
751 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
752 f=sys_fopen(fname,"r");
753 if (!f) {
754 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
755 return(0);
758 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
759 DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
760 fclose(f);
761 return 0;
764 q=p; /* need it to free memory because p change ! */
766 /* lookup the long printer driver name in the file description */
767 while (!feof(f) && !ok)
769 p = q; /* reset string pointer */
770 fgets(p,8191,f);
771 if (next_token(&p,tok,":",sizeof(tok)) &&
772 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
773 ok=1;
775 fclose(f);
777 if (ok) {
778 /* skip 5 fields */
779 i = 5;
780 while (*p && i) {
781 if (*p++ == ':') i--;
783 if (!*p || i)
784 return(0);
786 /* count the number of files */
787 while (next_token(&p,tok,",",sizeof(tok)))
788 i++;
790 free(q);
792 return(i);
795 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
796 uint16 vuid, char *param,char *data,
797 int mdrcnt,int mprcnt,
798 char **rdata,char **rparam,
799 int *rdata_len,int *rparam_len)
801 char *str1 = param+2;
802 char *str2 = skip_string(str1,1);
803 char *p = skip_string(str2,1);
804 char *QueueName = p;
805 int uLevel;
806 int count=0;
807 int snum;
808 char* str3;
809 struct pack_desc desc;
810 print_queue_struct *queue=NULL;
811 print_status_struct status;
813 memset((char *)&status,'\0',sizeof(status));
814 memset((char *)&desc,'\0',sizeof(desc));
816 p = skip_string(p,1);
817 uLevel = SVAL(p,0);
818 str3 = p + 4;
820 /* remove any trailing username */
821 if ((p = strchr(QueueName,'%'))) *p = 0;
823 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
825 /* check it's a supported varient */
826 if (!prefix_ok(str1,"zWrLh")) return False;
827 if (!check_printq_info(&desc,uLevel,str2,str3)) {
829 * Patch from Scott Moomaw <scott@bridgewater.edu>
830 * to return the 'invalid info level' error if an
831 * unknown level was requested.
833 *rdata_len = 0;
834 *rparam_len = 6;
835 *rparam = REALLOC(*rparam,*rparam_len);
836 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
837 SSVAL(*rparam,2,0);
838 SSVAL(*rparam,4,0);
839 return(True);
842 snum = lp_servicenumber(QueueName);
843 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
844 int pnum = lp_servicenumber(PRINTERS_NAME);
845 if (pnum >= 0) {
846 lp_add_printer(QueueName,pnum);
847 snum = lp_servicenumber(QueueName);
851 if (snum < 0 || !VALID_SNUM(snum)) return(False);
853 if (uLevel==52) {
854 count = get_printerdrivernumber(snum);
855 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
856 } else {
857 count = get_printqueue(snum, conn,&queue,&status);
860 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
861 desc.base = *rdata;
862 desc.buflen = mdrcnt;
863 if (init_package(&desc,1,count)) {
864 desc.subcount = count;
865 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
866 } else if(uLevel == 0) {
868 * This is a *disgusting* hack.
869 * This is *so* bad that even I'm embarrassed (and I
870 * have no shame). Here's the deal :
871 * Until we get the correct SPOOLSS code into smbd
872 * then when we're running with NT SMB support then
873 * NT makes this call with a level of zero, and then
874 * immediately follows it with an open request to
875 * the \\SRVSVC pipe. If we allow that open to
876 * succeed then NT barfs when it cannot open the
877 * \\SPOOLSS pipe immediately after and continually
878 * whines saying "Printer name is invalid" forever
879 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
880 * to fail, then NT downgrades to using the downlevel code
881 * and everything works as well as before. I hate
882 * myself for adding this code.... JRA.
885 fail_next_srvsvc_open();
888 *rdata_len = desc.usedlen;
890 *rparam_len = 6;
891 *rparam = REALLOC(*rparam,*rparam_len);
892 SSVALS(*rparam,0,desc.errcode);
893 SSVAL(*rparam,2,0);
894 SSVAL(*rparam,4,desc.neededlen);
896 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
898 if (queue) free(queue);
900 return(True);
904 /****************************************************************************
905 view list of all print jobs on all queues
906 ****************************************************************************/
907 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
908 int mdrcnt, int mprcnt,
909 char **rdata, char** rparam,
910 int *rdata_len, int *rparam_len)
912 char *param_format = param+2;
913 char *output_format1 = skip_string(param_format,1);
914 char *p = skip_string(output_format1,1);
915 int uLevel = SVAL(p,0);
916 char *output_format2 = p + 4;
917 int services = lp_numservices();
918 int i, n;
919 struct pack_desc desc;
920 print_queue_struct **queue = NULL;
921 print_status_struct *status = NULL;
922 int* subcntarr = NULL;
923 int queuecnt, subcnt=0, succnt=0;
925 memset((char *)&desc,'\0',sizeof(desc));
927 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
929 if (!prefix_ok(param_format,"WrLeh")) return False;
930 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
932 * Patch from Scott Moomaw <scott@bridgewater.edu>
933 * to return the 'invalid info level' error if an
934 * unknown level was requested.
936 *rdata_len = 0;
937 *rparam_len = 6;
938 *rparam = REALLOC(*rparam,*rparam_len);
939 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
940 SSVAL(*rparam,2,0);
941 SSVAL(*rparam,4,0);
942 return(True);
945 queuecnt = 0;
946 for (i = 0; i < services; i++)
947 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
948 queuecnt++;
949 if (uLevel > 0) {
950 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
951 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
952 return False;
954 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
955 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
956 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
957 return False;
959 memset(status,0,queuecnt*sizeof(print_status_struct));
960 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
961 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
962 return False;
964 subcnt = 0;
965 n = 0;
966 for (i = 0; i < services; i++)
967 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
968 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
969 subcnt += subcntarr[n];
970 n++;
973 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
974 desc.base = *rdata;
975 desc.buflen = mdrcnt;
977 if (init_package(&desc,queuecnt,subcnt)) {
978 n = 0;
979 succnt = 0;
980 for (i = 0; i < services; i++)
981 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
982 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
983 n++;
984 if (desc.errcode == NERR_Success) succnt = n;
988 if (subcntarr) free(subcntarr);
990 *rdata_len = desc.usedlen;
991 *rparam_len = 8;
992 *rparam = REALLOC(*rparam,*rparam_len);
993 SSVALS(*rparam,0,desc.errcode);
994 SSVAL(*rparam,2,0);
995 SSVAL(*rparam,4,succnt);
996 SSVAL(*rparam,6,queuecnt);
998 for (i = 0; i < queuecnt; i++) {
999 if (queue && queue[i]) free(queue[i]);
1002 if (queue) free(queue);
1003 if (status) free(status);
1005 return True;
1007 #endif
1008 /****************************************************************************
1009 get info level for a server list query
1010 ****************************************************************************/
1011 static BOOL check_server_info(int uLevel, char* id)
1013 switch( uLevel ) {
1014 case 0:
1015 if (strcmp(id,"B16") != 0) return False;
1016 break;
1017 case 1:
1018 if (strcmp(id,"B16BBDz") != 0) return False;
1019 break;
1020 default:
1021 return False;
1023 return True;
1026 struct srv_info_struct
1028 fstring name;
1029 uint32 type;
1030 fstring comment;
1031 fstring domain;
1032 BOOL server_added;
1036 /*******************************************************************
1037 get server info lists from the files saved by nmbd. Return the
1038 number of entries
1039 ******************************************************************/
1040 static int get_server_info(uint32 servertype,
1041 struct srv_info_struct **servers,
1042 char *domain)
1044 FILE *f;
1045 pstring fname;
1046 int count=0;
1047 int alloced=0;
1048 pstring line;
1049 BOOL local_list_only;
1051 pstrcpy(fname,lp_lockdir());
1052 trim_string(fname,NULL,"/");
1053 pstrcat(fname,"/");
1054 pstrcat(fname,SERVER_LIST);
1056 f = sys_fopen(fname,"r");
1058 if (!f) {
1059 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1060 return(0);
1063 /* request for everything is code for request all servers */
1064 if (servertype == SV_TYPE_ALL)
1065 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1067 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1069 DEBUG(4,("Servertype search: %8x\n",servertype));
1071 while (!feof(f))
1073 fstring stype;
1074 struct srv_info_struct *s;
1075 char *ptr = line;
1076 BOOL ok = True;
1077 *ptr = 0;
1079 fgets(line,sizeof(line)-1,f);
1080 if (!*line) continue;
1082 if (count == alloced) {
1083 alloced += 10;
1084 (*servers) = (struct srv_info_struct *)
1085 Realloc(*servers,sizeof(**servers)*alloced);
1086 if (!(*servers)) return(0);
1087 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1089 s = &(*servers)[count];
1091 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1092 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1093 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1094 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1095 /* this allows us to cope with an old nmbd */
1096 pstrcpy(s->domain,global_myworkgroup);
1099 if (sscanf(stype,"%X",&s->type) != 1) {
1100 DEBUG(4,("r:host file "));
1101 ok = False;
1104 /* Filter the servers/domains we return based on what was asked for. */
1106 /* Check to see if we are being asked for a local list only. */
1107 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1108 DEBUG(4,("r: local list only"));
1109 ok = False;
1112 /* doesn't match up: don't want it */
1113 if (!(servertype & s->type)) {
1114 DEBUG(4,("r:serv type "));
1115 ok = False;
1118 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1119 (s->type & SV_TYPE_DOMAIN_ENUM))
1121 DEBUG(4,("s: dom mismatch "));
1122 ok = False;
1125 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1127 ok = False;
1130 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1131 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1133 if (ok)
1135 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1136 s->name, s->type, s->comment, s->domain));
1138 s->server_added = True;
1139 count++;
1141 else
1143 DEBUG(4,("%20s %8x %25s %15s\n",
1144 s->name, s->type, s->comment, s->domain));
1148 fclose(f);
1149 return(count);
1153 /*******************************************************************
1154 fill in a server info structure
1155 ******************************************************************/
1156 static int fill_srv_info(struct srv_info_struct *service,
1157 int uLevel, char **buf, int *buflen,
1158 char **stringbuf, int *stringspace, char *baseaddr)
1160 int struct_len;
1161 char* p;
1162 char* p2;
1163 int l2;
1164 int len;
1166 switch (uLevel) {
1167 case 0: struct_len = 16; break;
1168 case 1: struct_len = 26; break;
1169 default: return -1;
1172 if (!buf)
1174 len = 0;
1175 switch (uLevel)
1177 case 1:
1178 len = strlen(service->comment)+1;
1179 break;
1182 if (buflen) *buflen = struct_len;
1183 if (stringspace) *stringspace = len;
1184 return struct_len + len;
1187 len = struct_len;
1188 p = *buf;
1189 if (*buflen < struct_len) return -1;
1190 if (stringbuf)
1192 p2 = *stringbuf;
1193 l2 = *stringspace;
1195 else
1197 p2 = p + struct_len;
1198 l2 = *buflen - struct_len;
1200 if (!baseaddr) baseaddr = p;
1202 switch (uLevel)
1204 case 0:
1205 StrnCpy(p,service->name,15);
1206 break;
1208 case 1:
1209 StrnCpy(p,service->name,15);
1210 SIVAL(p,18,service->type);
1211 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1212 len += CopyAndAdvance(&p2,service->comment,&l2);
1213 break;
1216 if (stringbuf)
1218 *buf = p + struct_len;
1219 *buflen -= struct_len;
1220 *stringbuf = p2;
1221 *stringspace = l2;
1223 else
1225 *buf = p2;
1226 *buflen -= len;
1228 return len;
1232 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1234 return(strcmp(s1->name,s2->name));
1237 /****************************************************************************
1238 view list of servers available (or possibly domains). The info is
1239 extracted from lists saved by nmbd on the local host
1240 ****************************************************************************/
1241 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1242 int mdrcnt, int mprcnt, char **rdata,
1243 char **rparam, int *rdata_len, int *rparam_len)
1245 char *str1 = param+2;
1246 char *str2 = skip_string(str1,1);
1247 char *p = skip_string(str2,1);
1248 int uLevel = SVAL(p,0);
1249 int buf_len = SVAL(p,2);
1250 uint32 servertype = IVAL(p,4);
1251 char *p2;
1252 int data_len, fixed_len, string_len;
1253 int f_len = 0, s_len = 0;
1254 struct srv_info_struct *servers=NULL;
1255 int counted=0,total=0;
1256 int i,missed;
1257 fstring domain;
1258 BOOL domain_request;
1259 BOOL local_request;
1261 /* If someone sets all the bits they don't really mean to set
1262 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1263 known servers. */
1265 if (servertype == SV_TYPE_ALL)
1266 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1268 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1269 any other bit (they may just set this bit on it's own) they
1270 want all the locally seen servers. However this bit can be
1271 set on its own so set the requested servers to be
1272 ALL - DOMAIN_ENUM. */
1274 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1275 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1277 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1278 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1280 p += 8;
1282 if (!prefix_ok(str1,"WrLehD")) return False;
1283 if (!check_server_info(uLevel,str2)) return False;
1285 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1286 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1287 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1289 if (strcmp(str1, "WrLehDz") == 0) {
1290 StrnCpy(domain, p, sizeof(fstring)-1);
1291 } else {
1292 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1295 if (lp_browse_list())
1296 total = get_server_info(servertype,&servers,domain);
1298 data_len = fixed_len = string_len = 0;
1299 missed = 0;
1301 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1304 char *lastname=NULL;
1306 for (i=0;i<total;i++)
1308 struct srv_info_struct *s = &servers[i];
1309 if (lastname && strequal(lastname,s->name)) continue;
1310 lastname = s->name;
1311 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1312 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1313 s->name, s->type, s->comment, s->domain));
1315 if (data_len <= buf_len) {
1316 counted++;
1317 fixed_len += f_len;
1318 string_len += s_len;
1319 } else {
1320 missed++;
1325 *rdata_len = fixed_len + string_len;
1326 *rdata = REALLOC(*rdata,*rdata_len);
1327 memset(*rdata,'\0',*rdata_len);
1329 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1330 p = *rdata;
1331 f_len = fixed_len;
1332 s_len = string_len;
1335 char *lastname=NULL;
1336 int count2 = counted;
1337 for (i = 0; i < total && count2;i++)
1339 struct srv_info_struct *s = &servers[i];
1340 if (lastname && strequal(lastname,s->name)) continue;
1341 lastname = s->name;
1342 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1343 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1344 s->name, s->type, s->comment, s->domain));
1345 count2--;
1349 *rparam_len = 8;
1350 *rparam = REALLOC(*rparam,*rparam_len);
1351 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1352 SSVAL(*rparam,2,0);
1353 SSVAL(*rparam,4,counted);
1354 SSVAL(*rparam,6,counted+missed);
1356 if (servers) free(servers);
1358 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1359 domain,uLevel,counted,counted+missed));
1361 return(True);
1364 /****************************************************************************
1365 command 0x34 - suspected of being a "Lookup Names" stub api
1366 ****************************************************************************/
1367 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1368 int mdrcnt, int mprcnt, char **rdata,
1369 char **rparam, int *rdata_len, int *rparam_len)
1371 char *str1 = param+2;
1372 char *str2 = skip_string(str1,1);
1373 char *p = skip_string(str2,1);
1374 int uLevel = SVAL(p,0);
1375 int buf_len = SVAL(p,2);
1376 int counted=0;
1377 int missed=0;
1379 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1380 str1, str2, p, uLevel, buf_len));
1382 if (!prefix_ok(str1,"zWrLeh")) return False;
1384 *rdata_len = 0;
1386 *rparam_len = 8;
1387 *rparam = REALLOC(*rparam,*rparam_len);
1389 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1390 SSVAL(*rparam,2,0);
1391 SSVAL(*rparam,4,counted);
1392 SSVAL(*rparam,6,counted+missed);
1394 return(True);
1397 /****************************************************************************
1398 get info about a share
1399 ****************************************************************************/
1400 static BOOL check_share_info(int uLevel, char* id)
1402 switch( uLevel ) {
1403 case 0:
1404 if (strcmp(id,"B13") != 0) return False;
1405 break;
1406 case 1:
1407 if (strcmp(id,"B13BWz") != 0) return False;
1408 break;
1409 case 2:
1410 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1411 break;
1412 case 91:
1413 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1414 break;
1415 default: return False;
1417 return True;
1420 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1421 char** buf, int* buflen,
1422 char** stringbuf, int* stringspace, char* baseaddr)
1424 int struct_len;
1425 char* p;
1426 char* p2;
1427 int l2;
1428 int len;
1430 switch( uLevel ) {
1431 case 0: struct_len = 13; break;
1432 case 1: struct_len = 20; break;
1433 case 2: struct_len = 40; break;
1434 case 91: struct_len = 68; break;
1435 default: return -1;
1439 if (!buf)
1441 len = 0;
1442 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1443 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1444 if (buflen) *buflen = struct_len;
1445 if (stringspace) *stringspace = len;
1446 return struct_len + len;
1449 len = struct_len;
1450 p = *buf;
1451 if ((*buflen) < struct_len) return -1;
1452 if (stringbuf)
1454 p2 = *stringbuf;
1455 l2 = *stringspace;
1457 else
1459 p2 = p + struct_len;
1460 l2 = (*buflen) - struct_len;
1462 if (!baseaddr) baseaddr = p;
1464 StrnCpy(p,lp_servicename(snum),13);
1466 if (uLevel > 0)
1468 int type;
1469 CVAL(p,13) = 0;
1470 type = STYPE_DISKTREE;
1471 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1472 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1473 SSVAL(p,14,type); /* device type */
1474 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1475 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1478 if (uLevel > 1)
1480 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1481 SSVALS(p,22,-1); /* max uses */
1482 SSVAL(p,24,1); /* current uses */
1483 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1484 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1485 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1488 if (uLevel > 2)
1490 memset(p+40,0,SHPWLEN+2);
1491 SSVAL(p,50,0);
1492 SIVAL(p,52,0);
1493 SSVAL(p,56,0);
1494 SSVAL(p,58,0);
1495 SIVAL(p,60,0);
1496 SSVAL(p,64,0);
1497 SSVAL(p,66,0);
1500 if (stringbuf)
1502 (*buf) = p + struct_len;
1503 (*buflen) -= struct_len;
1504 (*stringbuf) = p2;
1505 (*stringspace) = l2;
1507 else
1509 (*buf) = p2;
1510 (*buflen) -= len;
1512 return len;
1515 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1516 int mdrcnt,int mprcnt,
1517 char **rdata,char **rparam,
1518 int *rdata_len,int *rparam_len)
1520 char *str1 = param+2;
1521 char *str2 = skip_string(str1,1);
1522 char *netname = skip_string(str2,1);
1523 char *p = skip_string(netname,1);
1524 int uLevel = SVAL(p,0);
1525 int snum = find_service(netname);
1527 if (snum < 0) return False;
1529 /* check it's a supported varient */
1530 if (!prefix_ok(str1,"zWrLh")) return False;
1531 if (!check_share_info(uLevel,str2)) return False;
1533 *rdata = REALLOC(*rdata,mdrcnt);
1534 p = *rdata;
1535 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1536 if (*rdata_len < 0) return False;
1538 *rparam_len = 6;
1539 *rparam = REALLOC(*rparam,*rparam_len);
1540 SSVAL(*rparam,0,NERR_Success);
1541 SSVAL(*rparam,2,0); /* converter word */
1542 SSVAL(*rparam,4,*rdata_len);
1544 return(True);
1547 /****************************************************************************
1548 view list of shares available
1549 ****************************************************************************/
1550 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1551 int mdrcnt,int mprcnt,
1552 char **rdata,char **rparam,
1553 int *rdata_len,int *rparam_len)
1555 char *str1 = param+2;
1556 char *str2 = skip_string(str1,1);
1557 char *p = skip_string(str2,1);
1558 int uLevel = SVAL(p,0);
1559 int buf_len = SVAL(p,2);
1560 char *p2;
1561 int count=lp_numservices();
1562 int total=0,counted=0;
1563 BOOL missed = False;
1564 int i;
1565 int data_len, fixed_len, string_len;
1566 int f_len = 0, s_len = 0;
1568 if (!prefix_ok(str1,"WrLeh")) return False;
1569 //!! if (!check_share_info(uLevel,str2)) return False;
1571 data_len = fixed_len = string_len = 0;
1572 for (i=0;i<count;i++)
1573 if (lp_browseable(i) && lp_snum_ok(i))
1575 total++;
1576 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1577 if (data_len <= buf_len)
1579 counted++;
1580 fixed_len += f_len;
1581 string_len += s_len;
1583 else
1584 missed = True;
1586 *rdata_len = fixed_len + string_len;
1587 *rdata = REALLOC(*rdata,*rdata_len);
1588 memset(*rdata,0,*rdata_len);
1590 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1591 p = *rdata;
1592 f_len = fixed_len;
1593 s_len = string_len;
1594 for (i = 0; i < count;i++)
1595 if (lp_browseable(i) && lp_snum_ok(i))
1596 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1597 break;
1599 *rparam_len = 8;
1600 *rparam = REALLOC(*rparam,*rparam_len);
1601 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1602 SSVAL(*rparam,2,0);
1603 SSVAL(*rparam,4,counted);
1604 SSVAL(*rparam,6,total);
1606 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1607 counted,total,uLevel,
1608 buf_len,*rdata_len,mdrcnt));
1609 return(True);
1614 /****************************************************************************
1615 get the time of day info
1616 ****************************************************************************/
1617 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1618 int mdrcnt,int mprcnt,
1619 char **rdata,char **rparam,
1620 int *rdata_len,int *rparam_len)
1622 char *p;
1623 *rparam_len = 4;
1624 *rparam = REALLOC(*rparam,*rparam_len);
1626 *rdata_len = 21;
1627 *rdata = REALLOC(*rdata,*rdata_len);
1629 SSVAL(*rparam,0,NERR_Success);
1630 SSVAL(*rparam,2,0); /* converter word */
1632 p = *rdata;
1635 struct tm *t;
1636 time_t unixdate = time(NULL);
1638 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1639 by NT in a "net time" operation,
1640 it seems to ignore the one below */
1642 /* the client expects to get localtime, not GMT, in this bit
1643 (I think, this needs testing) */
1644 t = LocalTime(&unixdate);
1646 SIVAL(p,4,0); /* msecs ? */
1647 CVAL(p,8) = t->tm_hour;
1648 CVAL(p,9) = t->tm_min;
1649 CVAL(p,10) = t->tm_sec;
1650 CVAL(p,11) = 0; /* hundredths of seconds */
1651 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1652 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1653 CVAL(p,16) = t->tm_mday;
1654 CVAL(p,17) = t->tm_mon + 1;
1655 SSVAL(p,18,1900+t->tm_year);
1656 CVAL(p,20) = t->tm_wday;
1660 return(True);
1663 /****************************************************************************
1664 Set the user password.
1665 *****************************************************************************/
1667 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1668 int mdrcnt,int mprcnt,
1669 char **rdata,char **rparam,
1670 int *rdata_len,int *rparam_len)
1672 char *p = skip_string(param+2,2);
1673 fstring user;
1674 fstring pass1,pass2;
1676 fstrcpy(user,p);
1678 p = skip_string(p,1);
1680 memset(pass1,'\0',sizeof(pass1));
1681 memset(pass2,'\0',sizeof(pass2));
1682 memcpy(pass1,p,16);
1683 memcpy(pass2,p+16,16);
1685 *rparam_len = 4;
1686 *rparam = REALLOC(*rparam,*rparam_len);
1688 *rdata_len = 0;
1690 SSVAL(*rparam,0,NERR_badpass);
1691 SSVAL(*rparam,2,0); /* converter word */
1693 DEBUG(3,("Set password for <%s>\n",user));
1696 * Pass the user through the NT -> unix user mapping
1697 * function.
1700 (void)map_username(user);
1703 * Do any UNIX username case mangling.
1705 (void)Get_Pwnam( user, True);
1708 * Attempt to verify the old password against smbpasswd entries
1709 * Win98 clients send old and new password in plaintext for this call.
1713 fstring saved_pass2;
1714 struct smb_passwd *smbpw = NULL;
1717 * Save the new password as change_oem_password overwrites it
1718 * with zeros.
1721 fstrcpy(saved_pass2, pass2);
1723 if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) &&
1724 change_oem_password(smbpw,pass2,False))
1726 SSVAL(*rparam,0,NERR_Success);
1729 * If unix password sync was requested, attempt to change
1730 * the /etc/passwd database also. Return failure if this cannot
1731 * be done.
1734 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1735 SSVAL(*rparam,0,NERR_badpass);
1740 * If the above failed, attempt the plaintext password change.
1741 * This tests against the /etc/passwd database only.
1744 if(SVAL(*rparam,0) != NERR_Success)
1746 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1747 chgpasswd(user,pass1,pass2,False))
1749 SSVAL(*rparam,0,NERR_Success);
1754 * If the plaintext change failed, attempt
1755 * the old encrypted method. NT will generate this
1756 * after trying the samr method. Note that this
1757 * method is done as a last resort as this
1758 * password change method loses the NT password hash
1759 * and cannot change the UNIX password as no plaintext
1760 * is received.
1763 if(SVAL(*rparam,0) != NERR_Success)
1765 struct smb_passwd *sampw = NULL;
1767 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1768 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1770 SSVAL(*rparam,0,NERR_Success);
1774 memset((char *)pass1,'\0',sizeof(fstring));
1775 memset((char *)pass2,'\0',sizeof(fstring));
1777 return(True);
1780 /****************************************************************************
1781 Set the user password (SamOEM version - gets plaintext).
1782 ****************************************************************************/
1784 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1785 int mdrcnt,int mprcnt,
1786 char **rdata,char **rparam,
1787 int *rdata_len,int *rparam_len)
1789 fstring user;
1790 char *p = param + 2;
1791 *rparam_len = 2;
1792 *rparam = REALLOC(*rparam,*rparam_len);
1794 *rdata_len = 0;
1796 SSVAL(*rparam,0,NERR_badpass);
1799 * Check the parameter definition is correct.
1801 if(!strequal(param + 2, "zsT")) {
1802 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1803 return False;
1805 p = skip_string(p, 1);
1807 if(!strequal(p, "B516B16")) {
1808 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1809 return False;
1811 p = skip_string(p,1);
1813 fstrcpy(user,p);
1814 p = skip_string(p,1);
1816 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1819 * Pass the user through the NT -> unix user mapping
1820 * function.
1823 (void)map_username(user);
1826 * Do any UNIX username case mangling.
1828 (void)Get_Pwnam( user, True);
1830 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1832 SSVAL(*rparam,0,NERR_Success);
1835 return(True);
1837 #ifdef PRINTING
1838 /****************************************************************************
1839 delete a print job
1840 Form: <W> <>
1841 ****************************************************************************/
1842 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1843 int mdrcnt,int mprcnt,
1844 char **rdata,char **rparam,
1845 int *rdata_len,int *rparam_len)
1847 int function = SVAL(param,0);
1848 char *str1 = param+2;
1849 char *str2 = skip_string(str1,1);
1850 char *p = skip_string(str2,1);
1851 int jobid, snum;
1852 int i, count;
1854 printjob_decode(SVAL(p,0), &snum, &jobid);
1856 /* check it's a supported varient */
1857 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1858 return(False);
1860 *rparam_len = 4;
1861 *rparam = REALLOC(*rparam,*rparam_len);
1863 *rdata_len = 0;
1865 SSVAL(*rparam,0,NERR_Success);
1867 if (snum >= 0 && VALID_SNUM(snum))
1869 print_queue_struct *queue=NULL;
1870 lpq_reset(snum);
1871 count = get_printqueue(snum,conn,&queue,NULL);
1873 for (i=0;i<count;i++)
1874 if ((queue[i].job&0xFF) == jobid)
1876 switch (function) {
1877 case 81: /* delete */
1878 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1879 del_printqueue(conn,snum,queue[i].job);
1880 break;
1881 case 82: /* pause */
1882 case 83: /* resume */
1883 DEBUG(3,("%s queue entry %d\n",
1884 (function==82?"pausing":"resuming"),queue[i].job));
1885 status_printjob(conn,snum,queue[i].job,
1886 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1887 break;
1889 break;
1892 if (i==count)
1893 SSVAL(*rparam,0,NERR_JobNotFound);
1895 if (queue) free(queue);
1898 SSVAL(*rparam,2,0); /* converter word */
1900 return(True);
1903 /****************************************************************************
1904 Purge a print queue - or pause or resume it.
1905 ****************************************************************************/
1906 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1907 int mdrcnt,int mprcnt,
1908 char **rdata,char **rparam,
1909 int *rdata_len,int *rparam_len)
1911 int function = SVAL(param,0);
1912 char *str1 = param+2;
1913 char *str2 = skip_string(str1,1);
1914 char *QueueName = skip_string(str2,1);
1915 int snum;
1917 /* check it's a supported varient */
1918 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1919 return(False);
1921 *rparam_len = 4;
1922 *rparam = REALLOC(*rparam,*rparam_len);
1924 *rdata_len = 0;
1926 SSVAL(*rparam,0,NERR_Success);
1927 SSVAL(*rparam,2,0); /* converter word */
1929 snum = lp_servicenumber(QueueName);
1930 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1931 int pnum = lp_servicenumber(PRINTERS_NAME);
1932 if (pnum >= 0) {
1933 lp_add_printer(QueueName,pnum);
1934 snum = lp_servicenumber(QueueName);
1938 if (snum >= 0 && VALID_SNUM(snum)) {
1939 lpq_reset(snum);
1941 switch (function) {
1942 case 74: /* Pause queue */
1943 case 75: /* Resume queue */
1944 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1945 DEBUG(3,("Print queue %s, queue=%s\n",
1946 (function==74?"pause":"resume"),QueueName));
1947 break;
1948 case 103: /* Purge */
1950 print_queue_struct *queue=NULL;
1951 int i, count;
1952 count = get_printqueue(snum,conn,&queue,NULL);
1953 for (i = 0; i < count; i++)
1954 del_printqueue(conn,snum,queue[i].job);
1956 if (queue) free(queue);
1957 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1958 break;
1963 return(True);
1967 /****************************************************************************
1968 set the property of a print job (undocumented?)
1969 ? function = 0xb -> set name of print job
1970 ? function = 0x6 -> move print job up/down
1971 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1972 or <WWsTP> <WB21BB16B10zWWzDDz>
1973 ****************************************************************************/
1974 static int check_printjob_info(struct pack_desc* desc,
1975 int uLevel, char* id)
1977 desc->subformat = NULL;
1978 switch( uLevel ) {
1979 case 0: desc->format = "W"; break;
1980 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1981 case 2: desc->format = "WWzWWDDzz"; break;
1982 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1983 default: return False;
1985 if (strcmp(desc->format,id) != 0) return False;
1986 return True;
1989 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1990 int mdrcnt,int mprcnt,
1991 char **rdata,char **rparam,
1992 int *rdata_len,int *rparam_len)
1994 struct pack_desc desc;
1995 char *str1 = param+2;
1996 char *str2 = skip_string(str1,1);
1997 char *p = skip_string(str2,1);
1998 int jobid, snum;
1999 int uLevel = SVAL(p,2);
2000 int function = SVAL(p,4); /* what is this ?? */
2001 int i;
2002 char *s = data;
2003 files_struct *fsp;
2005 printjob_decode(SVAL(p,0), &snum, &jobid);
2007 *rparam_len = 4;
2008 *rparam = REALLOC(*rparam,*rparam_len);
2010 *rdata_len = 0;
2012 /* check it's a supported varient */
2013 if ((strcmp(str1,"WWsTP")) ||
2014 (!check_printjob_info(&desc,uLevel,str2)))
2015 return(False);
2017 switch (function) {
2018 case 0x6: /* change job place in the queue,
2019 data gives the new place */
2020 if (snum >= 0 && VALID_SNUM(snum)) {
2021 print_queue_struct *queue=NULL;
2022 int count;
2024 lpq_reset(snum);
2025 count = get_printqueue(snum,conn,&queue,NULL);
2026 for (i=0;i<count;i++) /* find job */
2027 if ((queue[i].job&0xFF) == jobid) break;
2029 if (i==count) {
2030 desc.errcode=NERR_JobNotFound;
2031 if (queue) free(queue);
2032 } else {
2033 desc.errcode=NERR_Success;
2034 i++;
2035 #if 0
2037 int place= SVAL(data,0);
2038 /* we currently have no way of
2039 doing this. Can any unix do it? */
2040 if (i < place) /* move down */;
2041 else if (i > place ) /* move up */;
2043 #endif
2044 desc.errcode=NERR_notsupported; /* not yet
2045 supported */
2046 if (queue) free(queue);
2048 } else {
2049 desc.errcode=NERR_JobNotFound;
2051 break;
2053 case 0xb: /* change print job name, data gives the name */
2054 /* jobid, snum should be zero */
2055 if (isalpha((int)*s)) {
2056 pstring name;
2057 int l = 0;
2058 while (l<64 && *s) {
2059 if (issafe(*s)) name[l++] = *s;
2060 s++;
2062 name[l] = 0;
2064 DEBUG(3,("Setting print name to %s\n",name));
2066 fsp = file_find_print();
2068 if (fsp) {
2069 connection_struct *fconn = fsp->conn;
2070 unbecome_user();
2072 if (!become_user(fconn,vuid) ||
2073 !become_service(fconn,True))
2074 break;
2076 if (dos_rename(fsp->fsp_name,name) == 0) {
2077 string_set(&fsp->fsp_name,name);
2079 break;
2082 desc.errcode=NERR_Success;
2083 break;
2085 default: /* not implemented */
2086 return False;
2089 SSVALS(*rparam,0,desc.errcode);
2090 SSVAL(*rparam,2,0); /* converter word */
2092 return(True);
2094 #endif
2096 /****************************************************************************
2097 get info about the server
2098 ****************************************************************************/
2099 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2100 int mdrcnt,int mprcnt,
2101 char **rdata,char **rparam,
2102 int *rdata_len,int *rparam_len)
2104 char *str1 = param+2;
2105 char *str2 = skip_string(str1,1);
2106 char *p = skip_string(str2,1);
2107 int uLevel = SVAL(p,0);
2108 char *p2;
2109 int struct_len;
2111 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2113 /* check it's a supported varient */
2114 if (!prefix_ok(str1,"WrLh")) return False;
2115 switch( uLevel ) {
2116 case 0:
2117 if (strcmp(str2,"B16") != 0) return False;
2118 struct_len = 16;
2119 break;
2120 case 1:
2121 if (strcmp(str2,"B16BBDz") != 0) return False;
2122 struct_len = 26;
2123 break;
2124 case 2:
2125 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2126 != 0) return False;
2127 struct_len = 134;
2128 break;
2129 case 3:
2130 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2131 != 0) return False;
2132 struct_len = 144;
2133 break;
2134 case 20:
2135 if (strcmp(str2,"DN") != 0) return False;
2136 struct_len = 6;
2137 break;
2138 case 50:
2139 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2140 struct_len = 42;
2141 break;
2142 default: return False;
2145 *rdata_len = mdrcnt;
2146 *rdata = REALLOC(*rdata,*rdata_len);
2148 p = *rdata;
2149 p2 = p + struct_len;
2150 if (uLevel != 20) {
2151 StrnCpy(p,local_machine,16);
2152 strupper(p);
2154 p += 16;
2155 if (uLevel > 0)
2157 struct srv_info_struct *servers=NULL;
2158 int i,count;
2159 pstring comment;
2160 uint32 servertype= lp_default_server_announce();
2162 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2164 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2165 for (i=0;i<count;i++)
2166 if (strequal(servers[i].name,local_machine))
2168 servertype = servers[i].type;
2169 pstrcpy(comment,servers[i].comment);
2172 if (servers) free(servers);
2174 SCVAL(p,0,lp_major_announce_version());
2175 SCVAL(p,1,lp_minor_announce_version());
2176 SIVAL(p,2,servertype);
2178 if (mdrcnt == struct_len) {
2179 SIVAL(p,6,0);
2180 } else {
2181 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2182 standard_sub(conn,comment);
2183 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2184 p2 = skip_string(p2,1);
2187 if (uLevel > 1)
2189 return False; /* not yet implemented */
2192 *rdata_len = PTR_DIFF(p2,*rdata);
2194 *rparam_len = 6;
2195 *rparam = REALLOC(*rparam,*rparam_len);
2196 SSVAL(*rparam,0,NERR_Success);
2197 SSVAL(*rparam,2,0); /* converter word */
2198 SSVAL(*rparam,4,*rdata_len);
2200 return(True);
2204 /****************************************************************************
2205 get info about the server
2206 ****************************************************************************/
2207 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2208 int mdrcnt,int mprcnt,
2209 char **rdata,char **rparam,
2210 int *rdata_len,int *rparam_len)
2212 char *str1 = param+2;
2213 char *str2 = skip_string(str1,1);
2214 char *p = skip_string(str2,1);
2215 char *p2;
2216 extern pstring sesssetup_user;
2217 int level = SVAL(p,0);
2219 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2221 *rparam_len = 6;
2222 *rparam = REALLOC(*rparam,*rparam_len);
2224 /* check it's a supported varient */
2225 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2226 return(False);
2228 *rdata_len = mdrcnt + 1024;
2229 *rdata = REALLOC(*rdata,*rdata_len);
2231 SSVAL(*rparam,0,NERR_Success);
2232 SSVAL(*rparam,2,0); /* converter word */
2234 p = *rdata;
2235 p2 = p + 22;
2238 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2239 pstrcpy(p2,local_machine);
2240 strupper(p2);
2241 p2 = skip_string(p2,1);
2242 p += 4;
2244 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2245 pstrcpy(p2,sesssetup_user);
2246 p2 = skip_string(p2,1);
2247 p += 4;
2249 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2250 pstrcpy(p2,global_myworkgroup);
2251 strupper(p2);
2252 p2 = skip_string(p2,1);
2253 p += 4;
2255 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2256 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2257 p += 2;
2259 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2260 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2261 p2 = skip_string(p2,1);
2262 p += 4;
2264 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2265 pstrcpy(p2,"");
2266 p2 = skip_string(p2,1);
2267 p += 4;
2269 *rdata_len = PTR_DIFF(p2,*rdata);
2271 SSVAL(*rparam,4,*rdata_len);
2273 return(True);
2276 /****************************************************************************
2277 get info about a user
2279 struct user_info_11 {
2280 char usri11_name[21]; 0-20
2281 char usri11_pad; 21
2282 char *usri11_comment; 22-25
2283 char *usri11_usr_comment; 26-29
2284 unsigned short usri11_priv; 30-31
2285 unsigned long usri11_auth_flags; 32-35
2286 long usri11_password_age; 36-39
2287 char *usri11_homedir; 40-43
2288 char *usri11_parms; 44-47
2289 long usri11_last_logon; 48-51
2290 long usri11_last_logoff; 52-55
2291 unsigned short usri11_bad_pw_count; 56-57
2292 unsigned short usri11_num_logons; 58-59
2293 char *usri11_logon_server; 60-63
2294 unsigned short usri11_country_code; 64-65
2295 char *usri11_workstations; 66-69
2296 unsigned long usri11_max_storage; 70-73
2297 unsigned short usri11_units_per_week; 74-75
2298 unsigned char *usri11_logon_hours; 76-79
2299 unsigned short usri11_code_page; 80-81
2302 where:
2304 usri11_name specifies the user name for which information is retireved
2306 usri11_pad aligns the next data structure element to a word boundary
2308 usri11_comment is a null terminated ASCII comment
2310 usri11_user_comment is a null terminated ASCII comment about the user
2312 usri11_priv specifies the level of the privilege assigned to the user.
2313 The possible values are:
2315 Name Value Description
2316 USER_PRIV_GUEST 0 Guest privilege
2317 USER_PRIV_USER 1 User privilege
2318 USER_PRV_ADMIN 2 Administrator privilege
2320 usri11_auth_flags specifies the account operator privileges. The
2321 possible values are:
2323 Name Value Description
2324 AF_OP_PRINT 0 Print operator
2327 Leach, Naik [Page 28] \f
2330 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2333 AF_OP_COMM 1 Communications operator
2334 AF_OP_SERVER 2 Server operator
2335 AF_OP_ACCOUNTS 3 Accounts operator
2338 usri11_password_age specifies how many seconds have elapsed since the
2339 password was last changed.
2341 usri11_home_dir points to a null terminated ASCII string that contains
2342 the path name of the user's home directory.
2344 usri11_parms points to a null terminated ASCII string that is set
2345 aside for use by applications.
2347 usri11_last_logon specifies the time when the user last logged on.
2348 This value is stored as the number of seconds elapsed since
2349 00:00:00, January 1, 1970.
2351 usri11_last_logoff specifies the time when the user last logged off.
2352 This value is stored as the number of seconds elapsed since
2353 00:00:00, January 1, 1970. A value of 0 means the last logoff
2354 time is unknown.
2356 usri11_bad_pw_count specifies the number of incorrect passwords
2357 entered since the last successful logon.
2359 usri11_log1_num_logons specifies the number of times this user has
2360 logged on. A value of -1 means the number of logons is unknown.
2362 usri11_logon_server points to a null terminated ASCII string that
2363 contains the name of the server to which logon requests are sent.
2364 A null string indicates logon requests should be sent to the
2365 domain controller.
2367 usri11_country_code specifies the country code for the user's language
2368 of choice.
2370 usri11_workstations points to a null terminated ASCII string that
2371 contains the names of workstations the user may log on from.
2372 There may be up to 8 workstations, with the names separated by
2373 commas. A null strings indicates there are no restrictions.
2375 usri11_max_storage specifies the maximum amount of disk space the user
2376 can occupy. A value of 0xffffffff indicates there are no
2377 restrictions.
2379 usri11_units_per_week specifies the equal number of time units into
2380 which a week is divided. This value must be equal to 168.
2382 usri11_logon_hours points to a 21 byte (168 bits) string that
2383 specifies the time during which the user can log on. Each bit
2384 represents one unique hour in a week. The first bit (bit 0, word
2385 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2389 Leach, Naik [Page 29] \f
2392 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2395 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2396 are no restrictions.
2398 usri11_code_page specifies the code page for the user's language of
2399 choice
2401 All of the pointers in this data structure need to be treated
2402 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2403 to be ignored. The converter word returned in the parameters section
2404 needs to be subtracted from the lower 16 bits to calculate an offset
2405 into the return buffer where this ASCII string resides.
2407 There is no auxiliary data in the response.
2409 ****************************************************************************/
2411 #define usri11_name 0
2412 #define usri11_pad 21
2413 #define usri11_comment 22
2414 #define usri11_usr_comment 26
2415 #define usri11_full_name 30
2416 #define usri11_priv 34
2417 #define usri11_auth_flags 36
2418 #define usri11_password_age 40
2419 #define usri11_homedir 44
2420 #define usri11_parms 48
2421 #define usri11_last_logon 52
2422 #define usri11_last_logoff 56
2423 #define usri11_bad_pw_count 60
2424 #define usri11_num_logons 62
2425 #define usri11_logon_server 64
2426 #define usri11_country_code 68
2427 #define usri11_workstations 70
2428 #define usri11_max_storage 74
2429 #define usri11_units_per_week 78
2430 #define usri11_logon_hours 80
2431 #define usri11_code_page 84
2432 #define usri11_end 86
2434 #define USER_PRIV_GUEST 0
2435 #define USER_PRIV_USER 1
2436 #define USER_PRIV_ADMIN 2
2438 #define AF_OP_PRINT 0
2439 #define AF_OP_COMM 1
2440 #define AF_OP_SERVER 2
2441 #define AF_OP_ACCOUNTS 3
2444 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2445 int mdrcnt,int mprcnt,
2446 char **rdata,char **rparam,
2447 int *rdata_len,int *rparam_len)
2449 char *str1 = param+2;
2450 char *str2 = skip_string(str1,1);
2451 char *UserName = skip_string(str2,1);
2452 char *p = skip_string(UserName,1);
2453 int uLevel = SVAL(p,0);
2454 char *p2;
2456 /* get NIS home of a previously validated user - simeon */
2457 /* With share level security vuid will always be zero.
2458 Don't depend on vuser being non-null !!. JRA */
2459 user_struct *vuser = get_valid_user_struct(vuid);
2460 if(vuser != NULL)
2461 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
2463 *rparam_len = 6;
2464 *rparam = REALLOC(*rparam,*rparam_len);
2466 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2468 /* check it's a supported variant */
2469 if (strcmp(str1,"zWrLh") != 0) return False;
2470 switch( uLevel )
2472 case 0: p2 = "B21"; break;
2473 case 1: p2 = "B21BB16DWzzWz"; break;
2474 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2475 case 10: p2 = "B21Bzzz"; break;
2476 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2477 default: return False;
2480 if (strcmp(p2,str2) != 0) return False;
2482 *rdata_len = mdrcnt + 1024;
2483 *rdata = REALLOC(*rdata,*rdata_len);
2485 SSVAL(*rparam,0,NERR_Success);
2486 SSVAL(*rparam,2,0); /* converter word */
2488 p = *rdata;
2489 p2 = p + usri11_end;
2491 memset(p,0,21);
2492 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2494 if (uLevel > 0)
2496 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2497 *p2 = 0;
2499 if (uLevel >= 10)
2501 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2502 pstrcpy(p2,"Comment");
2503 p2 = skip_string(p2,1);
2505 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2506 pstrcpy(p2,"UserComment");
2507 p2 = skip_string(p2,1);
2509 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2510 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2511 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2512 p2 = skip_string(p2,1);
2515 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2517 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2518 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2519 SIVALS(p,usri11_password_age,-1); /* password age */
2520 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2521 pstrcpy(p2, lp_logon_home());
2522 p2 = skip_string(p2,1);
2523 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2524 pstrcpy(p2,"");
2525 p2 = skip_string(p2,1);
2526 SIVAL(p,usri11_last_logon,0); /* last logon */
2527 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2528 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2529 SSVALS(p,usri11_num_logons,-1); /* num logons */
2530 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2531 pstrcpy(p2,"\\\\*");
2532 p2 = skip_string(p2,1);
2533 SSVAL(p,usri11_country_code,0); /* country code */
2535 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2536 pstrcpy(p2,"");
2537 p2 = skip_string(p2,1);
2539 SIVALS(p,usri11_max_storage,-1); /* max storage */
2540 SSVAL(p,usri11_units_per_week,168); /* units per week */
2541 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2543 /* a simple way to get logon hours at all times. */
2544 memset(p2,0xff,21);
2545 SCVAL(p2,21,0); /* fix zero termination */
2546 p2 = skip_string(p2,1);
2548 SSVAL(p,usri11_code_page,0); /* code page */
2550 if (uLevel == 1 || uLevel == 2)
2552 memset(p+22,' ',16); /* password */
2553 SIVALS(p,38,-1); /* password age */
2554 SSVAL(p,42,
2555 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2556 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2557 pstrcpy(p2,lp_logon_home());
2558 p2 = skip_string(p2,1);
2559 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2560 *p2++ = 0;
2561 SSVAL(p,52,0); /* flags */
2562 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2563 pstrcpy(p2,lp_logon_script());
2564 standard_sub( conn, p2 );
2565 p2 = skip_string(p2,1);
2566 if (uLevel == 2)
2568 SIVAL(p,60,0); /* auth_flags */
2569 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2570 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2571 p2 = skip_string(p2,1);
2572 SIVAL(p,68,0); /* urs_comment */
2573 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2574 pstrcpy(p2,"");
2575 p2 = skip_string(p2,1);
2576 SIVAL(p,76,0); /* workstations */
2577 SIVAL(p,80,0); /* last_logon */
2578 SIVAL(p,84,0); /* last_logoff */
2579 SIVALS(p,88,-1); /* acct_expires */
2580 SIVALS(p,92,-1); /* max_storage */
2581 SSVAL(p,96,168); /* units_per_week */
2582 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2583 memset(p2,-1,21);
2584 p2 += 21;
2585 SSVALS(p,102,-1); /* bad_pw_count */
2586 SSVALS(p,104,-1); /* num_logons */
2587 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2588 pstrcpy(p2,"\\\\%L");
2589 standard_sub_basic(p2);
2590 p2 = skip_string(p2,1);
2591 SSVAL(p,110,49); /* country_code */
2592 SSVAL(p,112,860); /* code page */
2596 *rdata_len = PTR_DIFF(p2,*rdata);
2598 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2600 return(True);
2603 /*******************************************************************
2604 get groups that a user is a member of
2605 ******************************************************************/
2606 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2607 int mdrcnt,int mprcnt,
2608 char **rdata,char **rparam,
2609 int *rdata_len,int *rparam_len)
2611 char *str1 = param+2;
2612 char *str2 = skip_string(str1,1);
2613 char *UserName = skip_string(str2,1);
2614 char *p = skip_string(UserName,1);
2615 int uLevel = SVAL(p,0);
2616 char *p2;
2617 int count=0;
2619 *rparam_len = 8;
2620 *rparam = REALLOC(*rparam,*rparam_len);
2622 /* check it's a supported varient */
2623 if (strcmp(str1,"zWrLeh") != 0) return False;
2624 switch( uLevel ) {
2625 case 0: p2 = "B21"; break;
2626 default: return False;
2628 if (strcmp(p2,str2) != 0) return False;
2630 *rdata_len = mdrcnt + 1024;
2631 *rdata = REALLOC(*rdata,*rdata_len);
2633 SSVAL(*rparam,0,NERR_Success);
2634 SSVAL(*rparam,2,0); /* converter word */
2636 p = *rdata;
2638 /* XXXX we need a real SAM database some day */
2639 pstrcpy(p,"Users"); p += 21; count++;
2640 pstrcpy(p,"Domain Users"); p += 21; count++;
2641 pstrcpy(p,"Guests"); p += 21; count++;
2642 pstrcpy(p,"Domain Guests"); p += 21; count++;
2644 *rdata_len = PTR_DIFF(p,*rdata);
2646 SSVAL(*rparam,4,count); /* is this right?? */
2647 SSVAL(*rparam,6,count); /* is this right?? */
2649 return(True);
2653 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2654 int mdrcnt,int mprcnt,
2655 char **rdata,char **rparam,
2656 int *rdata_len,int *rparam_len)
2658 char *str1 = param+2;
2659 char *str2 = skip_string(str1,1);
2660 char *p = skip_string(str2,1);
2661 int uLevel;
2662 struct pack_desc desc;
2663 char* name;
2665 uLevel = SVAL(p,0);
2666 name = p + 2;
2668 memset((char *)&desc,'\0',sizeof(desc));
2670 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2672 /* check it's a supported varient */
2673 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2674 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2675 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2676 desc.base = *rdata;
2677 desc.buflen = mdrcnt;
2678 desc.subformat = NULL;
2679 desc.format = str2;
2681 if (init_package(&desc,1,0))
2683 PACKI(&desc,"W",0); /* code */
2684 PACKS(&desc,"B21",name); /* eff. name */
2685 PACKS(&desc,"B",""); /* pad */
2686 PACKI(&desc,"W",
2687 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2688 PACKI(&desc,"D",0); /* auth flags XXX */
2689 PACKI(&desc,"W",0); /* num logons */
2690 PACKI(&desc,"W",0); /* bad pw count */
2691 PACKI(&desc,"D",0); /* last logon */
2692 PACKI(&desc,"D",-1); /* last logoff */
2693 PACKI(&desc,"D",-1); /* logoff time */
2694 PACKI(&desc,"D",-1); /* kickoff time */
2695 PACKI(&desc,"D",0); /* password age */
2696 PACKI(&desc,"D",0); /* password can change */
2697 PACKI(&desc,"D",-1); /* password must change */
2699 fstring mypath;
2700 fstrcpy(mypath,"\\\\");
2701 fstrcat(mypath,local_machine);
2702 strupper(mypath);
2703 PACKS(&desc,"z",mypath); /* computer */
2705 PACKS(&desc,"z",global_myworkgroup);/* domain */
2707 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2708 /* made sure all macros are fully substituted and available */
2710 pstring logon_script;
2711 pstrcpy(logon_script,lp_logon_script());
2712 standard_sub( conn, logon_script );
2713 PACKS(&desc,"z", logon_script); /* script path */
2715 /* End of JHT mods */
2717 PACKI(&desc,"D",0x00000000); /* reserved */
2720 *rdata_len = desc.usedlen;
2721 *rparam_len = 6;
2722 *rparam = REALLOC(*rparam,*rparam_len);
2723 SSVALS(*rparam,0,desc.errcode);
2724 SSVAL(*rparam,2,0);
2725 SSVAL(*rparam,4,desc.neededlen);
2727 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2728 return(True);
2732 /****************************************************************************
2733 api_WAccessGetUserPerms
2734 ****************************************************************************/
2735 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2736 int mdrcnt,int mprcnt,
2737 char **rdata,char **rparam,
2738 int *rdata_len,int *rparam_len)
2740 char *str1 = param+2;
2741 char *str2 = skip_string(str1,1);
2742 char *user = skip_string(str2,1);
2743 char *resource = skip_string(user,1);
2745 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2747 /* check it's a supported varient */
2748 if (strcmp(str1,"zzh") != 0) return False;
2749 if (strcmp(str2,"") != 0) return False;
2751 *rparam_len = 6;
2752 *rparam = REALLOC(*rparam,*rparam_len);
2753 SSVALS(*rparam,0,0); /* errorcode */
2754 SSVAL(*rparam,2,0); /* converter word */
2755 SSVAL(*rparam,4,0x7f); /* permission flags */
2757 return(True);
2759 #ifdef PRINTING
2760 /****************************************************************************
2761 api_WPrintJobEnumerate
2762 ****************************************************************************/
2763 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2764 int mdrcnt,int mprcnt,
2765 char **rdata,char **rparam,
2766 int *rdata_len,int *rparam_len)
2768 char *str1 = param+2;
2769 char *str2 = skip_string(str1,1);
2770 char *p = skip_string(str2,1);
2771 int uLevel;
2772 int count;
2773 int i;
2774 int snum;
2775 int job;
2776 struct pack_desc desc;
2777 print_queue_struct *queue=NULL;
2778 print_status_struct status;
2780 uLevel = SVAL(p,2);
2782 memset((char *)&desc,'\0',sizeof(desc));
2783 memset((char *)&status,'\0',sizeof(status));
2785 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2787 /* check it's a supported varient */
2788 if (strcmp(str1,"WWrLh") != 0) return False;
2789 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2791 printjob_decode(SVAL(p,0), &snum, &job);
2793 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2795 count = get_printqueue(snum,conn,&queue,&status);
2796 for (i = 0; i < count; i++) {
2797 if ((queue[i].job & 0xFF) == job) break;
2799 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2800 desc.base = *rdata;
2801 desc.buflen = mdrcnt;
2803 if (init_package(&desc,1,0)) {
2804 if (i < count) {
2805 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2806 *rdata_len = desc.usedlen;
2808 else {
2809 desc.errcode = NERR_JobNotFound;
2810 *rdata_len = 0;
2814 *rparam_len = 6;
2815 *rparam = REALLOC(*rparam,*rparam_len);
2816 SSVALS(*rparam,0,desc.errcode);
2817 SSVAL(*rparam,2,0);
2818 SSVAL(*rparam,4,desc.neededlen);
2820 if (queue) free(queue);
2822 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2823 return(True);
2826 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2827 int mdrcnt,int mprcnt,
2828 char **rdata,char **rparam,
2829 int *rdata_len,int *rparam_len)
2831 char *str1 = param+2;
2832 char *str2 = skip_string(str1,1);
2833 char *p = skip_string(str2,1);
2834 char* name = p;
2835 int uLevel;
2836 int count;
2837 int i, succnt=0;
2838 int snum;
2839 struct pack_desc desc;
2840 print_queue_struct *queue=NULL;
2841 print_status_struct status;
2843 memset((char *)&desc,'\0',sizeof(desc));
2844 memset((char *)&status,'\0',sizeof(status));
2846 p = skip_string(p,1);
2847 uLevel = SVAL(p,0);
2849 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2851 /* check it's a supported varient */
2852 if (strcmp(str1,"zWrLeh") != 0) return False;
2853 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2854 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2856 snum = lp_servicenumber(name);
2857 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2858 int pnum = lp_servicenumber(PRINTERS_NAME);
2859 if (pnum >= 0) {
2860 lp_add_printer(name,pnum);
2861 snum = lp_servicenumber(name);
2865 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2867 count = get_printqueue(snum,conn,&queue,&status);
2868 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2869 desc.base = *rdata;
2870 desc.buflen = mdrcnt;
2872 if (init_package(&desc,count,0)) {
2873 succnt = 0;
2874 for (i = 0; i < count; i++) {
2875 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2876 if (desc.errcode == NERR_Success) succnt = i+1;
2880 *rdata_len = desc.usedlen;
2882 *rparam_len = 8;
2883 *rparam = REALLOC(*rparam,*rparam_len);
2884 SSVALS(*rparam,0,desc.errcode);
2885 SSVAL(*rparam,2,0);
2886 SSVAL(*rparam,4,succnt);
2887 SSVAL(*rparam,6,count);
2889 if (queue) free(queue);
2891 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2892 return(True);
2895 static int check_printdest_info(struct pack_desc* desc,
2896 int uLevel, char* id)
2898 desc->subformat = NULL;
2899 switch( uLevel ) {
2900 case 0: desc->format = "B9"; break;
2901 case 1: desc->format = "B9B21WWzW"; break;
2902 case 2: desc->format = "z"; break;
2903 case 3: desc->format = "zzzWWzzzWW"; break;
2904 default: return False;
2906 if (strcmp(desc->format,id) != 0) return False;
2907 return True;
2910 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2911 struct pack_desc* desc)
2913 char buf[100];
2914 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2915 buf[sizeof(buf)-1] = 0;
2916 strupper(buf);
2917 if (uLevel <= 1) {
2918 PACKS(desc,"B9",buf); /* szName */
2919 if (uLevel == 1) {
2920 PACKS(desc,"B21",""); /* szUserName */
2921 PACKI(desc,"W",0); /* uJobId */
2922 PACKI(desc,"W",0); /* fsStatus */
2923 PACKS(desc,"z",""); /* pszStatus */
2924 PACKI(desc,"W",0); /* time */
2927 if (uLevel == 2 || uLevel == 3) {
2928 PACKS(desc,"z",buf); /* pszPrinterName */
2929 if (uLevel == 3) {
2930 PACKS(desc,"z",""); /* pszUserName */
2931 PACKS(desc,"z",""); /* pszLogAddr */
2932 PACKI(desc,"W",0); /* uJobId */
2933 PACKI(desc,"W",0); /* fsStatus */
2934 PACKS(desc,"z",""); /* pszStatus */
2935 PACKS(desc,"z",""); /* pszComment */
2936 PACKS(desc,"z","NULL"); /* pszDrivers */
2937 PACKI(desc,"W",0); /* time */
2938 PACKI(desc,"W",0); /* pad1 */
2943 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2944 int mdrcnt,int mprcnt,
2945 char **rdata,char **rparam,
2946 int *rdata_len,int *rparam_len)
2948 char *str1 = param+2;
2949 char *str2 = skip_string(str1,1);
2950 char *p = skip_string(str2,1);
2951 char* PrinterName = p;
2952 int uLevel;
2953 struct pack_desc desc;
2954 int snum;
2956 memset((char *)&desc,'\0',sizeof(desc));
2958 p = skip_string(p,1);
2959 uLevel = SVAL(p,0);
2961 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2963 /* check it's a supported varient */
2964 if (strcmp(str1,"zWrLh") != 0) return False;
2965 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2967 snum = lp_servicenumber(PrinterName);
2968 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2969 int pnum = lp_servicenumber(PRINTERS_NAME);
2970 if (pnum >= 0) {
2971 lp_add_printer(PrinterName,pnum);
2972 snum = lp_servicenumber(PrinterName);
2976 if (snum < 0) {
2977 *rdata_len = 0;
2978 desc.errcode = NERR_DestNotFound;
2979 desc.neededlen = 0;
2981 else {
2982 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2983 desc.base = *rdata;
2984 desc.buflen = mdrcnt;
2985 if (init_package(&desc,1,0)) {
2986 fill_printdest_info(conn,snum,uLevel,&desc);
2988 *rdata_len = desc.usedlen;
2991 *rparam_len = 6;
2992 *rparam = REALLOC(*rparam,*rparam_len);
2993 SSVALS(*rparam,0,desc.errcode);
2994 SSVAL(*rparam,2,0);
2995 SSVAL(*rparam,4,desc.neededlen);
2997 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2998 return(True);
3001 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3002 int mdrcnt,int mprcnt,
3003 char **rdata,char **rparam,
3004 int *rdata_len,int *rparam_len)
3006 char *str1 = param+2;
3007 char *str2 = skip_string(str1,1);
3008 char *p = skip_string(str2,1);
3009 int uLevel;
3010 int queuecnt;
3011 int i, n, succnt=0;
3012 struct pack_desc desc;
3013 int services = lp_numservices();
3015 memset((char *)&desc,'\0',sizeof(desc));
3017 uLevel = SVAL(p,0);
3019 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3021 /* check it's a supported varient */
3022 if (strcmp(str1,"WrLeh") != 0) return False;
3023 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3025 queuecnt = 0;
3026 for (i = 0; i < services; i++)
3027 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3028 queuecnt++;
3030 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3031 desc.base = *rdata;
3032 desc.buflen = mdrcnt;
3033 if (init_package(&desc,queuecnt,0)) {
3034 succnt = 0;
3035 n = 0;
3036 for (i = 0; i < services; i++) {
3037 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3038 fill_printdest_info(conn,i,uLevel,&desc);
3039 n++;
3040 if (desc.errcode == NERR_Success) succnt = n;
3045 *rdata_len = desc.usedlen;
3047 *rparam_len = 8;
3048 *rparam = REALLOC(*rparam,*rparam_len);
3049 SSVALS(*rparam,0,desc.errcode);
3050 SSVAL(*rparam,2,0);
3051 SSVAL(*rparam,4,succnt);
3052 SSVAL(*rparam,6,queuecnt);
3054 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3055 return(True);
3058 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3059 int mdrcnt,int mprcnt,
3060 char **rdata,char **rparam,
3061 int *rdata_len,int *rparam_len)
3063 char *str1 = param+2;
3064 char *str2 = skip_string(str1,1);
3065 char *p = skip_string(str2,1);
3066 int uLevel;
3067 int succnt;
3068 struct pack_desc desc;
3070 memset((char *)&desc,'\0',sizeof(desc));
3072 uLevel = SVAL(p,0);
3074 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3076 /* check it's a supported varient */
3077 if (strcmp(str1,"WrLeh") != 0) return False;
3078 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3080 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3081 desc.base = *rdata;
3082 desc.buflen = mdrcnt;
3083 if (init_package(&desc,1,0)) {
3084 PACKS(&desc,"B41","NULL");
3087 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3089 *rdata_len = desc.usedlen;
3091 *rparam_len = 8;
3092 *rparam = REALLOC(*rparam,*rparam_len);
3093 SSVALS(*rparam,0,desc.errcode);
3094 SSVAL(*rparam,2,0);
3095 SSVAL(*rparam,4,succnt);
3096 SSVAL(*rparam,6,1);
3098 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3099 return(True);
3102 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3103 int mdrcnt,int mprcnt,
3104 char **rdata,char **rparam,
3105 int *rdata_len,int *rparam_len)
3107 char *str1 = param+2;
3108 char *str2 = skip_string(str1,1);
3109 char *p = skip_string(str2,1);
3110 int uLevel;
3111 int succnt;
3112 struct pack_desc desc;
3114 memset((char *)&desc,'\0',sizeof(desc));
3116 uLevel = SVAL(p,0);
3118 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3120 /* check it's a supported varient */
3121 if (strcmp(str1,"WrLeh") != 0) return False;
3122 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3124 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3125 desc.base = *rdata;
3126 desc.buflen = mdrcnt;
3127 desc.format = str2;
3128 if (init_package(&desc,1,0)) {
3129 PACKS(&desc,"B13","lpd");
3132 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3134 *rdata_len = desc.usedlen;
3136 *rparam_len = 8;
3137 *rparam = REALLOC(*rparam,*rparam_len);
3138 SSVALS(*rparam,0,desc.errcode);
3139 SSVAL(*rparam,2,0);
3140 SSVAL(*rparam,4,succnt);
3141 SSVAL(*rparam,6,1);
3143 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3144 return(True);
3147 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3148 int mdrcnt,int mprcnt,
3149 char **rdata,char **rparam,
3150 int *rdata_len,int *rparam_len)
3152 char *str1 = param+2;
3153 char *str2 = skip_string(str1,1);
3154 char *p = skip_string(str2,1);
3155 int uLevel;
3156 int succnt;
3157 struct pack_desc desc;
3159 memset((char *)&desc,'\0',sizeof(desc));
3161 uLevel = SVAL(p,0);
3163 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3165 /* check it's a supported varient */
3166 if (strcmp(str1,"WrLeh") != 0) return False;
3167 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3169 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3170 memset((char *)&desc,'\0',sizeof(desc));
3171 desc.base = *rdata;
3172 desc.buflen = mdrcnt;
3173 desc.format = str2;
3174 if (init_package(&desc,1,0)) {
3175 PACKS(&desc,"B13","lp0");
3178 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3180 *rdata_len = desc.usedlen;
3182 *rparam_len = 8;
3183 *rparam = REALLOC(*rparam,*rparam_len);
3184 SSVALS(*rparam,0,desc.errcode);
3185 SSVAL(*rparam,2,0);
3186 SSVAL(*rparam,4,succnt);
3187 SSVAL(*rparam,6,1);
3189 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3190 return(True);
3192 #endif
3193 /****************************************************************************
3194 Start the first part of an RPC reply which began with an SMBtrans request.
3195 ****************************************************************************/
3197 static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p)
3199 char *rdata = malloc(p->max_trans_reply);
3200 int data_len;
3202 if(rdata == NULL) {
3203 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
3204 return False;
3207 if((data_len = (int)read_from_pipe( p, rdata, (size_t)p->max_trans_reply)) < 0) {
3208 free(rdata);
3209 return False;
3212 send_trans_reply(outbuf, NULL, 0, rdata, data_len, p->out_data.current_pdu_len > data_len);
3214 free(rdata);
3215 return True;
3218 /****************************************************************************
3219 WaitNamedPipeHandleState
3220 ****************************************************************************/
3222 static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
3224 uint16 priority;
3226 if (!param || param_len < 2)
3227 return False;
3229 priority = SVAL(param,0);
3230 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
3232 if (wait_rpc_pipe_hnd_state(p, priority)) {
3233 /* now send the reply */
3234 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
3235 return True;
3237 return False;
3241 /****************************************************************************
3242 SetNamedPipeHandleState
3243 ****************************************************************************/
3245 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
3247 uint16 id;
3249 if (!param || param_len < 2)
3250 return False;
3252 id = SVAL(param,0);
3253 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
3255 if (set_rpc_pipe_hnd_state(p, id)) {
3256 /* now send the reply */
3257 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
3258 return True;
3260 return False;
3264 /****************************************************************************
3265 When no reply is generated, indicate unsupported.
3266 ****************************************************************************/
3268 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3270 char rparam[4];
3272 /* unsupported */
3273 SSVAL(rparam,0,NERR_notsupported);
3274 SSVAL(rparam,2,0); /* converter word */
3276 DEBUG(3,("Unsupported API fd command\n"));
3278 /* now send the reply */
3279 send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
3281 return -1;
3284 /****************************************************************************
3285 Handle remote api calls delivered to a named pipe already opened.
3286 ****************************************************************************/
3288 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3289 uint16 *setup,char *data,char *params,
3290 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3292 BOOL reply = False;
3293 pipes_struct *p = NULL;
3294 int pnum;
3295 int subcommand;
3297 DEBUG(5,("api_fd_reply\n"));
3299 /* First find out the name of this file. */
3300 if (suwcnt != 2) {
3301 DEBUG(0,("Unexpected named pipe transaction.\n"));
3302 return(-1);
3305 /* Get the file handle and hence the file name. */
3307 * NB. The setup array has already been transformed
3308 * via SVAL and so is in gost byte order.
3310 pnum = ((int)setup[1]) & 0xFFFF;
3311 subcommand = ((int)setup[0]) & 0xFFFF;
3313 if(!(p = get_rpc_pipe(pnum))) {
3314 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3315 return api_no_reply(outbuf, mdrcnt);
3318 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum));
3320 /* record maximum data length that can be transmitted in an SMBtrans */
3321 p->max_trans_reply = mdrcnt;
3323 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
3325 switch (subcommand) {
3326 case 0x26:
3327 /* dce/rpc command */
3328 reply = write_to_pipe(p, data, tdscnt);
3329 if (reply)
3330 reply = api_rpc_trans_reply(outbuf, p);
3331 break;
3332 case 0x53:
3333 /* Wait Named Pipe Handle state */
3334 reply = api_WNPHS(outbuf, p, params, tpscnt);
3335 break;
3336 case 0x01:
3337 /* Set Named Pipe Handle state */
3338 reply = api_SNPHS(outbuf, p, params, tpscnt);
3339 break;
3342 if (!reply)
3343 return api_no_reply(outbuf, mdrcnt);
3345 return -1;
3348 /****************************************************************************
3349 The buffer was too small
3350 ****************************************************************************/
3352 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3353 int mdrcnt,int mprcnt,
3354 char **rdata,char **rparam,
3355 int *rdata_len,int *rparam_len)
3357 *rparam_len = MIN(*rparam_len,mprcnt);
3358 *rparam = REALLOC(*rparam,*rparam_len);
3360 *rdata_len = 0;
3362 SSVAL(*rparam,0,NERR_BufTooSmall);
3364 DEBUG(3,("Supplied buffer too small in API command\n"));
3366 return(True);
3370 /****************************************************************************
3371 The request is not supported
3372 ****************************************************************************/
3374 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3375 int mdrcnt,int mprcnt,
3376 char **rdata,char **rparam,
3377 int *rdata_len,int *rparam_len)
3379 *rparam_len = 4;
3380 *rparam = REALLOC(*rparam,*rparam_len);
3382 *rdata_len = 0;
3384 SSVAL(*rparam,0,NERR_notsupported);
3385 SSVAL(*rparam,2,0); /* converter word */
3387 DEBUG(3,("Unsupported API command\n"));
3389 return(True);
3395 struct
3397 char *name;
3398 int id;
3399 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3400 int,int,char **,char **,int *,int *);
3401 int flags;
3402 } api_commands[] = {
3403 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3404 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3405 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3406 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3407 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3408 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3409 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3410 #ifdef PRINTING
3411 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3412 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3413 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3414 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3415 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3416 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3417 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3418 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3419 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3420 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3421 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3422 #endif
3423 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3424 #ifdef PRINTING
3425 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3426 #endif
3427 {"NetServerEnum", 104, api_RNetServerEnum,0},
3428 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3429 {"SetUserPassword", 115, api_SetUserPassword,0},
3430 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3431 #ifdef PRINTING
3432 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3433 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3434 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3435 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3436 #endif
3437 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3438 {NULL, -1, api_Unsupported,0}};
3441 /****************************************************************************
3442 Handle remote api calls
3443 ****************************************************************************/
3445 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3446 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3448 int api_command;
3449 char *rdata = NULL;
3450 char *rparam = NULL;
3451 int rdata_len = 0;
3452 int rparam_len = 0;
3453 BOOL reply=False;
3454 int i;
3456 if (!params) {
3457 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3458 return 0;
3461 api_command = SVAL(params,0);
3463 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3464 api_command,
3465 params+2,
3466 skip_string(params+2,1),
3467 tdscnt,tpscnt,mdrcnt,mprcnt));
3469 for (i=0;api_commands[i].name;i++) {
3470 if (api_commands[i].id == api_command && api_commands[i].fn) {
3471 DEBUG(3,("Doing %s\n",api_commands[i].name));
3472 break;
3476 rdata = (char *)malloc(1024);
3477 if (rdata)
3478 memset(rdata,'\0',1024);
3480 rparam = (char *)malloc(1024);
3481 if (rparam)
3482 memset(rparam,'\0',1024);
3484 if(!rdata || !rparam) {
3485 DEBUG(0,("api_reply: malloc fail !\n"));
3486 return -1;
3489 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3490 &rdata,&rparam,&rdata_len,&rparam_len);
3493 if (rdata_len > mdrcnt ||
3494 rparam_len > mprcnt) {
3495 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3496 &rdata,&rparam,&rdata_len,&rparam_len);
3499 /* if we get False back then it's actually unsupported */
3500 if (!reply)
3501 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3502 &rdata,&rparam,&rdata_len,&rparam_len);
3504 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3506 if (rdata )
3507 free(rdata);
3508 if (rparam)
3509 free(rparam);
3511 return -1;
3514 /****************************************************************************
3515 handle named pipe commands
3516 ****************************************************************************/
3517 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3518 uint16 *setup,char *data,char *params,
3519 int suwcnt,int tdscnt,int tpscnt,
3520 int msrcnt,int mdrcnt,int mprcnt)
3522 DEBUG(3,("named pipe command on <%s> name\n", name));
3524 if (strequal(name,"LANMAN"))
3525 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3527 if (strequal(name,"WKSSVC") ||
3528 strequal(name,"SRVSVC") ||
3529 strequal(name,"WINREG") ||
3530 strequal(name,"SAMR") ||
3531 strequal(name,"LSARPC"))
3533 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
3534 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3537 if (strlen(name) < 1)
3538 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3540 if (setup)
3541 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3543 return 0;
3547 /****************************************************************************
3548 Reply to a SMBtrans.
3549 ****************************************************************************/
3551 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3553 fstring name;
3554 int name_offset = 0;
3555 char *data=NULL,*params=NULL;
3556 uint16 *setup=NULL;
3557 int outsize = 0;
3558 uint16 vuid = SVAL(inbuf,smb_uid);
3559 unsigned int tpscnt = SVAL(inbuf,smb_vwv0);
3560 unsigned int tdscnt = SVAL(inbuf,smb_vwv1);
3561 unsigned int mprcnt = SVAL(inbuf,smb_vwv2);
3562 unsigned int mdrcnt = SVAL(inbuf,smb_vwv3);
3563 unsigned int msrcnt = CVAL(inbuf,smb_vwv4);
3564 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3565 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3566 unsigned int pscnt = SVAL(inbuf,smb_vwv9);
3567 unsigned int psoff = SVAL(inbuf,smb_vwv10);
3568 unsigned int dscnt = SVAL(inbuf,smb_vwv11);
3569 unsigned int dsoff = SVAL(inbuf,smb_vwv12);
3570 unsigned int suwcnt = CVAL(inbuf,smb_vwv13);
3572 memset(name, '\0',sizeof(name));
3573 fstrcpy(name,smb_buf(inbuf));
3575 if (dscnt > tdscnt || pscnt > tpscnt) {
3576 exit_server("invalid trans parameters\n");
3579 if (tdscnt) {
3580 if((data = (char *)malloc(tdscnt)) == NULL) {
3581 DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt));
3582 return(ERROR(ERRDOS,ERRnomem));
3584 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
3585 goto bad_param;
3586 if (smb_base(inbuf)+dsoff+dscnt > inbuf + size)
3587 goto bad_param;
3589 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3592 if (tpscnt) {
3593 if((params = (char *)malloc(tpscnt)) == NULL) {
3594 DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt));
3595 SAFE_FREE(data);
3596 return(ERROR(ERRDOS,ERRnomem));
3598 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
3599 goto bad_param;
3600 if (smb_base(inbuf)+psoff+pscnt > inbuf + size)
3601 goto bad_param;
3603 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3606 if (suwcnt) {
3607 int i;
3608 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
3609 DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt * sizeof(uint16))));
3610 SAFE_FREE(data);
3611 SAFE_FREE(params);
3612 return(ERROR(ERRDOS,ERRnomem));
3614 if (inbuf+smb_vwv14+(suwcnt*SIZEOFWORD) > inbuf + size)
3615 goto bad_param;
3616 if ((smb_vwv14+(suwcnt*SIZEOFWORD) < smb_vwv14) || (smb_vwv14+(suwcnt*SIZEOFWORD) < (suwcnt*SIZEOFWORD)))
3617 goto bad_param;
3619 for (i=0;i<suwcnt;i++)
3620 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3623 if (pscnt < tpscnt || dscnt < tdscnt) {
3624 /* We need to send an interim response then receive the rest
3625 of the parameter/data bytes */
3626 outsize = set_message(outbuf,0,0,True);
3627 show_msg(outbuf);
3628 send_smb(Client,outbuf);
3631 /* receive the rest of the trans packet */
3632 while (pscnt < tpscnt || dscnt < tdscnt) {
3633 BOOL ret;
3634 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
3636 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3638 if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
3639 if(ret) {
3640 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3641 } else {
3642 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3643 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3645 SAFE_FREE(params);
3646 SAFE_FREE(data);
3647 SAFE_FREE(setup);
3648 return(ERROR(ERRSRV,ERRerror));
3651 show_msg(inbuf);
3653 /* Revise total_params and total_data in case they have changed downwards */
3654 if (SVAL(inbuf,smb_vwv0) < tpscnt)
3655 tpscnt = SVAL(inbuf,smb_vwv0);
3656 if (SVAL(inbuf,smb_vwv1) < tdscnt)
3657 tdscnt = SVAL(inbuf,smb_vwv1);
3659 pcnt = SVAL(inbuf,smb_vwv2);
3660 poff = SVAL(inbuf,smb_vwv3);
3661 pdisp = SVAL(inbuf,smb_vwv4);
3663 dcnt = SVAL(inbuf,smb_vwv5);
3664 doff = SVAL(inbuf,smb_vwv6);
3665 ddisp = SVAL(inbuf,smb_vwv7);
3667 pscnt += pcnt;
3668 dscnt += dcnt;
3670 if (dscnt > tdscnt || pscnt > tpscnt)
3671 goto bad_param;
3673 if (pcnt) {
3674 if (pdisp+pcnt >= tpscnt)
3675 goto bad_param;
3676 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
3677 goto bad_param;
3678 if (smb_base(inbuf) + poff + pcnt >= inbuf + bufsize)
3679 goto bad_param;
3680 if (params + pdisp < params)
3681 goto bad_param;
3683 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3686 if (dcnt) {
3687 if (ddisp+dcnt >= tdscnt)
3688 goto bad_param;
3689 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
3690 goto bad_param;
3691 if (smb_base(inbuf) + doff + dcnt >= inbuf + bufsize)
3692 goto bad_param;
3693 if (data + ddisp < data)
3694 goto bad_param;
3696 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3700 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3701 name,tdscnt,tpscnt,suwcnt));
3704 * WinCE wierdness....
3707 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, strlen(local_machine)) == 0) &&
3708 (name[strlen(local_machine)+1] == '\\'))
3709 name_offset = strlen(local_machine)+1;
3711 if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3712 DEBUG(5,("calling named_pipe\n"));
3713 outsize = named_pipe(conn,vuid,outbuf,
3714 name+name_offset+strlen("\\PIPE\\"),setup,data,params,
3715 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3716 } else {
3717 DEBUG(3,("invalid pipe name\n"));
3718 outsize = 0;
3722 if (data)
3723 free(data);
3724 if (params)
3725 free(params);
3726 if (setup)
3727 free(setup);
3729 if (close_on_completion)
3730 close_cnum(conn,vuid);
3732 if (one_way)
3733 return(-1);
3735 if (outsize == 0)
3736 return(ERROR(ERRSRV,ERRnosupport));
3738 return(outsize);
3740 bad_param:
3742 DEBUG(0,("reply_trans: invalid trans parameters\n"));
3743 SAFE_FREE(data);
3744 SAFE_FREE(params);
3745 SAFE_FREE(setup);
3746 return(ERROR(ERRSRV,ERRerror));