mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
f296a8d087
- cleaned up some code
- Fixed a few memory leaks of my own making
- Add AddPrinterDriver(); I'm missing some of the semantics
here as the call is done correctly, but I'm not getting all
the information right in the DRIVER_INFO_3 struct I think.
Will work on it tomorrow some more...
--jerry
(This used to be commit 3bf9a29f34
)
404 lines
8.6 KiB
C
404 lines
8.6 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
SMB msrpcent generic functions
|
|
Copyright (C) Andrew Tridgell 1994-1999
|
|
Copyright (C) Luke Kenneth Casson Leighton 1996-1999
|
|
|
|
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
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
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.
|
|
*/
|
|
|
|
#define NO_SYSLOG
|
|
|
|
#include "includes.h"
|
|
|
|
extern int DEBUGLEVEL;
|
|
|
|
/****************************************************************************
|
|
read an msrpc pdu from a fd.
|
|
The timeout is in milliseconds.
|
|
****************************************************************************/
|
|
BOOL receive_msrpc(int fd, prs_struct *data, unsigned int timeout)
|
|
{
|
|
BOOL ok;
|
|
size_t len;
|
|
RPC_HDR hdr;
|
|
|
|
prs_init(data, 0, 4, NULL, True);
|
|
|
|
ok = prs_read(data, fd, 16, timeout);
|
|
|
|
if (!ok)
|
|
{
|
|
prs_mem_free(data);
|
|
return False;
|
|
}
|
|
|
|
if (!smb_io_rpc_hdr("hdr", &hdr, data, 0))
|
|
{
|
|
prs_mem_free(data);
|
|
return False;
|
|
}
|
|
|
|
len = hdr.frag_len - 16;
|
|
if (len > 0)
|
|
{
|
|
ok = prs_read(data, fd, hdr.frag_len, 0);
|
|
if (!ok)
|
|
{
|
|
prs_mem_free(data);
|
|
return False;
|
|
}
|
|
data->data_offset = hdr.frag_len;
|
|
return True;
|
|
}
|
|
|
|
prs_mem_free(data);
|
|
return False;
|
|
}
|
|
|
|
/****************************************************************************
|
|
send an smb to a fd and re-establish if necessary
|
|
****************************************************************************/
|
|
BOOL msrpc_send(int fd, prs_struct *ps)
|
|
{
|
|
size_t len = ps != NULL ? ps->buffer_size : 0;
|
|
size_t nwritten=0;
|
|
ssize_t ret;
|
|
char *outbuf = ps->data_p;
|
|
|
|
DEBUG(10,("msrpc_send_prs: data: %p len %d\n", outbuf, len));
|
|
dbgflush();
|
|
|
|
dump_data(10, outbuf, len);
|
|
|
|
while (nwritten < len)
|
|
{
|
|
ret = write_socket(fd,outbuf+nwritten,len - nwritten);
|
|
if (ret <= 0)
|
|
{
|
|
DEBUG(0,("Error writing %d msrpc bytes. %d.\n",
|
|
len,ret));
|
|
prs_mem_free(ps);
|
|
return False;
|
|
}
|
|
nwritten += ret;
|
|
}
|
|
|
|
prs_mem_free(ps);
|
|
return True;
|
|
}
|
|
|
|
/****************************************************************************
|
|
receive msrpc packet
|
|
****************************************************************************/
|
|
BOOL msrpc_receive(int fd, prs_struct *ps)
|
|
{
|
|
int len;
|
|
|
|
DEBUG(10,("msrpc_receive: %d\n", __LINE__));
|
|
|
|
if (!receive_msrpc(fd, ps, 0))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
len = ps->buffer_size;
|
|
|
|
if (ps->data_p == NULL || len <= 0)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
dump_data(10, ps->data_p, len);
|
|
|
|
DEBUG(10,("msrpc_receive: len %d\n", len));
|
|
|
|
return True;
|
|
}
|
|
|
|
/****************************************************************************
|
|
open the msrpcent sockets
|
|
****************************************************************************/
|
|
BOOL msrpc_connect(struct msrpc_state *msrpc, const char *pipe_name)
|
|
{
|
|
fstring path;
|
|
slprintf(path, sizeof(path)-1, "%s/.msrpc/%s", LOCKDIR, pipe_name);
|
|
|
|
fstrcpy(msrpc->pipe_name, pipe_name);
|
|
|
|
msrpc->fd = open_pipe_sock(path);
|
|
|
|
if (msrpc->fd == -1)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
initialise a msrpcent structure
|
|
****************************************************************************/
|
|
void msrpc_init_creds(struct msrpc_state *msrpc, const struct user_creds *usr)
|
|
{
|
|
copy_user_creds(&msrpc->usr, usr);
|
|
}
|
|
|
|
/****************************************************************************
|
|
close the socket descriptor
|
|
****************************************************************************/
|
|
void msrpc_close_socket(struct msrpc_state *msrpc)
|
|
{
|
|
if (msrpc->fd != -1)
|
|
{
|
|
close(msrpc->fd);
|
|
}
|
|
msrpc->fd = -1;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
set socket options on a open connection
|
|
****************************************************************************/
|
|
void msrpc_sockopt(struct msrpc_state *msrpc, char *options)
|
|
{
|
|
set_socket_options(msrpc->fd, options);
|
|
}
|
|
|
|
|
|
static BOOL msrpc_authenticate(struct msrpc_state *msrpc,
|
|
struct user_creds *usr)
|
|
{
|
|
struct msrpc_state msrpc_redir;
|
|
|
|
int sock = msrpc->fd;
|
|
char *data;
|
|
prs_struct ps;
|
|
uint32 len;
|
|
char *in = msrpc->inbuf;
|
|
char *out = msrpc->outbuf;
|
|
uint16 command;
|
|
|
|
command = usr != NULL ? AGENT_CMD_CON : AGENT_CMD_CON_ANON;
|
|
|
|
if (!create_user_creds(&ps, msrpc->pipe_name, 0x0, command,
|
|
msrpc->pid, usr))
|
|
{
|
|
DEBUG(0,("could not parse credentials\n"));
|
|
close(sock);
|
|
return False;
|
|
}
|
|
|
|
len = ps.data_offset;
|
|
data = ps.data_p;
|
|
|
|
SIVAL(data, 0, len);
|
|
|
|
#ifdef DEBUG_PASSWORD
|
|
DEBUG(100,("data len: %d\n", len));
|
|
dump_data(100, data, len);
|
|
#endif
|
|
|
|
if (write(sock, data, len) <= 0)
|
|
{
|
|
DEBUG(0,("write failed\n"));
|
|
return False;
|
|
}
|
|
|
|
if (msrpc->redirect)
|
|
{
|
|
len = read(sock, &msrpc_redir, sizeof(msrpc_redir));
|
|
|
|
if (len != sizeof(msrpc_redir))
|
|
{
|
|
DEBUG(0,("read failed\n"));
|
|
return False;
|
|
}
|
|
|
|
memcpy(msrpc, &msrpc_redir, sizeof(msrpc_redir));
|
|
msrpc->inbuf = in;
|
|
msrpc->outbuf = out;
|
|
msrpc->fd = sock;
|
|
msrpc->usr.reuse = False;
|
|
}
|
|
else
|
|
{
|
|
uint32 status;
|
|
len = read(sock, &status, sizeof(status));
|
|
|
|
return len == sizeof(status) && status == 0x0;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
static BOOL msrpc_init_redirect(struct msrpc_state *msrpc,
|
|
const char* pipe_name,
|
|
struct user_creds *usr)
|
|
{
|
|
int sock;
|
|
fstring path;
|
|
|
|
slprintf(path, sizeof(path)-1, "/tmp/.msrpc/.%s/agent", pipe_name);
|
|
|
|
sock = open_pipe_sock(path);
|
|
|
|
if (sock < 0)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
msrpc->fd = sock;
|
|
|
|
if (!msrpc_authenticate(msrpc, usr))
|
|
{
|
|
DEBUG(0,("authenticate failed\n"));
|
|
close(msrpc->fd);
|
|
msrpc->fd = -1;
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
BOOL msrpc_connect_auth(struct msrpc_state *msrpc,
|
|
uint32 pid,
|
|
const char* pipename,
|
|
const struct user_creds *usr)
|
|
{
|
|
ZERO_STRUCTP(msrpc);
|
|
if (!msrpc_initialise(msrpc, pid))
|
|
{
|
|
DEBUG(0,("unable to initialise msrpcent connection.\n"));
|
|
return False;
|
|
}
|
|
|
|
msrpc_init_creds(msrpc, usr);
|
|
|
|
if (!msrpc_establish_connection(msrpc, pipename))
|
|
{
|
|
msrpc_shutdown(msrpc);
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/****************************************************************************
|
|
initialise a msrpcent structure
|
|
****************************************************************************/
|
|
struct msrpc_state *msrpc_initialise(struct msrpc_state *msrpc, uint32 pid)
|
|
{
|
|
if (!msrpc) {
|
|
msrpc = (struct msrpc_state *)malloc(sizeof(*msrpc));
|
|
if (!msrpc)
|
|
return NULL;
|
|
ZERO_STRUCTP(msrpc);
|
|
}
|
|
|
|
if (msrpc->initialised) {
|
|
msrpc_shutdown(msrpc);
|
|
}
|
|
|
|
ZERO_STRUCTP(msrpc);
|
|
|
|
msrpc->fd = -1;
|
|
msrpc->outbuf = (char *)malloc(CLI_BUFFER_SIZE+4);
|
|
msrpc->inbuf = (char *)malloc(CLI_BUFFER_SIZE+4);
|
|
if (!msrpc->outbuf || !msrpc->inbuf)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
msrpc->initialised = 1;
|
|
msrpc_init_creds(msrpc, NULL);
|
|
msrpc->pid = pid;
|
|
|
|
return msrpc;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
shutdown a msrpcent structure
|
|
****************************************************************************/
|
|
void msrpc_shutdown(struct msrpc_state *msrpc)
|
|
{
|
|
DEBUG(10,("msrpc_shutdown\n"));
|
|
if (msrpc->outbuf)
|
|
{
|
|
free(msrpc->outbuf);
|
|
}
|
|
if (msrpc->inbuf)
|
|
{
|
|
free(msrpc->inbuf);
|
|
}
|
|
msrpc_close_socket(msrpc);
|
|
memset(msrpc, 0, sizeof(*msrpc));
|
|
}
|
|
|
|
/****************************************************************************
|
|
establishes a connection right up to doing tconX, reading in a password.
|
|
****************************************************************************/
|
|
BOOL msrpc_establish_connection(struct msrpc_state *msrpc,
|
|
const char *pipe_name)
|
|
{
|
|
DEBUG(5,("msrpc_establish_connection: connecting to %s (%s) - %s\n",
|
|
pipe_name,
|
|
msrpc->usr.ntc.user_name, msrpc->usr.ntc.domain));
|
|
|
|
/* establish connection */
|
|
|
|
if ((!msrpc->initialised))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
if (msrpc->fd == -1 && msrpc->redirect)
|
|
{
|
|
if (msrpc_init_redirect(msrpc, pipe_name, &msrpc->usr))
|
|
{
|
|
DEBUG(10,("msrpc_establish_connection: redirected OK\n"));
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
DEBUG(10,("redirect FAILED\n"));
|
|
return False;
|
|
}
|
|
}
|
|
if (msrpc->fd == -1)
|
|
{
|
|
if (!msrpc_connect(msrpc, pipe_name))
|
|
{
|
|
DEBUG(1,("msrpc_establish_connection: failed %s)\n",
|
|
pipe_name));
|
|
|
|
return False;
|
|
}
|
|
}
|
|
|
|
if (!msrpc_authenticate(msrpc, &msrpc->usr))
|
|
{
|
|
DEBUG(0,("authenticate failed\n"));
|
|
close(msrpc->fd);
|
|
msrpc->fd = -1;
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|