mirror of
https://github.com/samba-team/samba.git
synced 2025-01-08 21:18:16 +03:00
460 lines
14 KiB
C
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;
|
|
}
|
|
|
|
|
|
|