1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00
samba-mirror/source/rpc_client/ncacn_np_use.c
0001-01-01 00:00:00 +00:00

460 lines
14 KiB
C

/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB client generic functions
Copyright (C) Andrew Tridgell 1994-2000
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
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"
#include "rpc_parse.h"
#include "trans2.h"
extern int DEBUGLEVEL;
extern pstring global_myname;
struct ncacn_np_use
{
struct ncacn_np *cli;
uint32 num_users;
};
static struct ncacn_np_use **msrpcs = NULL;
static uint32 num_msrpcs = 0;
/****************************************************************************
terminate client connection
****************************************************************************/
static void ncacn_np_shutdown(struct ncacn_np *cli)
{
struct ntuser_creds usr;
BOOL closed;
if (cli != NULL)
{
if (cli->smb != NULL)
{
if (cli->smb->initialised)
{
/* cli_nt_session_close(cli->smb, cli->fnum); JERRY */
cli_nt_session_close(cli->smb);
}
create_ntc_from_cli_state(&usr, cli->smb);
cli_net_use_del(cli->smb->desthost, &usr, False, &closed);
}
}
}
static BOOL ncacn_np_establish_connection(struct ncacn_np *cli,
const char *srv_name,
const struct ntuser_creds *ntc,
const char *pipe_name,
BOOL reuse)
{
BOOL new_smb_conn;
cli->smb = cli_net_use_add(srv_name, ntc,
True, &new_smb_conn);
if (cli->smb == NULL)
{
return False;
}
/* if (!cli_nt_session_open(cli->smb, pipe_name, &cli->fnum)) by JERRY */
if (!cli_nt_session_open(cli->smb, (char *)pipe_name))
{
cli_net_use_del(srv_name, ntc, False, NULL);
return False;
}
fstrcpy(cli->pipe_name, pipe_name);
return True;
}
/****************************************************************************
terminate client connection
****************************************************************************/
static void ncacn_np_use_free(struct ncacn_np_use *cli)
{
if (cli->cli != NULL)
{
if (cli->cli->initialised)
{
ncacn_np_shutdown(cli->cli);
}
ZERO_STRUCTP(cli->cli);
free(cli->cli);
}
ZERO_STRUCTP(cli);
free(cli);
}
/****************************************************************************
add a client state to the array
****************************************************************************/
static struct ncacn_np_use *add_ncacn_np_to_array(uint32 * len,
struct ncacn_np_use
***array,
struct ncacn_np_use *cli)
{
int i;
/* traverse the list and try to find a previously
allocate spot that is not being used */
for (i = 0; i < num_msrpcs; i++)
{
if (msrpcs[i] == NULL)
{
/* found and empty spot to
store the cli pointer */
msrpcs[i] = cli;
return cli;
}
}
return (struct ncacn_np_use *)add_item_to_array(len,
(void ***)array,
(void *)cli);
}
/****************************************************************************
delete a client state
****************************************************************************/
BOOL ncacn_np_use_del(const char *srv_name, const char *pipe_name,
const vuser_key * key,
BOOL force_close, BOOL *connection_closed)
{
int i;
DEBUG(10, ("ncacn_np_net_use_del: %s. force close: %s ",
pipe_name, BOOLSTR(force_close)));
if (key != NULL)
{
DEBUG(10, ("[%d,%x]", key->pid, key->vuid));
}
DEBUG(10, ("\n"));
if (connection_closed != NULL)
{
*connection_closed = False;
}
if (strnequal("\\PIPE\\", pipe_name, 6))
{
pipe_name = &pipe_name[6];
}
if (strnequal("\\\\", srv_name, 2))
{
srv_name = &srv_name[2];
}
for (i = 0; i < num_msrpcs; i++)
{
char *ncacn_np_name = NULL;
char *ncacn_np_srv_name = NULL;
struct ncacn_np_use *c = msrpcs[i];
vuser_key k;
if (c == NULL || c->cli == NULL || c->cli->smb == NULL)
continue;
ncacn_np_name = c->cli->pipe_name;
ncacn_np_srv_name = c->cli->smb->desthost;
k = c->cli->smb->key;
DEBUG(10, ("use_del[%d]: %s %s %s %s [%d,%x]\n",
i, ncacn_np_name, ncacn_np_srv_name,
c->cli->smb->user_name,
c->cli->smb->domain, k.pid, k.vuid));
if (strnequal("\\PIPE\\", ncacn_np_name, 6))
{
ncacn_np_name = &ncacn_np_name[6];
}
if (!strequal(ncacn_np_name, pipe_name))
{
continue;
}
if (strnequal("\\\\", ncacn_np_srv_name, 2))
{
ncacn_np_srv_name = &ncacn_np_srv_name[2];
}
if (!strequal(ncacn_np_srv_name, srv_name))
{
continue;
}
if (key->pid != k.pid || key->vuid != k.vuid)
{
continue;
}
/* decrement number of users */
c->num_users--;
DEBUG(10, ("idx: %i num_users now: %d\n",
i, c->num_users));
if (force_close || c->num_users == 0)
{
ncacn_np_use_free(c);
msrpcs[i] = NULL;
if (connection_closed != NULL)
{
*connection_closed = True;
}
}
return True;
}
return False;
}
/****************************************************************************
find client state. server name, user name, domain name and password must all
match.
****************************************************************************/
static struct ncacn_np_use *ncacn_np_find(const char *srv_name,
const char *pipe_name,
const vuser_key * key,
const struct ntuser_creds
*usr_creds, BOOL reuse)
{
int i;
const char *sv_name = srv_name;
if (strnequal("\\PIPE\\", pipe_name, 6))
{
pipe_name = &pipe_name[6];
}
if (strnequal("\\\\", sv_name, 2))
{
sv_name = &sv_name[2];
}
if (usr_creds != NULL)
{
DEBUG(10, ("ncacn_np_find: %s %s %s",
srv_name, usr_creds->user_name, usr_creds->domain));
}
else
{
DEBUG(10,("ncacn_np_find: %s (no creds)\n", srv_name));
}
if (key != NULL)
{
DEBUG(10, ("[%d,%x]", key->pid, key->vuid));
}
DEBUG(10, ("\n"));
for (i = 0; i < num_msrpcs; i++)
{
char *ncacn_np_srv_name = NULL;
struct ncacn_np_use *c = msrpcs[i];
vuser_key k;
char *ncacn_np_name = NULL;
if (c == NULL || c->cli == NULL || c->cli->smb == NULL ||
c->cli->smb->fd == -1 ||
!c->cli->initialised)
{
continue;
}
ncacn_np_name = c->cli->pipe_name;
ncacn_np_srv_name = c->cli->smb->desthost;
k = c->cli->smb->key;
DEBUG(10, ("ncacn_np_find[%d]: %s %s %s %s [%d,%x]\n",
i, ncacn_np_name, ncacn_np_srv_name,
c->cli->smb->user_name,
c->cli->smb->domain, k.pid, k.vuid));
if (strnequal("\\\\", ncacn_np_srv_name, 2))
{
ncacn_np_srv_name = &ncacn_np_srv_name[2];
}
if (strnequal("\\PIPE\\", ncacn_np_name, 6))
{
ncacn_np_name = &ncacn_np_name[6];
}
if (!strequal(ncacn_np_name, pipe_name))
{
continue;
}
if (!strequal(ncacn_np_srv_name, sv_name))
{
continue;
}
if (key != NULL && (k.pid != key->pid || k.vuid != key->vuid))
{
continue;
}
if (usr_creds == NULL)
{
if (reuse)
{
return c;
}
else
{
continue;
}
}
if (!strequal
(usr_creds->user_name, c->cli->smb->user_name))
{
continue;
}
if (!reuse
&& !pwd_compare((struct pwd_info *)&usr_creds->pwd, &c->cli->smb->pwd))
{
DEBUG(100, ("password doesn't match\n"));
continue;
}
if (usr_creds->domain[0] == 0)
{
return c;
}
if (strequal(usr_creds->domain, c->cli->smb->domain))
{
return c;
}
}
return NULL;
}
/****************************************************************************
initialise a msrpcent structure
****************************************************************************/
struct ncacn_np *ncacn_np_initialise(struct ncacn_np *msrpc,
const vuser_key * key)
{
if (!msrpc)
{
msrpc = (struct ncacn_np *)malloc(sizeof(*msrpc));
if (!msrpc)
return NULL;
ZERO_STRUCTP(msrpc);
}
if (msrpc->initialised)
{
ncacn_np_shutdown(msrpc);
}
ZERO_STRUCTP(msrpc);
msrpc->fnum = -1;
msrpc->initialised = 1;
return msrpc;
}
/****************************************************************************
create a new client state from user credentials
****************************************************************************/
static struct ncacn_np_use *ncacn_np_use_get(const char *pipe_name,
const vuser_key * key)
{
struct ncacn_np_use *cli =
(struct ncacn_np_use *)malloc(sizeof(*cli));
if (cli == NULL)
{
return NULL;
}
memset(cli, 0, sizeof(*cli));
cli->cli = ncacn_np_initialise(NULL, key);
if (cli->cli == NULL)
{
return NULL;
}
return cli;
}
/****************************************************************************
init client state
****************************************************************************/
struct ncacn_np *ncacn_np_use_add(const char *pipe_name,
const vuser_key * key,
const char *srv_name,
const struct ntuser_creds *ntc,
BOOL reuse, BOOL *is_new_connection)
{
struct ncacn_np_use *cli;
DEBUG(10, ("ncacn_np_use_add: %s\n", pipe_name));
(*is_new_connection) = False;
cli = ncacn_np_find(srv_name, pipe_name, key, ntc, reuse);
if (cli != NULL)
{
cli->num_users++;
return cli->cli;
}
/*
* allocate
*/
(*is_new_connection) = True;
cli = ncacn_np_use_get(pipe_name, key);
if (!ncacn_np_establish_connection
(cli->cli, srv_name, ntc, pipe_name, True))
{
DEBUG(0, ("ncacn_np_use_add: connection failed\n"));
cli->cli = NULL;
ncacn_np_use_free(cli);
return NULL;
}
if (key != NULL)
{
cli->cli->smb->key = *key;
}
else
{
cli->cli->smb->key.pid = sys_getpid();
cli->cli->smb->key.vuid = UID_FIELD_INVALID;
}
add_ncacn_np_to_array(&num_msrpcs, &msrpcs, cli);
cli->num_users++;
return cli->cli;
}