diff options
Diffstat (limited to 'source/smbd/ipc.c')
-rw-r--r-- | source/smbd/ipc.c | 365 |
1 files changed, 234 insertions, 131 deletions
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index 8852e57e8b6..78a98077694 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -24,8 +24,6 @@ */ #include "includes.h" -#include "loadparm.h" -#include "pcap.h" #ifdef CHECK_TYPES #undef CHECK_TYPES @@ -61,8 +59,21 @@ extern fstring local_machine; #define SNLEN 15 /* service name length */ #define QNLEN 12 /* queue name maximum length */ +#define MAJOR_VERSION 4 +#define MINOR_VERSION 0 + extern int Client; +static BOOL api_Unsupported(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); +static BOOL api_TooSmall(int cnum,int uid, char *param,char *data, + int mdrcnt,int mprcnt, + char **rdata,char **rparam, + int *rdata_len,int *rparam_len); + + static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) { pstring buf; @@ -189,12 +200,6 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, } } - - -/**************************************************************************** - get a print queue - ****************************************************************************/ - struct pack_desc { char* format; /* formatstring for structure */ char* subformat; /* subformat for structure */ @@ -418,6 +423,11 @@ static void PACKS(struct pack_desc* desc,char *t,char *v) PACK(desc,t,v); } + +/**************************************************************************** + get a print queue + ****************************************************************************/ + static void PackDriverData(struct pack_desc* desc) { char drivdata[4+4+32]; @@ -467,7 +477,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, time_t t = queue->time; /* the client expects localtime */ - t += GMT_TO_LOCAL*TimeDiff(t); + t -= TimeDiff(t); PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */ if (uLevel == 1) { @@ -479,7 +489,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, PACKI(desc,"W",n+1); /* uPosition */ PACKI(desc,"W",queue->status); /* fsStatus */ PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",queue->time); /* ulSubmitted */ + PACKI(desc,"D",t); /* ulSubmitted */ PACKI(desc,"D",queue->size); /* ulSize */ PACKS(desc,"z",queue->file); /* pszComment */ } @@ -488,7 +498,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel, PACKS(desc,"z",queue->user); /* pszUserName */ PACKI(desc,"W",n+1); /* uPosition */ PACKI(desc,"W",queue->status); /* fsStatus */ - PACKI(desc,"D",queue->time); /* ulSubmitted */ + PACKI(desc,"D",t); /* ulSubmitted */ PACKI(desc,"D",queue->size); /* ulSize */ PACKS(desc,"z","Samba"); /* pszComment */ PACKS(desc,"z",queue->file); /* pszDocument */ @@ -545,7 +555,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, PACKI(desc,"W",0); /* uUntiltime */ PACKI(desc,"W",5); /* pad1 */ PACKS(desc,"z",""); /* pszSepFile */ - PACKS(desc,"z","lpd"); /* pszPrProc */ + PACKS(desc,"z","WinPrint"); /* pszPrProc */ PACKS(desc,"z",""); /* pszParms */ if (!status || !status->message[0]) { PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */ @@ -556,7 +566,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel, } PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ - PACKS(desc,"z","NULL"); /* pszDriverName */ + PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */ PackDriverData(desc); /* pDriverData */ } if (uLevel == 2 || uLevel == 4) { @@ -593,6 +603,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data, cbBuf = SVAL(p,2); str3 = p + 4; + /* remove any trailing username */ if ((p = strchr(QueueName,'%'))) *p = 0; DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName)); @@ -662,7 +673,7 @@ static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data, DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); - if (prefix_ok(param_format,"WrLeh")) return False; + if (!prefix_ok(param_format,"WrLeh")) return False; if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) return False; queuecnt = 0; @@ -737,58 +748,23 @@ static BOOL check_server_info(int uLevel, char* id) return True; } -/* used for server information: client, nameserv and ipc */ struct srv_info_struct { fstring name; uint32 type; fstring comment; - fstring domain; /* used ONLY in ipc.c NOT namework.c */ - BOOL server_added; /* used ONLY in ipc.c NOT namework.c */ + fstring domain; + BOOL server_added; }; -/******************************************************************* - filter out unwanted server info - ******************************************************************/ -static BOOL filter_server_info(struct srv_info_struct *server, - char *domain) -{ - if (*domain) - return(strequal(domain, server->domain)); - - return (True); /* be indiscriminate: get all servers! */ -} - -/******************************************************************* - find server in the files saved by nmbd. Return True if we find it. - ******************************************************************/ -static BOOL find_server(struct srv_info_struct *servers, int num_servers, - char *domain, char *name) -{ - int count; - - if (!servers || num_servers == 0) return (False); - - for (count = 0; count < num_servers; count++) { - struct srv_info_struct *s; - - s = &servers[count]; - - if (strequal(name, s->name)) { - StrnCpy(domain, s->domain, sizeof(pstring)-1); - return (True); - } - } - return (False); -} - /******************************************************************* get server info lists from the files saved by nmbd. Return the number of entries ******************************************************************/ static int get_server_info(uint32 servertype, - struct srv_info_struct **servers) + struct srv_info_struct **servers, + char *domain) { FILE *f; pstring fname; @@ -807,18 +783,23 @@ static int get_server_info(uint32 servertype, DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno))); return(0); } + + /* request for everything is code for request all servers */ if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM; + DEBUG(4,("Servertype search: %8x\n",servertype)); + while (!feof(f)) { fstring stype; struct srv_info_struct *s; char *ptr = line; + BOOL ok = True; *ptr = 0; fgets(line,sizeof(line)-1,f); if (!*line) continue; - + if (count == alloced) { alloced += 10; (*servers) = (struct srv_info_struct *) @@ -827,36 +808,58 @@ static int get_server_info(uint32 servertype, bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count)); } s = &(*servers)[count]; - - s->server_added = True; - + if (!next_token(&ptr,s->name , NULL)) continue; if (!next_token(&ptr,stype , NULL)) continue; if (!next_token(&ptr,s->comment, NULL)) continue; if (!next_token(&ptr,s->domain , NULL)) { - /* this allows us to cop with an old nmbd */ - strcpy(s->domain,my_workgroup()); + /* this allows us to cope with an old nmbd */ + strcpy(s->domain,lp_workgroup()); } - - if (sscanf(stype,"%X",&s->type) != 1) continue; - + + if (sscanf(stype,"%X",&s->type) != 1) { + DEBUG(4,("r:host file ")); + ok = False; + } + /* doesn't match up: don't want it */ - if (!(servertype & s->type)) continue; - - /* server entry is a domain, we haven't asked for domains: don't want it */ - if ((s->type&SV_TYPE_DOMAIN_ENUM) && !(servertype&SV_TYPE_DOMAIN_ENUM)) - continue; - - DEBUG(4,("Server %20s %8x %25s %15s\n", - s->name, stype, s->comment, s->domain)); - - count++; + if (!(servertype & s->type)) { + DEBUG(4,("r:serv type ")); + ok = False; + } + + if ((servertype & SV_TYPE_DOMAIN_ENUM) != + (s->type & SV_TYPE_DOMAIN_ENUM)) + { + DEBUG(4,("s: dom mismatch ")); + ok = False; + } + + if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) + { + ok = False; + } + + if (ok) + { + DEBUG(4,("**SV** %20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); + + s->server_added = True; + count++; + } + else + { + DEBUG(4,("%20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); + } } - + fclose(f); return(count); } + /******************************************************************* fill in a server info structure ******************************************************************/ @@ -936,6 +939,11 @@ static int fill_srv_info(struct srv_info_struct *service, } +static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) +{ + return(strcmp(s1->name,s2->name)); +} + /**************************************************************************** view list of servers available (or possibly domains). The info is extracted from lists saved by nmbd on the local host @@ -957,51 +965,47 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, int counted=0,total=0; int i; fstring domain; - BOOL domain_request = (servertype & SV_TYPE_DOMAIN_ENUM) && - !(servertype == SV_TYPE_ALL); + BOOL domain_request; + BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY; + + if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM; + + domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); - domain[0] = 0; p += 8; if (!prefix_ok(str1,"WrLehD")) return False; if (!check_server_info(uLevel,str2)) return False; - DEBUG(4, ("server request level: %s\n", str2)); + DEBUG(4, ("server request level: %s %8x ", str2, servertype)); + DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request))); + DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); - if (strcmp(str1, "WrLehDO") == 0) - { - /* asking for servers. we will have to work out which workgroup was - requested, as we maintain lists for multiple workgroups */ - } - else if (strcmp(str1, "WrLehDz") == 0) - { - /* asking for a specific workgroup */ + if (strcmp(str1, "WrLehDz") == 0) { StrnCpy(domain, p, sizeof(fstring)-1); + } else { + StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1); } if (lp_browse_list()) - { - total = get_server_info(servertype,&servers); - } - - if (!domain[0] && !domain_request) { - extern fstring remote_machine; - /* must be a server request with an assumed domain. find a domain */ - - if (find_server(servers, total, domain, remote_machine)) { - DEBUG(4, ("No domain specified: using %s for %s\n", - domain, remote_machine)); - } else { - /* default to soemthing sensible */ - strcpy(domain,my_workgroup()); - } - } + total = get_server_info(servertype,&servers,domain); data_len = fixed_len = string_len = 0; - for (i=0;i<total;i++) - if (filter_server_info(&servers[i],domain)) { - data_len += fill_srv_info(&servers[i],uLevel,0,&f_len,0,&s_len,0); + qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); + + { + char *lastname=NULL; + + for (i=0;i<total;i++) + { + struct srv_info_struct *s = &servers[i]; + if (lastname && strequal(lastname,s->name)) continue; + lastname = s->name; + data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0); + DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); + if (data_len <= buf_len) { counted++; @@ -1009,6 +1013,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, string_len += s_len; } } + } *rdata_len = fixed_len + string_len; *rdata = REALLOC(*rdata,*rdata_len); @@ -1020,13 +1025,18 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data, s_len = string_len; { + char *lastname=NULL; int count2 = counted; - for (i = 0; i < total && count2;i++) { - if (filter_server_info(&servers[i],domain)) { - fill_srv_info(&servers[i],uLevel,&p,&f_len,&p2,&s_len,*rdata); + for (i = 0; i < total && count2;i++) + { + struct srv_info_struct *s = &servers[i]; + if (lastname && strequal(lastname,s->name)) continue; + lastname = s->name; + fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata); + DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", + s->name, s->type, s->comment, s->domain)); count2--; } - } } *rparam_len = 8; @@ -1289,7 +1299,7 @@ static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data, /* the client expects to get localtime, not GMT, in this bit (I think, this needs testing) */ - t = LocalTime(&unixdate,GMT_TO_LOCAL); + t = LocalTime(&unixdate); SIVAL(p,4,0); /* msecs ? */ CVAL(p,8) = t->tm_hour; @@ -1332,14 +1342,16 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data, *rdata_len = 0; - SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,0,NERR_badpass); SSVAL(*rparam,2,0); /* converter word */ DEBUG(3,("Set password for <%s>\n",user)); - if (!password_ok(user,pass1,strlen(pass1),NULL,False) || - !chgpasswd(user,pass1,pass2)) - SSVAL(*rparam,0,NERR_badpass); + if (password_ok(user,pass1,strlen(pass1),NULL,False) && + chgpasswd(user,pass1,pass2)) + { + SSVAL(*rparam,0,NERR_Success); + } bzero(pass1,sizeof(fstring)); bzero(pass2,sizeof(fstring)); @@ -1551,8 +1563,7 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data, int l = 0; while (l<64 && *s) { - if (isalnum(*s) || strchr("-._",*s)) - name[l++] = *s; + if (issafe(*s)) name[l++] = *s; s++; } name[l] = 0; @@ -1658,7 +1669,7 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, strcpy(comment,lp_serverstring()); - if ((count=get_server_info(SV_TYPE_ALL,&servers))>0) { + if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { for (i=0;i<count;i++) if (strequal(servers[i].name,local_machine)) { servertype = servers[i].type; @@ -1667,9 +1678,10 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, } if (servers) free(servers); - SCVAL(p,0,2); /* version_major */ - SCVAL(p,1,0); /* version_minor */ + SCVAL(p,0,MAJOR_VERSION); + SCVAL(p,1,MINOR_VERSION); SIVAL(p,2,servertype); + if (mdrcnt == struct_len) { SIVAL(p,6,0); } else { @@ -1740,16 +1752,16 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data, p += 4; SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,my_workgroup()); + strcpy(p2,lp_workgroup()); p2 = skip_string(p2,1); p += 4; - SCVAL(p,0,2); /* major version?? */ - SCVAL(p,1,1); /* minor version?? */ + SCVAL(p,0,MAJOR_VERSION); + SCVAL(p,1,MINOR_VERSION); p += 2; SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,my_workgroup()); /* login domain?? */ + strcpy(p2,lp_workgroup()); /* login domain?? */ p2 = skip_string(p2,1); p += 4; @@ -1827,7 +1839,8 @@ static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data, p2 = skip_string(p2,1); } if (uLevel == 11) { /* modelled after NTAS 3.51 reply */ - SSVAL(p,34,USER_PRIV_USER); /* user privilege */ + SSVAL(p,34, + Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,36,0); /* auth flags */ SIVALS(p,40,-1); /* password age */ SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */ @@ -1862,7 +1875,8 @@ static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data, if (uLevel == 1 || uLevel == 2) { memset(p+22,' ',16); /* password */ SIVALS(p,38,-1); /* password age */ - SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */ + SSVAL(p,42, + Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ strcpy(p2,"\\\\%L\\HOMES"); standard_sub_basic(p2); @@ -2012,7 +2026,7 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data, strupper(mypath); PACKS(&desc,"z",mypath); /* computer */ } - PACKS(&desc,"z",my_workgroup());/* domain */ + PACKS(&desc,"z",lp_workgroup());/* domain */ PACKS(&desc,"z",lp_logon_script()); /* script path */ PACKI(&desc,"D",0); /* reserved */ } @@ -2498,6 +2512,92 @@ static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data, return(True); } + +struct +{ + char * name; + char * pipename; + int subcommand; + BOOL (*fn) (); +} api_fd_commands [] = + { + { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, + { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, + { NULL, NULL, -1, api_Unsupported } + }; + +/**************************************************************************** + handle remote api calls delivered to a named pipe already opened. + ****************************************************************************/ +static int api_fd_reply(int cnum,int uid,char *outbuf, + uint16 *setup,char *data,char *params, + int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) +{ + char *rdata = NULL; + char *rparam = NULL; + int rdata_len = 0; + int rparam_len = 0; + BOOL reply=False; + int i; + int fd; + int subcommand; + + /* First find out the name of this file. */ + if (suwcnt != 2) + { + DEBUG(0,("Unexpected named pipe transaction.\n")); + return(-1); + } + + /* Get the file handle and hence the file name. */ + fd = setup[1]; + subcommand = setup[0]; + + DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name)); + DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", + tdscnt,tpscnt,mdrcnt,mprcnt)); + + for (i=0;api_fd_commands[i].name;i++) + if (strequal(api_fd_commands[i].pipename, Files[fd].name) && + api_fd_commands[i].subcommand == subcommand && + api_fd_commands[i].fn) + { + DEBUG(3,("Doing %s\n",api_fd_commands[i].name)); + break; + } + + rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); + rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); + + reply = api_fd_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + if (rdata_len > mdrcnt || + rparam_len > mprcnt) + { + reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + } + + + /* if we get False back then it's actually unsupported */ + if (!reply) + api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt, + &rdata,&rparam,&rdata_len,&rparam_len); + + /* now send the reply */ + send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); + + if (rdata) + free(rdata); + if (rparam) + free(rparam); + + return(-1); +} + + + /**************************************************************************** the buffer was too small ****************************************************************************/ @@ -2648,6 +2748,10 @@ static int named_pipe(int cnum,int uid, char *outbuf,char *name, if (strequal(name,"LANMAN")) return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt)); +if (strlen(name) < 1) + return(api_fd_reply(cnum,uid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt)); + + DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n", name,(int)setup[0],(int)setup[1])); @@ -2717,12 +2821,9 @@ int reply_trans(char *inbuf,char *outbuf) while (pscnt < tpscnt || dscnt < tdscnt) { int pcnt,poff,dcnt,doff,pdisp,ddisp; - - receive_smb(Client,inbuf, 0); - show_msg(inbuf); - - /* Ensure this is still a trans packet (sanity check) */ - if(CVAL(inbuf, smb_com) != SMBtrans) + + if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) || + CVAL(inbuf, smb_com) != SMBtrans) { DEBUG(2,("Invalid secondary trans2 packet\n")); if (params) free(params); @@ -2730,6 +2831,8 @@ int reply_trans(char *inbuf,char *outbuf) if (setup) free(setup); return(ERROR(ERRSRV,ERRerror)); } + + show_msg(inbuf); tpscnt = SVAL(inbuf,smb_vwv0); tdscnt = SVAL(inbuf,smb_vwv1); |