/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
Pipe SMB reply routines
- Copyright (C) Andrew Tridgell 1992-1997,
- Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
- Copyright (C) Paul Ashton 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))
+#define MAX_PIPE_NAME_LEN 24
-/* 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;
+/* PIPE/<name>/<pid>/<pnum> */
+#define PIPEDB_KEY_FORMAT "PIPE/%s/%u/%d"
-/* 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))
+struct pipe_dbrec {
+ struct server_id pid;
+ int pnum;
+ uid_t uid;
-char * known_pipes [] =
-{
- "lsarpc",
-#if NTDOMAIN
- "NETLOGON",
-#endif
- NULL
+ char name[MAX_PIPE_NAME_LEN];
+ fstring user;
};
-/****************************************************************************
- reply to an open and X on a named pipe
-
- 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...).
-
- 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);
-}
+extern struct pipe_id_info pipe_names[];
/****************************************************************************
- 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.
+ 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.
****************************************************************************/
-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;
-
- id = param[0] + (param[1] << 8);
- DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
- return(True);
-}
-
-
-/****************************************************************************
- api_LsarpcTNP
-
- TransactNamedPipe on \PIPE\lsarpc.
-****************************************************************************/
-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);
-}
-
-
-#ifdef NTDOMAIN
-/*
- 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 :-)
-*/
-
-/* this function is due to be replaced */
-static void initrpcreply(char *inbuf, char *q)
-{
- uint32 callid;
-
- SCVAL(q, 0, 5); q++; /* RPC version 5 */
- SCVAL(q, 0, 0); q++; /* minor version 0 */
- SCVAL(q, 0, 2); q++; /* RPC response packet */
- SCVAL(q, 0, 3); q++; /* first frag + last frag */
- RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */
- RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */
- SSVAL(q, 0, 0); q += 2; /* authentication length */
- callid = RIVAL(inbuf, 12);
- RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */
- SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */
- SSVAL(q, 0, 0); q += 2; /* presentation context identifier */
- SCVAL(q, 0, 0); q++; /* cancel count */
- SCVAL(q, 0, 0); q++; /* reserved */
-}
-
-/* this function is due to be replaced */
-static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen)
-{
- SSVAL(q, 8, datalen + 4);
- SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */
- SIVAL(q, datalen, rtnval);
- *rlen = datalen + 4;
- { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); }
-}
-
-/* RID username mapping function. just for fun, it maps to the unix uid */
-static uint32 name_to_rid(char *user_name)
-{
- struct passwd *pw = Get_Pwnam(user_name, False);
- if (!pw)
- {
- DEBUG(1,("Username %s is invalid on this system\n", user_name));
- return (uint32)(-1);
- }
-
- return (uint32)(pw->pw_uid);
-}
-
-
-/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
-char *dom_sid_to_string(DOM_SID *sid)
-{
- static pstring sidstr;
- char subauth[16];
- int i;
- uint32 ia = (sid->id_auth[0]) +
- (sid->id_auth[1] << 8 ) +
- (sid->id_auth[2] << 16) +
- (sid->id_auth[3] << 24);
-
- sprintf(sidstr, "S-%d-%d", sid->sid_no, ia);
-
- for (i = 0; i < sid->num_auths; i++)
- {
- sprintf(subauth, "-%d", sid->sub_auths[i]);
- strcat(sidstr, subauth);
- }
-
- DEBUG(5,("dom_sid_to_string returning %s\n", sidstr));
- return sidstr;
-}
-
-/* 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 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);
-
- sid->num_auths = 0;
-
- while ((p = strtok(0, "-")) != NULL)
- {
- sid->sub_auths[sid->num_auths++] = atoi(p);
- }
-}
-
-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 */
-}
-
-static int make_rpc_reply(char *inbuf, char *q, int data_len)
-{
- uint32 callid = RIVAL(inbuf, 12);
- RPC_HDR hdr;
-
- create_rpc_reply(&hdr, callid, data_len);
- return smb_io_rpc_hdr(False, &hdr, q, q, 4, 0) - q;
-}
-
-static int lsa_reply_open_policy(char *q, char *base)
+void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
{
+ const char *fname = NULL;
+ char *pipe_name = NULL;
+ smb_np_struct *p;
+ int size=0,fmode=0,mtime=0,rmode=0;
int i;
- LSA_R_OPEN_POL r_o;
-
- /* set up the LSA QUERY INFO response */
- /* bzero(&(r_o.pol.data), POL_HND_SIZE); */
- for (i = 0; i < POL_HND_SIZE; i++)
- {
- r_o.pol.data[i] = i;
+ TALLOC_CTX *ctx = talloc_tos();
+
+ /* XXXX we need to handle passed times, sattr and flags */
+ srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &pipe_name,
+ smb_buf(req->inbuf), STR_TERMINATE);
+ if (!pipe_name) {
+ reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ERRDOS, ERRbadpipe);
+ return;
}
- r_o.status = 0x0;
-
- /* store the response in the SMB stream */
- q = lsa_io_r_open_pol(False, &r_o, q, base, 4, 0);
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
-
-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;
-}
-
-static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
-{
- make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
- hdr->undoc_buffer = len > 0 ? 1 : 0;
-}
-
-static void make_unistr(UNISTR *str, char *buf)
-{
- /* store the string (null-terminated copy) */
- PutUniCode((char *)(str->buffer), buf);
-}
-
-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;
-
- /* store the string (null-terminated copy) */
- PutUniCode((char *)str->buffer, buf);
-
- /* overwrite the last character: some strings are terminated with 4 not 0 */
- str->buffer[len] = (uint16)terminate;
-}
-
-static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid)
-{
- rid2->type = 0x5;
- rid2->undoc = 0x5;
- rid2->rid = rid;
- rid2->rid_idx = 0;
-}
-
-static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str)
-{
- int len_sid_str = strlen(sid_str);
-
- sid2->type = 0x5;
- sid2->undoc = 0;
- make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0);
- make_unistr (&(sid2->str), sid_str);
-}
-
-static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
-{
- int domlen = strlen(dom_name);
-
- d_q->uni_dom_max_len = domlen * 2;
- d_q->padding = 0;
- d_q->uni_dom_str_len = domlen * 2;
-
- d_q->buffer_dom_name = 0; /* domain buffer pointer */
- d_q->buffer_dom_sid = 0; /* domain sid pointer */
-
- /* NOT null-terminated: 4-terminated instead! */
- make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4);
-
- make_dom_sid(&(d_q->dom_sid), dom_sid);
-}
-
-static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base,
- char *dom_name, char *dom_sid)
-{
- 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, 0);
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
-
-/* pretty much hard-coded choice of "other" sids, unfortunately... */
-static void make_dom_ref(DOM_R_REF *ref,
- char *dom_name, char *dom_sid,
- char *other_sid1, char *other_sid2, char *other_sid3)
-{
- int len_dom_name = strlen(dom_name);
- int len_other_sid1 = strlen(other_sid1);
- int len_other_sid2 = strlen(other_sid2);
- int len_other_sid3 = strlen(other_sid3);
- ref->undoc_buffer = 1;
- ref->num_ref_doms_1 = 4;
- ref->buffer_dom_name = 1;
- ref->max_entries = 32;
- ref->num_ref_doms_2 = 4;
-
- make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0);
- make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
- make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
- make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
-
- if (dom_name != NULL)
- {
- make_unistr(&(ref->uni_dom_name), dom_name);
+ /* 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 ) {
+ reply_doserror(req, ERRSRV, ERRaccess);
+ return;
}
- make_dom_sid(&(ref->ref_dom[0]), dom_sid );
- make_dom_sid(&(ref->ref_dom[1]), other_sid1);
- make_dom_sid(&(ref->ref_dom[2]), other_sid2);
- make_dom_sid(&(ref->ref_dom[3]), other_sid3);
-}
-
-static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
- int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
- char *dom_name, char *dom_sid,
- char *other_sid1, char *other_sid2, char *other_sid3)
-{
- int i;
-
- make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
- other_sid1, other_sid2, other_sid3);
+ DEBUG(4,("Opening pipe %s.\n", pipe_name));
- r_l->num_entries = num_entries;
- r_l->undoc_buffer = 1;
- r_l->num_entries2 = num_entries;
-
- for (i = 0; i < num_entries; i++)
- {
- make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
+ /* 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;
+ }
}
- r_l->num_entries3 = num_entries;
-}
-
-static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
- int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
- char *dom_name, char *dom_sid,
- char *other_sid1, char *other_sid2, char *other_sid3)
-{
- int i;
-
- make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
- other_sid1, other_sid2, other_sid3);
-
- r_l->num_entries = num_entries;
- r_l->undoc_buffer = 1;
- r_l->num_entries2 = num_entries;
-
- for (i = 0; i < num_entries; i++)
- {
- make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]);
+ if (pipe_names[i].client_pipe == NULL) {
+ reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ERRDOS, ERRbadpipe);
+ return;
}
- r_l->num_entries3 = num_entries;
-}
-
-static int lsa_reply_lookup_sids(char *q, char *base,
- int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS],
- char *dom_name, char *dom_sid,
- char *other_sid1, char *other_sid2, char *other_sid3)
-{
- LSA_R_LOOKUP_SIDS r_l;
-
- /* set up the LSA Lookup SIDs response */
- make_reply_lookup_sids(&r_l, num_entries, dom_sids,
- dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
- r_l.status = 0x0;
-
- /* store the response in the SMB stream */
- q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4, 0);
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
-
-static int lsa_reply_lookup_rids(char *q, char *base,
- int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
- char *dom_name, char *dom_sid,
- char *other_sid1, char *other_sid2, char *other_sid3)
-{
- LSA_R_LOOKUP_RIDS r_l;
-
- /* set up the LSA Lookup RIDs response */
- make_reply_lookup_rids(&r_l, num_entries, dom_rids,
- dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
- r_l.status = 0x0;
-
- /* store the response in the SMB stream */
- q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4, 0);
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
-
-static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c,
- DOM_CHAL *srv_chal, int status)
-{
- DEBUG(6,("make_lsa_r_req_chal: %d\n", __LINE__));
- memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
- r_c->status = status;
-}
-
-static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base,
- DOM_CHAL *srv_chal)
-{
- LSA_R_REQ_CHAL r_c;
-
- DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__));
-
- /* set up the LSA REQUEST CHALLENGE response */
- make_lsa_r_req_chal(&r_c, srv_chal, 0);
-
- /* store the response in the SMB stream */
- q = lsa_io_r_req_chal(False, &r_c, q, base, 4, 0);
-
- DEBUG(6,("lsa_reply_req_chal: %d\n", __LINE__));
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
-
-static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a,
- DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
-{
- memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
- memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs));
- r_a->status = status;
-}
-
-static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base,
- DOM_CHAL *resp_cred, int status)
-{
- LSA_R_AUTH_2 r_a;
-
- /* set up the LSA AUTH 2 response */
-
- make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
-
- /* store the response in the SMB stream */
- q = lsa_io_r_auth_2(False, &r_a, q, base, 4, 0);
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
+ /* Strip \PIPE\ off the name. */
+ fname = pipe_name + PIPELEN;
-static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a,
- DOM_CRED *srv_cred, int status)
-{
- memcpy(&(r_a->srv_cred), srv_cred, sizeof(r_a->srv_cred));
- r_a->status = status;
-}
-
-static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base,
- DOM_CRED *srv_cred, int status)
-{
- LSA_R_SRV_PWSET r_s;
-
- /* set up the LSA Server Password Set response */
- make_lsa_r_srv_pwset(&r_s, srv_cred, status);
-
- /* store the response in the SMB stream */
- q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4, 0);
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
-
-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,
-
- 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));
- }
- else
- {
- bzero(usr->sess_key, sizeof(usr->sess_key));
+#if 0
+ /*
+ * Hack for NT printers... JRA.
+ */
+ if(should_fail_next_srvsvc_open(fname)) {
+ reply_doserror(req, ERRSRV, ERRaccess);
+ return;
}
+#endif
- 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 */
-
- bzero(usr->padding, sizeof(usr->padding));
-
- 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);
+ /* 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));
- usr->num_groups2 = num_groups;
- for (i = 0; i < num_groups; i++)
- {
- usr->gids[i] = gids[i];
+ p = open_rpc_pipe_p(fname, conn, req->vuid);
+ if (!p) {
+ reply_doserror(req, ERRSRV, ERRnofids);
+ return;
}
- 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,
- DOM_CRED *srv_cred, LSA_USER_INFO *user_info)
-{
- 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 */
- memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
+ /* Prepare the reply */
+ reply_outbuf(req, 15, 0);
- /* 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, 0);
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
-
-
-static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base,
- DOM_CRED *srv_cred,
- uint32 status)
-{
- LSA_R_SAM_LOGOFF 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 */
- memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
-
- r_s.status = status;
-
- /* store the response in the SMB stream */
- q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4, 0);
-
- /* return length of SMB data stored */
- return PTR_DIFF(q, base);
-}
+ /* Mark the opened file as an existing named pipe in message mode. */
+ SSVAL(req->outbuf,smb_vwv9,2);
+ SSVAL(req->outbuf,smb_vwv10,0xc700);
+ if (rmode == 2) {
+ DEBUG(4,("Resetting open result to open from create.\n"));
+ rmode = 1;
+ }
-static void api_lsa_open_policy( char *param, char *data,
- char **rdata, int *rdata_len )
-{
- /* we might actually want to decode the query, but it's not necessary */
- /* lsa_io_q_open_policy(...); */
+ SSVAL(req->outbuf,smb_vwv2, p->pnum);
+ SSVAL(req->outbuf,smb_vwv3,fmode);
+ srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
+ SIVAL(req->outbuf,smb_vwv6,size);
+ SSVAL(req->outbuf,smb_vwv8,rmode);
+ SSVAL(req->outbuf,smb_vwv11,0x0001);
- /* return a 20 byte policy handle */
- *rdata_len = lsa_reply_open_policy(*rdata + 0x18, *rdata);
+ chain_reply(req);
+ return;
}
-static void api_lsa_query_info( char *param, char *data,
- char **rdata, int *rdata_len )
-{
- LSA_Q_QUERY_INFO q_i;
- pstring dom_name;
- pstring dom_sid;
-
- /* grab the info class and policy handle */
- lsa_io_q_query(True, &q_i, data + 0x18, data, 4, 0);
-
- pstrcpy(dom_name, lp_workgroup());
- pstrcpy(dom_sid , lp_domainsid());
-
- /* construct reply. return status is always 0x0 */
- *rdata_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata,
- dom_name, dom_sid);
-}
+/****************************************************************************
+ Reply to a write on a pipe.
+****************************************************************************/
-static void api_lsa_lookup_sids( char *param, char *data,
- char **rdata, int *rdata_len )
+void reply_pipe_write(struct smb_request *req)
{
- int i;
- LSA_Q_LOOKUP_SIDS q_l;
- pstring dom_name;
- pstring dom_sid;
- fstring dom_sids[MAX_LOOKUP_SIDS];
-
- /* grab the info class and policy handle */
- lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data, 4, 0);
-
- pstrcpy(dom_name, lp_workgroup());
- pstrcpy(dom_sid , lp_domainsid());
+ smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv0));
+ size_t numtowrite = SVAL(req->inbuf,smb_vwv1);
+ int nwritten;
+ char *data;
- /* convert received SIDs to strings, so we can do them. */
- for (i = 0; i < q_l.num_entries; i++)
- {
- fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i])));
+ if (!p) {
+ reply_doserror(req, ERRDOS, ERRbadfid);
+ return;
}
- /* construct reply. return status is always 0x0 */
- *rdata_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata,
- q_l.num_entries, dom_sids, /* text-converted SIDs */
- dom_name, dom_sid, /* domain name, domain SID */
- "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
-}
-
-static void api_lsa_lookup_names( char *param, char *data,
- char **rdata, int *rdata_len )
-{
- int i;
- LSA_Q_LOOKUP_RIDS q_l;
- pstring dom_name;
- pstring dom_sid;
- uint32 dom_rids[MAX_LOOKUP_SIDS];
-
- /* grab the info class and policy handle */
- lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data, 4, 0);
-
- pstrcpy(dom_name, lp_workgroup());
- pstrcpy(dom_sid , lp_domainsid());
-
- /* convert received RIDs to strings, so we can do them. */
- for (i = 0; i < q_l.num_entries; i++)
- {
- char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
- dom_rids[i] = name_to_rid(user_name);
+ if (p->vuid != req->vuid) {
+ reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ return;
}
- /* construct reply. return status is always 0x0 */
- *rdata_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata,
- q_l.num_entries, dom_rids, /* text-converted SIDs */
- dom_name, dom_sid, /* domain name, domain SID */
- "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
-}
-
-BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
-{
- uint16 opnum = SVAL(data,22);
+ data = smb_buf(req->inbuf) + 3;
- int pkttype = CVAL(data, 2);
- if (pkttype == 0x0b) /* RPC BIND */
- {
- DEBUG(4,("netlogon rpc bind %x\n",pkttype));
- LsarpcTNP1(data,rdata,rdata_len);
- return True;
+ if (numtowrite == 0) {
+ nwritten = 0;
+ } else {
+ nwritten = write_to_pipe(p, data, numtowrite);
}
- DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum));
- switch (opnum)
- {
- case LSA_OPENPOLICY:
- {
- DEBUG(3,("LSA_OPENPOLICY\n"));
- api_lsa_open_policy(param, data, rdata, rdata_len);
- make_rpc_reply(data, *rdata, *rdata_len);
- break;
- }
-
- case LSA_QUERYINFOPOLICY:
- {
- DEBUG(3,("LSA_QUERYINFOPOLICY\n"));
-
- api_lsa_query_info(param, data, rdata, rdata_len);
- make_rpc_reply(data, *rdata, *rdata_len);
- break;
- }
-
- case LSA_ENUMTRUSTDOM:
- {
- char *q = *rdata + 0x18;
-
- DEBUG(3,("LSA_ENUMTRUSTDOM\n"));
-
- initrpcreply(data, *rdata);
-
- SIVAL(q, 0, 0); /* enumeration context */
- SIVAL(q, 0, 4); /* entries read */
- SIVAL(q, 0, 8); /* trust information */
-
- endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len);
-
- break;
- }
-
- case LSA_CLOSE:
- {
- char *q = *rdata + 0x18;
-
- DEBUG(3,("LSA_CLOSE\n"));
-
- initrpcreply(data, *rdata);
-
- SIVAL(q, 0, 0);
- SIVAL(q, 0, 4);
- SIVAL(q, 0, 8);
- SIVAL(q, 0, 12);
- SIVAL(q, 0, 16);
-
- endrpcreply(data, *rdata, q-*rdata, 0, rdata_len);
-
- break;
- }
-
- case LSA_OPENSECRET:
- {
- char *q = *rdata + 0x18;
- DEBUG(3,("LSA_OPENSECRET\n"));
-
- initrpcreply(data, *rdata);
-
- SIVAL(q, 0, 0);
- SIVAL(q, 0, 4);
- SIVAL(q, 0, 8);
- SIVAL(q, 0, 12);
- SIVAL(q, 0, 16);
-
- endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len);
-
- break;
- }
+ if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
+ return;
+ }
- case LSA_LOOKUPSIDS:
- {
- DEBUG(3,("LSA_OPENSECRET\n"));
- api_lsa_lookup_sids(param, data, rdata, rdata_len);
- make_rpc_reply(data, *rdata, *rdata_len);
- break;
- }
+ reply_outbuf(req, 1, 0);
- case LSA_LOOKUPNAMES:
- {
- DEBUG(3,("LSA_LOOKUPNAMES\n"));
- api_lsa_lookup_names(param, data, rdata, rdata_len);
- make_rpc_reply(data, *rdata, *rdata_len);
- break;
- }
+ SSVAL(req->outbuf,smb_vwv0,nwritten);
+
+ DEBUG(3,("write-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));
- default:
- {
- DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum));
- break;
- }
- }
- return True;
+ return;
}
-static BOOL update_dcinfo(int cnum, uint16 vuid,
- struct dcinfo *dc, DOM_CHAL *clnt_chal, char *mach_acct)
-{
- struct smb_passwd *smb_pass;
- int i;
+/****************************************************************************
+ Reply to a write and X.
- unbecome_user();
- smb_pass = get_smbpwnam(mach_acct);
- become_user(cnum, vuid);
+ This code is basically stolen from reply_write_and_X with some
+ wrinkles to handle pipes.
+****************************************************************************/
- if (smb_pass != NULL)
- {
- memcpy(dc->md4pw, smb_pass->smb_nt_passwd, sizeof(dc->md4pw));
- DEBUG(5,("dc->md4pw(%d) :", sizeof(dc->md4pw)));
- dump_data(5, dc->md4pw, 16);
- }
- else
- {
- /* No such machine account. Should error out here, but we'll
- print and carry on */
- DEBUG(1,("No account in domain for %s\n", mach_acct));
- return False;
+void reply_pipe_write_and_X(struct smb_request *req)
+{
+ smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv2));
+ size_t numtowrite = SVAL(req->inbuf,smb_vwv10);
+ int nwritten = -1;
+ int smb_doff = SVAL(req->inbuf, smb_vwv11);
+ bool pipe_start_message_raw =
+ ((SVAL(req->inbuf, smb_vwv7)
+ & (PIPE_START_MESSAGE|PIPE_RAW_MODE))
+ == (PIPE_START_MESSAGE|PIPE_RAW_MODE));
+ char *data;
+
+ if (!p) {
+ reply_doserror(req, ERRDOS, ERRbadfid);
+ return;
}
- {
- char foo[16];
- for (i = 0; i < 16; i++) sprintf(foo+i*2,"%02x ", dc->md4pw[i]);
- DEBUG(4,("pass %s %s\n", mach_acct, foo));
+ if (p->vuid != req->vuid) {
+ reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ return;
}
- /* copy the client credentials */
- memcpy(dc->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data));
- memcpy(dc->clnt_cred.data, clnt_chal->data, sizeof(clnt_chal->data));
-
- /* create a server challenge for the client */
- /* PAXX: set these to random values. */
- /* lkcl: paul, you mentioned that it doesn't really matter much */
- for (i = 0; i < 8; i++)
- {
- dc->srv_chal.data[i] = 0xA5;
+ data = smb_base(req->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 ));
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
+ return;
+ }
+
+ data += 2;
+ numtowrite -= 2;
+ }
+ nwritten = write_to_pipe(p, data, numtowrite);
}
- /* from client / server challenges and md4 password, generate sess key */
- cred_session_key(&(dc->clnt_chal), &(dc->srv_chal),
- dc->md4pw, dc->sess_key);
-
- DEBUG(6,("update_dcinfo: %d\n", __LINE__));
-
- return True;
-}
-
-static void api_lsa_req_chal( int cnum, uint16 vuid,
- user_struct *vuser,
- char *param, char *data,
- char **rdata, int *rdata_len )
-{
- LSA_Q_REQ_CHAL q_r;
-
- fstring mach_acct;
-
- /* grab the challenge... */
- lsa_io_q_req_chal(True, &q_r, data + 0x18, data, 4, 0);
-
- fstrcpy(mach_acct, unistr2(q_r.uni_logon_clnt.buffer));
-
- strcat(mach_acct, "$");
-
- DEBUG(6,("q_r.clnt_chal.data(%d) :", sizeof(q_r.clnt_chal.data)));
- dump_data(6, q_r.clnt_chal.data, 8);
-
- update_dcinfo(cnum, vuid, &(vuser->dc), &(q_r.clnt_chal), mach_acct);
-
- /* construct reply. return status is always 0x0 */
- *rdata_len = lsa_reply_req_chal(&q_r, *rdata + 0x18, *rdata,
- &(vuser->dc.srv_chal));
-
-}
-
-static void api_lsa_auth_2( user_struct *vuser,
- char *param, char *data,
- char **rdata, int *rdata_len )
-{
- LSA_Q_AUTH_2 q_a;
-
- DOM_CHAL srv_chal;
- UTIME srv_time;
-
- srv_time.time = 0;
-
- /* grab the challenge... */
- lsa_io_q_auth_2(True, &q_a, data + 0x18, data, 4, 0);
-
- /* check that the client credentials are valid */
- cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
- &(vuser->dc.srv_cred), srv_time);
-
- /* create server credentials for inclusion in the reply */
- cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), srv_time, &srv_chal);
-
- /* construct reply. */
- *rdata_len = lsa_reply_auth_2(&q_a, *rdata + 0x18, *rdata,
- &srv_chal, 0x0);
-}
-
-
-static BOOL deal_with_credentials(user_struct *vuser,
- DOM_CRED *clnt_cred, DOM_CRED *srv_cred)
-{
- UTIME new_clnt_time;
-
- /* doesn't matter that server time is 0 */
- srv_cred->timestamp.time = 0;
-
- /* check that the client credentials are valid */
- if (cred_assert(&(clnt_cred->challenge), vuser->dc.sess_key,
- &(vuser->dc.srv_cred), clnt_cred->timestamp))
- {
- return False;
+ if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
+ reply_unixerror(req, ERRDOS,ERRnoaccess);
+ return;
}
- /* increment client time by one second */
- new_clnt_time.time = clnt_cred->timestamp.time + 1;
-
- /* create server credentials for inclusion in the reply */
- cred_create(vuser->dc.sess_key, &(vuser->dc.clnt_cred), new_clnt_time,
- &(srv_cred->challenge));
-
- /* update the client and server credentials, for use next time... */
- *(uint32*)(vuser->dc.srv_cred.data) = ( *(uint32*)(vuser->dc.clnt_cred.data) += new_clnt_time.time );
-
- return True;
-}
-
-static void api_lsa_srv_pwset( user_struct *vuser,
- char *param, char *data,
- char **rdata, int *rdata_len )
-{
- LSA_Q_SRV_PWSET q_a;
-
- DOM_CRED srv_cred;
-
- /* grab the challenge and encrypted password ... */
- lsa_io_q_srv_pwset(True, &q_a, data + 0x18, data, 4, 0);
-
- /* checks and updates credentials. creates reply credentials */
- deal_with_credentials(vuser, &(q_a.clnt_id.cred), &srv_cred);
-
- /* construct reply. always indicate failure. nt keeps going... */
- *rdata_len = lsa_reply_srv_pwset(&q_a, *rdata + 0x18, *rdata,
- &srv_cred,
- NT_STATUS_WRONG_PASSWORD|0xC000000);
-}
+ reply_outbuf(req, 6, 0);
+ nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
+ SSVAL(req->outbuf,smb_vwv2,nwritten);
+
+ DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));
-static void api_lsa_sam_logoff( user_struct *vuser,
- char *param, char *data,
- char **rdata, int *rdata_len )
-{
- LSA_Q_SAM_LOGOFF q_l;
-
- DOM_CRED srv_cred;
-
- /* grab the challenge... */
- lsa_io_q_sam_logoff(True, &q_l, data + 0x18, data, 4, 0);
-
- /* checks and updates credentials. creates reply credentials */
- deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_cred);
-
- /* construct reply. always indicate success */
- *rdata_len = lsa_reply_sam_logoff(&q_l, *rdata + 0x18, *rdata,
- &srv_cred,
- 0x0);
+ chain_reply(req);
}
+/****************************************************************************
+ Reply to a read and X.
+ This code is basically stolen from reply_read_and_X with some
+ wrinkles to handle pipes.
+****************************************************************************/
-static void api_lsa_sam_logon( user_struct *vuser,
- char *param, char *data,
- char **rdata, int *rdata_len )
+void reply_pipe_read_and_X(struct smb_request *req)
{
- LSA_Q_SAM_LOGON q_l;
- LSA_USER_INFO usr_info;
- LSA_USER_INFO *p_usr_info = NULL;
-
- DOM_CRED srv_creds;
-
- lsa_io_q_sam_logon(True, &q_l, data + 0x18, data, 4, 0);
-
- /* checks and updates credentials. creates reply credentials */
- deal_with_credentials(vuser, &(q_l.sam_id.client.cred), &srv_creds);
-
- if (vuser != NULL)
- {
- NTTIME dummy_time;
- pstring logon_script;
- pstring profile_path;
- pstring home_dir;
- pstring home_drive;
- pstring my_name;
- pstring my_workgroup;
- pstring dom_sid;
- pstring username;
- extern pstring myname;
-
- dummy_time.low = 0xffffffff;
- dummy_time.high = 0x7fffffff;
+ smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv2));
+ int smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
+ int smb_mincnt = SVAL(req->inbuf,smb_vwv6);
+ int nread = -1;
+ char *data;
+ bool unused;
- get_myname(myname, NULL);
-
- pstrcpy(logon_script, lp_logon_script());
- pstrcpy(profile_path, lp_logon_path ());
- pstrcpy(dom_sid , lp_domainsid ());
- pstrcpy(my_workgroup, lp_workgroup ());
-
- pstrcpy(username, unistr2(q_l.sam_id.client.login.uni_acct_name.buffer));
- pstrcpy(my_name , myname );
- strupper(my_name);
-
- pstrcpy(home_drive , "a:" );
-
-#if (defined(NETGROUP) && defined(AUTOMOUNT))
- pstrcpy(home_dir , vuser->home_share);
-#else
- pstrcpy(home_dir , "\\\\%L\\%U");
- standard_sub_basic(home_dir);
+ /* 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(req->inbuf,smb_vwv3);
#endif
- p_usr_info = &usr_info;
-
- make_lsa_user_info(p_usr_info,
-
- &dummy_time, /* logon_time */
- &dummy_time, /* logoff_time */
- &dummy_time, /* kickoff_time */
- &dummy_time, /* pass_last_set_time */
- &dummy_time, /* pass_can_change_time */
- &dummy_time, /* pass_must_change_time */
-
- username, /* user_name */
- vuser->real_name, /* full_name */
- logon_script, /* logon_script */
- profile_path, /* profile_path */
- home_dir, /* home_dir */
- home_drive, /* dir_drive */
-
- 0, /* logon_count */
- 0, /* bad_pw_count */
+ if (!p) {
+ reply_doserror(req, ERRDOS, ERRbadfid);
+ return;
+ }
- vuser->uid, /* uint32 user_id */
- vuser->gid, /* uint32 group_id */
- 0, /* uint32 num_groups */
- NULL, /* DOM_GID *gids */
- 0x20, /* uint32 user_flgs */
+ reply_outbuf(req, 12, smb_maxcnt);
- NULL, /* char sess_key[16] */
+ data = smb_buf(req->outbuf);
- my_name, /* char *logon_srv */
- my_workgroup, /* char *logon_dom */
+ nread = read_from_pipe(p, data, smb_maxcnt, &unused);
- dom_sid, /* char *dom_sid */
- NULL); /* char *other_sids */
+ if (nread < 0) {
+ reply_doserror(req, ERRDOS, ERRnoaccess);
+ return;
}
- *rdata_len = lsa_reply_sam_logon(&q_l, *rdata + 0x18, *rdata,
- &srv_creds, p_usr_info);
+ set_message((char *)req->outbuf, 12, nread, False);
+
+ SSVAL(req->outbuf,smb_vwv5,nread);
+ SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf));
+ SSVAL(smb_buf(req->outbuf),-2,nread);
+
+ DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n",
+ p->pnum, smb_mincnt, smb_maxcnt, nread));
+
+ chain_reply(req);
}
+/****************************************************************************
+ Reply to a close.
+****************************************************************************/
-BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len)
+void reply_pipe_close(connection_struct *conn, struct smb_request *req)
{
- uint16 opnum = SVAL(data,22);
- int pkttype = CVAL(data, 2);
+ smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv0));
- user_struct *vuser;
-
- if (pkttype == 0x0b) /* RPC BIND */
- {
- DEBUG(4,("netlogon rpc bind %x\n",pkttype));
- LsarpcTNP1(data,rdata,rdata_len);
- return True;
+ if (!p) {
+ reply_doserror(req, ERRDOS, ERRbadfid);
+ return;
}
- DEBUG(4,("netlogon TransactNamedPipe op %x\n",opnum));
-
- if ((vuser = get_valid_user_struct(uid)) == NULL) return False;
+ DEBUG(5,("reply_pipe_close: pnum:%x\n", p->pnum));
- DEBUG(3,("Username of UID %d is %s\n", vuser->uid, vuser->name));
-#if defined(NETGROUP) && defined(AUTOMOUNT)
- DEBUG(3,("HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
-#endif
-
- switch (opnum)
- {
- case LSA_REQCHAL:
- {
- DEBUG(3,("LSA_REQCHAL\n"));
- api_lsa_req_chal(cnum, uid, vuser, param, data, rdata, rdata_len);
- make_rpc_reply(data, *rdata, *rdata_len);
- break;
- }
-
- case LSA_AUTH2:
- {
- DEBUG(3,("LSA_AUTH2\n"));
- api_lsa_auth_2(vuser, param, data, rdata, rdata_len);
- make_rpc_reply(data, *rdata, *rdata_len);
- break;
- }
-
- case LSA_SRVPWSET:
- {
- DEBUG(3,("LSA_SRVPWSET\n"));
- api_lsa_srv_pwset(vuser, param, data, rdata, rdata_len);
- make_rpc_reply(data, *rdata, *rdata_len);
- break;
- }
-
- case LSA_SAMLOGON:
- {
- DEBUG(3,("LSA_SAMLOGON\n"));
- api_lsa_sam_logon(vuser, param, data, rdata, rdata_len);
- make_rpc_reply(data, *rdata, *rdata_len);
- break;
- }
-
- case LSA_SAMLOGOFF:
- {
- DEBUG(3,("LSA_SAMLOGOFF\n"));
- api_lsa_sam_logoff(vuser, param, data, rdata, rdata_len);
- break;
- }
-
- default:
- {
- DEBUG(4, ("**** netlogon, unknown code: %lx\n", opnum));
- break;
- }
+ if (!close_rpc_pipe_hnd(p)) {
+ reply_doserror(req, ERRDOS, ERRbadfid);
+ return;
}
+
+ /* TODO: REMOVE PIPE FROM DB */
- return True;
+ reply_outbuf(req, 0, 0);
+ return;
}
-
-#endif /* NTDOMAIN */