/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
Pipe SMB reply routines
- Copyright (C) Andrew Tridgell 1992-1997,
- Paul Ashton 1997,
- Luke Kenneth Casson Leighton 1996-1997.
+ Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Luke Kenneth Casson Leighton 1996-1998
+ Copyright (C) Paul Ashton 1997-1998.
+ Copyright (C) Jeremy Allison 2005.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
This file handles reply_ calls on named pipes that the server
#include "includes.h"
-#include "trans2.h"
-#include "nterr.h"
#define PIPE "\\PIPE\\"
#define PIPELEN strlen(PIPE)
-#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
-
-/* look in server.c for some explanation of these variables */
-extern int Protocol;
-extern int DEBUGLEVEL;
-extern int chain_fnum;
-extern char magic_char;
-extern connection_struct Connections[];
-extern files_struct Files[];
-extern BOOL case_sensitive;
-extern pstring sesssetup_user;
-extern int Client;
-extern fstring myworkgroup;
-
-/* this macro should always be used to extract an fnum (smb_fid) from
-a packet to ensure chaining works correctly */
-#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
-
-char * known_pipes [] =
-{
- "lsarpc",
-#if 0
- "NETLOGON",
-#endif
- NULL
-};
+#define MAX_PIPE_NAME_LEN 24
-/****************************************************************************
- reply to an open and X on a named pipe
+/* PIPE/<name>/<pid>/<pnum> */
+#define PIPEDB_KEY_FORMAT "PIPE/%s/%u/%d"
- In fact what we do is to open a regular file with the same name in
- /tmp. This can then be closed as normal. Reading and writing won't
- make much sense, but will do *something*. The real reason for this
- support is to be able to do transactions on them (well, on lsarpc
- for domain login purposes...).
+struct pipe_dbrec {
+ struct server_id pid;
+ int pnum;
+ uid_t uid;
- This code is basically stolen from reply_open_and_X with some
- wrinkles to handle pipes.
-****************************************************************************/
-int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
-{
- pstring fname;
- int cnum = SVAL(inbuf,smb_tid);
- int fnum = -1;
- int smb_mode = SVAL(inbuf,smb_vwv3);
- int smb_attr = SVAL(inbuf,smb_vwv5);
-#if 0
- int open_flags = SVAL(inbuf,smb_vwv2);
- int smb_sattr = SVAL(inbuf,smb_vwv4);
- uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
-#endif
- int smb_ofun = SVAL(inbuf,smb_vwv8);
- int unixmode;
- int size=0,fmode=0,mtime=0,rmode=0;
- struct stat sbuf;
- int smb_action = 0;
- int i;
- BOOL bad_path = False;
-
- /* XXXX we need to handle passed times, sattr and flags */
- pstrcpy(fname,smb_buf(inbuf));
-
- /* If the name doesn't start \PIPE\ then this is directed */
- /* at a mailslot or something we really, really don't understand, */
- /* not just something we really don't understand. */
- if ( strncmp(fname,PIPE,PIPELEN) != 0 )
- return(ERROR(ERRSRV,ERRaccess));
-
- DEBUG(4,("Opening pipe %s.\n", fname));
-
- /* Strip \PIPE\ off the name. */
- pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
-
- /* See if it is one we want to handle. */
- for( i = 0; known_pipes[i] ; i++ )
- if( strcmp(fname,known_pipes[i]) == 0 )
- break;
-
- if ( known_pipes[i] == NULL )
- return(ERROR(ERRSRV,ERRaccess));
-
- /* Known pipes arrive with DIR attribs. Remove it so a regular file */
- /* can be opened and add it in after the open. */
- DEBUG(3,("Known pipe %s opening.\n",fname));
- smb_attr &= ~aDIR;
- Connections[cnum].read_only = 0;
- smb_ofun |= 0x10; /* Add Create it not exists flag */
-
- unix_convert(fname,cnum,0,&bad_path);
-
- fnum = find_free_file();
- if (fnum < 0)
- return(ERROR(ERRSRV,ERRnofids));
-
- if (!check_name(fname,cnum))
- return(UNIXERROR(ERRDOS,ERRnoaccess));
-
- unixmode = unix_mode(cnum,smb_attr);
-
- open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
- 0, &rmode,&smb_action);
-
- if (!Files[fnum].open)
- {
- /* Change the error code if bad_path was set. */
- if((errno == ENOENT) && bad_path)
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
- close_file(fnum);
- return(ERROR(ERRDOS,ERRnoaccess));
- }
-
- size = sbuf.st_size;
- fmode = dos_mode(cnum,fname,&sbuf);
- mtime = sbuf.st_mtime;
- if (fmode & aDIR) {
- close_file(fnum);
- return(ERROR(ERRDOS,ERRnoaccess));
- }
-
- /* Prepare the reply */
- set_message(outbuf,15,0,True);
-
- /* Put things back the way they were. */
- Connections[cnum].read_only = 1;
-
- /* Mark the opened file as an existing named pipe in message mode. */
- SSVAL(outbuf,smb_vwv9,2);
- SSVAL(outbuf,smb_vwv10,0xc700);
- if (rmode == 2)
- {
- DEBUG(4,("Resetting open result to open from create.\n"));
- rmode = 1;
- }
-
- SSVAL(outbuf,smb_vwv2,fnum);
- SSVAL(outbuf,smb_vwv3,fmode);
- put_dos_date3(outbuf,smb_vwv4,mtime);
- SIVAL(outbuf,smb_vwv6,size);
- SSVAL(outbuf,smb_vwv8,rmode);
- SSVAL(outbuf,smb_vwv11,smb_action);
-
- chain_fnum = fnum;
-
- DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
- fname, fnum, Files[fnum].name));
-
- return chain_reply(inbuf,outbuf,length,bufsize);
-}
-
-
-/****************************************************************************
- api_LsarpcSNPHS
-
- SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
- so just blithely return True. This is really only for NT domain stuff,
- we we're only handling that - don't assume Samba now does complete
- named pipe handling.
-****************************************************************************/
-BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
-{
- uint16 id;
+ char name[MAX_PIPE_NAME_LEN];
+ fstring user;
+};
- id = param[0] + (param[1] << 8);
- DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
- return(True);
-}
+extern struct pipe_id_info pipe_names[];
/****************************************************************************
- api_LsarpcTNP
-
- TransactNamedPipe on \PIPE\lsarpc.
+ Reply to an open and X on a named pipe.
+ This code is basically stolen from reply_open_and_X with some
+ wrinkles to handle pipes.
****************************************************************************/
-static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
-{
- uint32 dword1, dword2;
- char pname[] = "\\PIPE\\lsass";
-
- /* All kinds of mysterious numbers here */
- *rdata_len = 68;
- *rdata = REALLOC(*rdata,*rdata_len);
-
- dword1 = IVAL(data,0xC);
- dword2 = IVAL(data,0x10);
-
- SIVAL(*rdata,0,0xc0005);
- SIVAL(*rdata,4,0x10);
- SIVAL(*rdata,8,0x44);
- SIVAL(*rdata,0xC,dword1);
-
- SIVAL(*rdata,0x10,dword2);
- SIVAL(*rdata,0x14,0x15);
- SSVAL(*rdata,0x18,sizeof(pname));
- strcpy(*rdata + 0x1a,pname);
- SIVAL(*rdata,0x28,1);
- memcpy(*rdata + 0x30, data + 0x34, 0x14);
-}
-
-static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
-{
- uint32 dword1;
-
- /* All kinds of mysterious numbers here */
- *rdata_len = 48;
- *rdata = REALLOC(*rdata,*rdata_len);
-
- dword1 = IVAL(data,0xC);
-
- SIVAL(*rdata,0,0x03020005);
- SIVAL(*rdata,4,0x10);
- SIVAL(*rdata,8,0x30);
- SIVAL(*rdata,0xC,dword1);
- SIVAL(*rdata,0x10,0x18);
- SIVAL(*rdata,0x1c,0x44332211);
- SIVAL(*rdata,0x20,0x88776655);
- SIVAL(*rdata,0x24,0xCCBBAA99);
- SIVAL(*rdata,0x28,0x11FFEEDD);
-}
-
-static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
-{
- uint32 dword1;
- uint16 word1;
- char * workgroup = myworkgroup;
- int wglen = strlen(workgroup);
- int i;
-
- /* All kinds of mysterious numbers here */
- *rdata_len = 90 + 2 * wglen;
- *rdata = REALLOC(*rdata,*rdata_len);
-
- dword1 = IVAL(data,0xC);
- word1 = SVAL(data,0x2C);
-
- SIVAL(*rdata,0,0x03020005);
- SIVAL(*rdata,4,0x10);
- SIVAL(*rdata,8,0x60);
- SIVAL(*rdata,0xC,dword1);
- SIVAL(*rdata,0x10,0x48);
- SSVAL(*rdata,0x18,0x5988); /* This changes */
- SSVAL(*rdata,0x1A,0x15);
- SSVAL(*rdata,0x1C,word1);
- SSVAL(*rdata,0x20,6);
- SSVAL(*rdata,0x22,8);
- SSVAL(*rdata,0x24,0x8E8); /* So does this */
- SSVAL(*rdata,0x26,0x15);
- SSVAL(*rdata,0x28,0x4D48); /* And this */
- SSVAL(*rdata,0x2A,0x15);
- SIVAL(*rdata,0x2C,4);
- SIVAL(*rdata,0x34,wglen);
- for ( i = 0 ; i < wglen ; i++ )
- (*rdata)[0x38 + i * 2] = workgroup[i];
-
- /* Now fill in the rest */
- i = 0x38 + wglen * 2;
- SSVAL(*rdata,i,0x648);
- SIVAL(*rdata,i+2,4);
- SIVAL(*rdata,i+6,0x401);
- SSVAL(*rdata,i+0xC,0x500);
- SIVAL(*rdata,i+0xE,0x15);
- SIVAL(*rdata,i+0x12,0x2372FE1);
- SIVAL(*rdata,i+0x16,0x7E831BEF);
- SIVAL(*rdata,i+0x1A,0x4B454B2);
-}
-
-static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
-{
- uint32 dword1;
-
- /* All kinds of mysterious numbers here */
- *rdata_len = 48;
- *rdata = REALLOC(*rdata,*rdata_len);
-
- dword1 = IVAL(data,0xC);
- SIVAL(*rdata,0,0x03020005);
- SIVAL(*rdata,4,0x10);
- SIVAL(*rdata,8,0x30);
- SIVAL(*rdata,0xC,dword1);
- SIVAL(*rdata,0x10,0x18);
-}
-
-
-BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
-{
- uint32 id,id2;
-
- id = IVAL(data,0);
-
- DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
- switch (id)
- {
- case 0xb0005:
- LsarpcTNP1(data,rdata,rdata_len);
- break;
-
- case 0x03000005:
- id2 = IVAL(data,8);
- DEBUG(4,("\t- Suboperation %lx\n",id2));
- switch (id2 & 0xF)
- {
- case 8:
- LsarpcTNP2(data,rdata,rdata_len);
- break;
-
- case 0xC:
- LsarpcTNP4(data,rdata,rdata_len);
- break;
-
- case 0xE:
- LsarpcTNP3(data,rdata,rdata_len);
- break;
- }
- break;
- }
- return(True);
-}
-
-#if 0 /* HAVING TO DO THIS TO GET THINGS TO COMPILE - LUKE PLEASE CHECK THIS !!! */
-
-/*
- PAXX: Someone fix above.
- The above API is indexing RPC calls based on RPC flags and
- fragment length. I've decided to do it based on operation number :-)
-*/
-
-/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
-/* identauth >= 2^32 can be detected because it will be specified in hex */
-static void make_dom_sid(DOM_SID *sid, char *domsid)
+int reply_open_pipe_and_X(connection_struct *conn,
+ char *inbuf,char *outbuf,int length,int bufsize)
{
- int identauth;
- char *p;
-
- DEBUG(4,("netlogon domain SID: %s\n", domsid));
-
- /* assume, but should check, that domsid starts "S-" */
- p = strtok(domsid+2,"-");
- sid->sid_no = atoi(p);
-
- /* identauth in decimal should be < 2^32 */
- /* identauth in hex should be >= 2^32 */
- identauth = atoi(strtok(0,"-"));
-
- DEBUG(4,("netlogon rev %d\n", sid->sid_no));
- DEBUG(4,("netlogon %s ia %d\n", p, identauth));
-
- sid->id_auth[0] = 0;
- sid->id_auth[1] = 0;
- sid->id_auth[2] = (identauth & 0xff000000) >> 24;
- sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
- sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
- sid->id_auth[5] = (identauth & 0x000000ff);
+ pstring fname;
+ pstring pipe_name;
+ uint16 vuid = SVAL(inbuf, smb_uid);
+ smb_np_struct *p;
+ int size=0,fmode=0,mtime=0,rmode=0;
+ int i;
- sid->num_auths = 0;
+ /* XXXX we need to handle passed times, sattr and flags */
+ srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), pipe_name,
+ smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE);
- while ((p = strtok(0, "-")) != NULL)
- {
- sid->sub_auths[sid->num_auths++] = atoi(p);
+ /* If the name doesn't start \PIPE\ then this is directed */
+ /* at a mailslot or something we really, really don't understand, */
+ /* not just something we really don't understand. */
+ if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) {
+ return(ERROR_DOS(ERRSRV,ERRaccess));
}
-}
-static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len)
-{
- if (hdr == NULL) return;
-
- hdr->major = 5; /* RPC version 5 */
- hdr->minor = 0; /* minor version 0 */
- hdr->pkt_type = 2; /* RPC response packet */
- hdr->frag = 3; /* first frag + last frag */
- hdr->pack_type = 1; /* packed data representation */
- hdr->frag_len = data_len; /* fragment length, fill in later */
- hdr->auth_len = 0; /* authentication length */
- hdr->call_id = call_id; /* call identifier - match incoming RPC */
- hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */
- hdr->context_id = 0; /* presentation context identifier */
- hdr->cancel_count = 0; /* cancel count */
- hdr->reserved = 0; /* reserved */
-}
+ DEBUG(4,("Opening pipe %s.\n", pipe_name));
-static void make_rpc_reply(char *inbuf, char *q, char *base, int data_len)
-{
- uint32 callid = RIVAL(inbuf, 12);
- RPC_HDR hdr;
-
- create_rpc_reply(&hdr, callid, data_len);
- smb_io_rpc_hdr(False, &hdr, q, base, 4);
-}
-
-static int lsa_reply_open_policy(char *q, char *base)
-{
- char *start = q;
- LSA_R_OPEN_POL r_o;
-
- /* set up the LSA QUERY INFO response */
- bzero(&(r_o.pol.data), POL_HND_SIZE);
- r_o.status = 0x0;
-
- /* store the response in the SMB stream */
- q = lsa_io_r_open_pol(False, &r_o, q, base, 4);
+ /* See if it is one we want to handle. */
+ for( i = 0; pipe_names[i].client_pipe ; i++ ) {
+ if( strequal(pipe_name,pipe_names[i].client_pipe)) {
+ break;
+ }
+ }
- /* return length of SMB data stored */
- return q - start;
-}
+ if (pipe_names[i].client_pipe == NULL) {
+ return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe));
+ }
-static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate)
-{
- hdr->uni_max_len = max_len;
- hdr->uni_str_len = len;
- hdr->undoc = terminate;
-}
+ /* Strip \PIPE\ off the name. */
+ pstrcpy(fname, pipe_name + PIPELEN);
-static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate)
-{
- /* set up string lengths. add one if string is not null-terminated */
- str->uni_max_len = len + (terminate != 0 ? 1 : 0);
- str->undoc = 0;
- str->uni_str_len = len;
+#if 0
+ /*
+ * Hack for NT printers... JRA.
+ */
+ if(should_fail_next_srvsvc_open(fname))
+ return(ERROR(ERRSRV,ERRaccess));
+#endif
- /* store the string (null-terminated copy) */
- PutUniCode((char *)str->buffer, buf);
+ /* Known pipes arrive with DIR attribs. Remove it so a regular file */
+ /* can be opened and add it in after the open. */
+ DEBUG(3,("Known pipe %s opening.\n",fname));
- /* overwrite the last character: some strings are terminated with 4 not 0 */
- str->buffer[len] = (uint16)terminate;
-}
+ p = open_rpc_pipe_p(fname, conn, vuid);
+ if (!p) {
+ return(ERROR_DOS(ERRSRV,ERRnofids));
+ }
-static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
-{
- int domlen = strlen(dom_name);
+ /* Prepare the reply */
+ set_message(inbuf,outbuf,15,0,True);
- d_q->uni_dom_max_len = domlen * 2;
- d_q->padding = 0;
- d_q->uni_dom_str_len = domlen * 2;
+ /* Mark the opened file as an existing named pipe in message mode. */
+ SSVAL(outbuf,smb_vwv9,2);
+ SSVAL(outbuf,smb_vwv10,0xc700);
- d_q->buffer_dom_name = 0; /* domain buffer pointer */
- d_q->buffer_dom_sid = 0; /* domain sid pointer */
+ if (rmode == 2) {
+ DEBUG(4,("Resetting open result to open from create.\n"));
+ rmode = 1;
+ }
- /* NOT null-terminated: 4-terminated instead! */
- make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
+ SSVAL(outbuf,smb_vwv2, p->pnum);
+ SSVAL(outbuf,smb_vwv3,fmode);
+ srv_put_dos_date3(outbuf,smb_vwv4,mtime);
+ SIVAL(outbuf,smb_vwv6,size);
+ SSVAL(outbuf,smb_vwv8,rmode);
+ SSVAL(outbuf,smb_vwv11,0x0001);
- make_dom_sid(&(d_q->dom_sid), dom_sid);
+ return chain_reply(inbuf,outbuf,length,bufsize);
}
-static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
- char *dom_name, char *dom_sid)
-{
- char *start = q;
- LSA_R_QUERY_INFO r_q;
-
- /* set up the LSA QUERY INFO response */
-
- r_q.undoc_buffer = 1; /* not null */
- r_q.info_class = q_q->info_class;
-
- make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
-
- r_q.status = 0x0;
-
- /* store the response in the SMB stream */
- q = lsa_io_r_query(False, &r_q, q, base, 4);
-
- /* return length of SMB data stored */
- return q - start;
-}
+/****************************************************************************
+ Reply to a write on a pipe.
+****************************************************************************/
-static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status)
+int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize)
{
- memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data));
- r_c->status = status;
-}
+ smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0);
+ uint16 vuid = SVAL(inbuf,smb_uid);
+ size_t numtowrite = SVAL(inbuf,smb_vwv1);
+ int nwritten;
+ int outsize;
+ char *data;
+
+ if (!p) {
+ return(ERROR_DOS(ERRDOS,ERRbadfid));
+ }
-#if 0
- char chal[8];
- /* PAXX: set these to random values */
- for (int i = 0; i < 8; i+++)
- {
- chal[i] = 0xA5;
+ if (p->vuid != vuid) {
+ return ERROR_NT(NT_STATUS_INVALID_HANDLE);
}
-#endif
-static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
- char chal[8])
-{
- char *start = q;
- LSA_R_REQ_CHAL r_c;
+ data = smb_buf(inbuf) + 3;
- /* set up the LSA REQUEST CHALLENGE response */
+ if (numtowrite == 0) {
+ nwritten = 0;
+ } else {
+ nwritten = write_to_pipe(p, data, numtowrite);
+ }
- make_lsa_r_req_chal(&r_c, chal, 0);
+ if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
+ return (UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ outsize = set_message(inbuf,outbuf,1,0,True);
- /* store the response in the SMB stream */
- q = lsa_io_r_req_chal(False, &r_c, q, base, 4);
+ SSVAL(outbuf,smb_vwv0,nwritten);
+
+ DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));
- /* return length of SMB data stored */
- return q - start;
+ return(outsize);
}
-static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8])
-{
- memcpy(cred->data, resp_cred, sizeof(cred->data));
-}
+/****************************************************************************
+ Reply to a write and X.
-static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
- char resp_cred[8], NEG_FLAGS *flgs, int status)
-{
- make_lsa_chal(&(r_a->srv_chal), resp_cred);
- memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs));
- r_a->status = status;
-}
+ This code is basically stolen from reply_write_and_X with some
+ wrinkles to handle pipes.
+****************************************************************************/
-static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
- char resp_cred[8], int status)
+int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
{
- char *start = q;
- LSA_R_AUTH_2 r_a;
+ smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2);
+ uint16 vuid = SVAL(inbuf,smb_uid);
+ size_t numtowrite = SVAL(inbuf,smb_vwv10);
+ int nwritten = -1;
+ int smb_doff = SVAL(inbuf, smb_vwv11);
+ BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) ==
+ (PIPE_START_MESSAGE|PIPE_RAW_MODE));
+ char *data;
+
+ if (!p) {
+ return(ERROR_DOS(ERRDOS,ERRbadfid));
+ }
- /* set up the LSA AUTH 2 response */
+ if (p->vuid != vuid) {
+ return ERROR_NT(NT_STATUS_INVALID_HANDLE);
+ }
- make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
+ data = smb_base(inbuf) + smb_doff;
+
+ if (numtowrite == 0) {
+ nwritten = 0;
+ } else {
+ if(pipe_start_message_raw) {
+ /*
+ * For the start of a message in named pipe byte mode,
+ * the first two bytes are a length-of-pdu field. Ignore
+ * them (we don't trust the client). JRA.
+ */
+ if(numtowrite < 2) {
+ DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n",
+ (unsigned int)numtowrite ));
+ return (UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ data += 2;
+ numtowrite -= 2;
+ }
+ nwritten = write_to_pipe(p, data, numtowrite);
+ }
- /* store the response in the SMB stream */
- q = lsa_io_r_auth_2(False, &r_a, q, base, 4);
+ if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
+ return (UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ set_message(inbuf,outbuf,6,0,True);
- /* return length of SMB data stored */
- return q - start;
-}
+ nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
+ SSVAL(outbuf,smb_vwv2,nwritten);
+
+ DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));
-static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time)
-{
- make_lsa_chal(&(cred->challenge), srv_chal);
- cred->timestamp = srv_time;
+ return chain_reply(inbuf,outbuf,length,bufsize);
}
-
-static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
- char srv_chal[8], UTIME srv_time, int status)
-{
- make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time);
- r_a->status = status;
-}
+/****************************************************************************
+ Reply to a read and X.
+ This code is basically stolen from reply_read_and_X with some
+ wrinkles to handle pipes.
+****************************************************************************/
-static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
- char srv_cred[8], UTIME srv_time,
- int status)
+int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
{
- char *start = q;
- LSA_R_SRV_PWSET r_s;
-
- /* set up the LSA Server Password Set response */
- make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status);
-
- /* store the response in the SMB stream */
- q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4);
-
- /* return length of SMB data stored */
- return q - start;
-}
-
-static void make_lsa_user_info(LSA_USER_INFO *usr,
-
- NTTIME *logon_time,
- NTTIME *logoff_time,
- NTTIME *kickoff_time,
- NTTIME *pass_last_set_time,
- NTTIME *pass_can_change_time,
- NTTIME *pass_must_change_time,
-
- char *user_name,
- char *full_name,
- char *logon_script,
- char *profile_path,
- char *home_dir,
- char *dir_drive,
-
- uint16 logon_count,
- uint16 bad_pw_count,
-
- uint32 user_id,
- uint32 group_id,
- uint32 num_groups,
- DOM_GID *gids,
- uint32 user_flgs,
-
- char sess_key[16],
-
- char *logon_srv,
- char *logon_dom,
+ smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2);
+ int smb_maxcnt = SVAL(inbuf,smb_vwv5);
+ int smb_mincnt = SVAL(inbuf,smb_vwv6);
+ int nread = -1;
+ char *data;
+ BOOL unused;
+
+ /* we don't use the offset given to use for pipe reads. This
+ is deliberate, instead we always return the next lump of
+ data on the pipe */
+#if 0
+ uint32 smb_offs = IVAL(inbuf,smb_vwv3);
+#endif
- char *dom_sid,
- char *other_sids) /* space-delimited set of SIDs */
-{
- /* only cope with one "other" sid, right now. */
- /* need to count the number of space-delimited sids */
- int i;
- int num_other_sids = other_sids != NULL ? 1 : 0;
-
- int len_user_name = strlen(user_name );
- int len_full_name = strlen(full_name );
- int len_logon_script = strlen(logon_script);
- int len_profile_path = strlen(profile_path);
- int len_home_dir = strlen(home_dir );
- int len_dir_drive = strlen(dir_drive );
-
- int len_logon_srv = strlen(logon_srv);
- int len_logon_dom = strlen(logon_dom);
-
- usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */
-
- usr->logon_time = *logon_time;
- usr->logoff_time = *logoff_time;
- usr->kickoff_time = *kickoff_time;
- usr->pass_last_set_time = *pass_last_set_time;
- usr->pass_can_change_time = *pass_can_change_time;
- usr->pass_must_change_time = *pass_must_change_time;
-
- make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4);
- make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4);
- make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4);
- make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4);
- make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4);
- make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4);
-
- usr->logon_count = logon_count;
- usr->bad_pw_count = bad_pw_count;
-
- usr->user_id = user_id;
- usr->group_id = group_id;
- usr->num_groups = num_groups;
- usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */
- usr->user_flgs = user_flgs;
-
- if (sess_key != NULL)
- {
- memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key));
+ if (!p) {
+ return(ERROR_DOS(ERRDOS,ERRbadfid));
}
- else
- {
- bzero(usr->sess_key, sizeof(usr->sess_key));
- }
-
- make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4);
- make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4);
- usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */
+ set_message(inbuf,outbuf,12,0,True);
+ data = smb_buf(outbuf);
- bzero(usr->padding, sizeof(usr->padding));
+ nread = read_from_pipe(p, data, smb_maxcnt, &unused);
- usr->num_other_sids = num_other_sids;
- usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0;
-
- make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0);
- make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0);
- make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0);
- make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0);
- make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0);
- make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0);
-
- usr->num_groups2 = num_groups;
- for (i = 0; i < num_groups; i++)
- {
- usr->gids[i] = gids[i];
+ if (nread < 0) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
}
+
+ SSVAL(outbuf,smb_vwv5,nread);
+ SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+ SSVAL(smb_buf(outbuf),-2,nread);
+
+ DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n",
+ p->pnum, smb_mincnt, smb_maxcnt, nread));
- make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0);
- make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0);
-
- make_dom_sid(&(usr->dom_sid), dom_sid);
- make_dom_sid(&(usr->other_sids[0]), other_sids);
-}
-
-
-static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base,
- char srv_cred[8], UTIME srv_time,
- LSA_USER_INFO *user_info)
-{
- char *start = q;
- LSA_R_SAM_LOGON r_s;
-
- /* XXXX maybe we want to say 'no', reject the client's credentials */
- r_s.buffer_creds = 1; /* yes, we have valid server credentials */
- make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
-
- /* store the user information, if there is any. */
- r_s.user = user_info;
- r_s.buffer_user = user_info != NULL ? 1 : 0;
- r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER);
-
- /* store the response in the SMB stream */
- q = lsa_io_r_sam_logon(False, &r_s, q, base, 4);
-
- /* return length of SMB data stored */
- return q - start;
+ /* Ensure we set up the message length to include the data length read. */
+ set_message_bcc(inbuf,outbuf,nread);
+ return chain_reply(inbuf,outbuf,length,bufsize);
}
+/****************************************************************************
+ Reply to a close.
+****************************************************************************/
-static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
- char srv_cred[8], UTIME srv_time,
- uint32 status)
+int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
{
- char *start = q;
- LSA_R_SAM_LOGOFF r_s;
+ smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0);
+ int outsize = set_message(inbuf,outbuf,0,0,True);
- /* XXXX maybe we want to say 'no', reject the client's credentials */
- r_s.buffer_creds = 1; /* yes, we have valid server credentials */
- make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time);
+ if (!p) {
+ return(ERROR_DOS(ERRDOS,ERRbadfid));
+ }
- r_s.status = status;
+ DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum));
- /* store the response in the SMB stream */
- q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4);
+ if (!close_rpc_pipe_hnd(p)) {
+ return ERROR_DOS(ERRDOS,ERRbadfid);
+ }
+
+ /* TODO: REMOVE PIPE FROM DB */
- /* return length of SMB data stored */
- return q - start;
+ return(outsize);
}
-
-#endif /* LUKE PLEASE CHECK THIS !! */