1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-05 12:22:11 +03:00

s3:libsmb: change cli_full_connection_send/recv into cli_full_connection_creds_send/recv

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Stefan Metzmacher
2016-10-26 13:48:58 +02:00
committed by Andreas Schneider
parent 879c291363
commit 3c67855c2b
3 changed files with 162 additions and 91 deletions

View File

@ -2830,72 +2830,86 @@ fail:
@param port (optional) The destination port (0 for default) @param port (optional) The destination port (0 for default)
@param service (optional) The share to make the connection to. Should be 'unqualified' in any way. @param service (optional) The share to make the connection to. Should be 'unqualified' in any way.
@param service_type The 'type' of serivice. @param service_type The 'type' of serivice.
@param user Username, unix string @param creds The used user credentials
@param domain User's domain
@param password User's password, unencrypted unix string.
*/ */
struct cli_full_connection_state { struct cli_full_connection_creds_state {
struct tevent_context *ev; struct tevent_context *ev;
const char *service; const char *service;
const char *service_type; const char *service_type;
const char *user; struct cli_credentials *creds;
const char *domain;
const char *password;
int pw_len;
int flags; int flags;
struct cli_state *cli; struct cli_state *cli;
}; };
static int cli_full_connection_state_destructor( static int cli_full_connection_creds_state_destructor(
struct cli_full_connection_state *s); struct cli_full_connection_creds_state *s);
static void cli_full_connection_started(struct tevent_req *subreq); static void cli_full_connection_creds_started(struct tevent_req *subreq);
static void cli_full_connection_sess_set_up(struct tevent_req *subreq); static void cli_full_connection_creds_sess_set_up(struct tevent_req *subreq);
static void cli_full_connection_done(struct tevent_req *subreq); static void cli_full_connection_creds_done(struct tevent_req *subreq);
struct tevent_req *cli_full_connection_send( struct tevent_req *cli_full_connection_creds_send(
TALLOC_CTX *mem_ctx, struct tevent_context *ev, TALLOC_CTX *mem_ctx, struct tevent_context *ev,
const char *my_name, const char *dest_host, const char *my_name, const char *dest_host,
const struct sockaddr_storage *dest_ss, int port, const struct sockaddr_storage *dest_ss, int port,
const char *service, const char *service_type, const char *service, const char *service_type,
const char *user, const char *domain, struct cli_credentials *creds,
const char *password, int flags, int signing_state) int flags, int signing_state)
{ {
struct tevent_req *req, *subreq; struct tevent_req *req, *subreq;
struct cli_full_connection_state *state; struct cli_full_connection_creds_state *state;
enum credentials_use_kerberos krb5_state;
uint32_t gensec_features = 0;
req = tevent_req_create(mem_ctx, &state, req = tevent_req_create(mem_ctx, &state,
struct cli_full_connection_state); struct cli_full_connection_creds_state);
if (req == NULL) { if (req == NULL) {
return NULL; return NULL;
} }
talloc_set_destructor(state, cli_full_connection_state_destructor); talloc_set_destructor(state, cli_full_connection_creds_state_destructor);
flags &= ~CLI_FULL_CONNECTION_USE_KERBEROS;
flags &= ~CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
flags &= ~CLI_FULL_CONNECTION_USE_CCACHE;
flags &= ~CLI_FULL_CONNECTION_USE_NT_HASH;
krb5_state = cli_credentials_get_kerberos_state(creds);
switch (krb5_state) {
case CRED_MUST_USE_KERBEROS:
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
flags &= ~CLI_FULL_CONNECTION_DONT_SPNEGO;
break;
case CRED_AUTO_USE_KERBEROS:
flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
break;
case CRED_DONT_USE_KERBEROS:
break;
}
gensec_features = cli_credentials_get_gensec_features(creds);
if (gensec_features & GENSEC_FEATURE_NTLM_CCACHE) {
flags |= CLI_FULL_CONNECTION_USE_CCACHE;
}
state->ev = ev; state->ev = ev;
state->service = service; state->service = service;
state->service_type = service_type; state->service_type = service_type;
state->user = user; state->creds = creds;
state->domain = domain;
state->password = password;
state->flags = flags; state->flags = flags;
state->pw_len = state->password ? strlen(state->password)+1 : 0;
if (state->password == NULL) {
state->password = "";
}
subreq = cli_start_connection_send( subreq = cli_start_connection_send(
state, ev, my_name, dest_host, dest_ss, port, state, ev, my_name, dest_host, dest_ss, port,
signing_state, flags); signing_state, flags);
if (tevent_req_nomem(subreq, req)) { if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev); return tevent_req_post(req, ev);
} }
tevent_req_set_callback(subreq, cli_full_connection_started, req); tevent_req_set_callback(subreq, cli_full_connection_creds_started, req);
return req; return req;
} }
static int cli_full_connection_state_destructor( static int cli_full_connection_creds_state_destructor(
struct cli_full_connection_state *s) struct cli_full_connection_creds_state *s)
{ {
if (s->cli != NULL) { if (s->cli != NULL) {
cli_shutdown(s->cli); cli_shutdown(s->cli);
@ -2904,14 +2918,13 @@ static int cli_full_connection_state_destructor(
return 0; return 0;
} }
static void cli_full_connection_started(struct tevent_req *subreq) static void cli_full_connection_creds_started(struct tevent_req *subreq)
{ {
struct tevent_req *req = tevent_req_callback_data( struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req); subreq, struct tevent_req);
struct cli_full_connection_state *state = tevent_req_data( struct cli_full_connection_creds_state *state = tevent_req_data(
req, struct cli_full_connection_state); req, struct cli_full_connection_creds_state);
NTSTATUS status; NTSTATUS status;
struct cli_credentials *creds = NULL;
status = cli_start_connection_recv(subreq, &state->cli); status = cli_start_connection_recv(subreq, &state->cli);
TALLOC_FREE(subreq); TALLOC_FREE(subreq);
@ -2919,33 +2932,20 @@ static void cli_full_connection_started(struct tevent_req *subreq)
return; return;
} }
creds = cli_session_creds_init(state,
state->user,
state->domain,
NULL, /* realm (use default) */
state->password,
state->cli->use_kerberos,
state->cli->fallback_after_kerberos,
state->cli->use_ccache,
state->cli->pw_nt_hash);
if (tevent_req_nomem(creds, req)) {
return;
}
subreq = cli_session_setup_creds_send( subreq = cli_session_setup_creds_send(
state, state->ev, state->cli, creds); state, state->ev, state->cli, state->creds);
if (tevent_req_nomem(subreq, req)) { if (tevent_req_nomem(subreq, req)) {
return; return;
} }
tevent_req_set_callback(subreq, cli_full_connection_sess_set_up, req); tevent_req_set_callback(subreq, cli_full_connection_creds_sess_set_up, req);
} }
static void cli_full_connection_sess_set_up(struct tevent_req *subreq) static void cli_full_connection_creds_sess_set_up(struct tevent_req *subreq)
{ {
struct tevent_req *req = tevent_req_callback_data( struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req); subreq, struct tevent_req);
struct cli_full_connection_state *state = tevent_req_data( struct cli_full_connection_creds_state *state = tevent_req_data(
req, struct cli_full_connection_state); req, struct cli_full_connection_creds_state);
NTSTATUS status; NTSTATUS status;
status = cli_session_setup_creds_recv(subreq); status = cli_session_setup_creds_recv(subreq);
@ -2953,22 +2953,21 @@ static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
if (!NT_STATUS_IS_OK(status) && if (!NT_STATUS_IS_OK(status) &&
(state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) { (state->flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
struct cli_credentials *creds = NULL;
state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK; state->flags &= ~CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK;
creds = cli_credentials_init_anon(state); state->creds = cli_credentials_init_anon(state);
if (tevent_req_nomem(creds, req)) { if (tevent_req_nomem(state->creds, req)) {
return; return;
} }
subreq = cli_session_setup_creds_send( subreq = cli_session_setup_creds_send(
state, state->ev, state->cli, creds); state, state->ev, state->cli, state->creds);
if (tevent_req_nomem(subreq, req)) { if (tevent_req_nomem(subreq, req)) {
return; return;
} }
tevent_req_set_callback( tevent_req_set_callback(
subreq, cli_full_connection_sess_set_up, req); subreq, cli_full_connection_creds_sess_set_up, req);
return; return;
} }
@ -2977,21 +2976,28 @@ static void cli_full_connection_sess_set_up(struct tevent_req *subreq)
} }
if (state->service != NULL) { if (state->service != NULL) {
const char *password = cli_credentials_get_password(state->creds);
int pw_len = password ? strlen(password)+1 : 0;
if (password == NULL) {
password = "";
}
subreq = cli_tree_connect_send( subreq = cli_tree_connect_send(
state, state->ev, state->cli, state, state->ev, state->cli,
state->service, state->service_type, state->service, state->service_type,
state->password, state->pw_len); password, pw_len);
if (tevent_req_nomem(subreq, req)) { if (tevent_req_nomem(subreq, req)) {
return; return;
} }
tevent_req_set_callback(subreq, cli_full_connection_done, req); tevent_req_set_callback(subreq, cli_full_connection_creds_done, req);
return; return;
} }
tevent_req_done(req); tevent_req_done(req);
} }
static void cli_full_connection_done(struct tevent_req *subreq) static void cli_full_connection_creds_done(struct tevent_req *subreq)
{ {
struct tevent_req *req = tevent_req_callback_data( struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req); subreq, struct tevent_req);
@ -3006,11 +3012,11 @@ static void cli_full_connection_done(struct tevent_req *subreq)
tevent_req_done(req); tevent_req_done(req);
} }
NTSTATUS cli_full_connection_recv(struct tevent_req *req, NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
struct cli_state **output_cli) struct cli_state **output_cli)
{ {
struct cli_full_connection_state *state = tevent_req_data( struct cli_full_connection_creds_state *state = tevent_req_data(
req, struct cli_full_connection_state); req, struct cli_full_connection_creds_state);
NTSTATUS status; NTSTATUS status;
if (tevent_req_is_nterror(req, &status)) { if (tevent_req_is_nterror(req, &status)) {
@ -3021,6 +3027,38 @@ NTSTATUS cli_full_connection_recv(struct tevent_req *req,
return NT_STATUS_OK; return NT_STATUS_OK;
} }
NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
const char *my_name,
const char *dest_host,
const struct sockaddr_storage *dest_ss, int port,
const char *service, const char *service_type,
struct cli_credentials *creds,
int flags,
int signing_state)
{
struct tevent_context *ev;
struct tevent_req *req;
NTSTATUS status = NT_STATUS_NO_MEMORY;
ev = samba_tevent_context_init(talloc_tos());
if (ev == NULL) {
goto fail;
}
req = cli_full_connection_creds_send(
ev, ev, my_name, dest_host, dest_ss, port, service,
service_type, creds, flags, signing_state);
if (req == NULL) {
goto fail;
}
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
goto fail;
}
status = cli_full_connection_creds_recv(req, output_cli);
fail:
TALLOC_FREE(ev);
return status;
}
NTSTATUS cli_full_connection(struct cli_state **output_cli, NTSTATUS cli_full_connection(struct cli_state **output_cli,
const char *my_name, const char *my_name,
const char *dest_host, const char *dest_host,
@ -3030,29 +3068,57 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
const char *password, int flags, const char *password, int flags,
int signing_state) int signing_state)
{ {
struct tevent_context *ev; TALLOC_CTX *frame = talloc_stackframe();
struct tevent_req *req; NTSTATUS status;
NTSTATUS status = NT_STATUS_NO_MEMORY; bool use_kerberos = false;
bool fallback_after_kerberos = false;
bool use_ccache = false;
bool pw_nt_hash = false;
struct cli_credentials *creds = NULL;
ev = samba_tevent_context_init(talloc_tos()); if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
if (ev == NULL) { use_kerberos = true;
goto fail;
} }
req = cli_full_connection_send(
ev, ev, my_name, dest_host, dest_ss, port, service, if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
service_type, user, domain, password, flags, signing_state); fallback_after_kerberos = true;
if (req == NULL) {
goto fail;
} }
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
goto fail; if (flags & CLI_FULL_CONNECTION_USE_CCACHE) {
use_ccache = true;
} }
status = cli_full_connection_recv(req, output_cli);
fail: if (flags & CLI_FULL_CONNECTION_USE_NT_HASH) {
TALLOC_FREE(ev); pw_nt_hash = true;
}
creds = cli_session_creds_init(frame,
user,
domain,
NULL, /* realm (use default) */
password,
use_kerberos,
fallback_after_kerberos,
use_ccache,
pw_nt_hash);
if (creds == NULL) {
TALLOC_FREE(frame);
return NT_STATUS_NO_MEMORY;
}
status = cli_full_connection_creds(output_cli, my_name,
dest_host, dest_ss, port,
service, service_type,
creds, flags, signing_state);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(frame);
return status; return status;
} }
TALLOC_FREE(frame);
return NT_STATUS_OK;
}
/**************************************************************************** /****************************************************************************
Send an old style tcon. Send an old style tcon.
****************************************************************************/ ****************************************************************************/

View File

@ -89,15 +89,23 @@ NTSTATUS cli_start_connection(struct cli_state **output_cli,
const char *dest_host, const char *dest_host,
const struct sockaddr_storage *dest_ss, int port, const struct sockaddr_storage *dest_ss, int port,
int signing_state, int flags); int signing_state, int flags);
struct tevent_req *cli_full_connection_send( struct tevent_req *cli_full_connection_creds_send(
TALLOC_CTX *mem_ctx, struct tevent_context *ev, TALLOC_CTX *mem_ctx, struct tevent_context *ev,
const char *my_name, const char *dest_host, const char *my_name, const char *dest_host,
const struct sockaddr_storage *dest_ss, int port, const struct sockaddr_storage *dest_ss, int port,
const char *service, const char *service_type, const char *service, const char *service_type,
const char *user, const char *domain, struct cli_credentials *creds,
const char *password, int flags, int signing_state); int flags, int signing_state);
NTSTATUS cli_full_connection_recv(struct tevent_req *req, NTSTATUS cli_full_connection_creds_recv(struct tevent_req *req,
struct cli_state **output_cli); struct cli_state **output_cli);
NTSTATUS cli_full_connection_creds(struct cli_state **output_cli,
const char *my_name,
const char *dest_host,
const struct sockaddr_storage *dest_ss, int port,
const char *service, const char *service_type,
struct cli_credentials *creds,
int flags,
int signing_state);
NTSTATUS cli_full_connection(struct cli_state **output_cli, NTSTATUS cli_full_connection(struct cli_state **output_cli,
const char *my_name, const char *my_name,
const char *dest_host, const char *dest_host,

View File

@ -442,16 +442,13 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
cli_creds = PyCredentials_AsCliCredentials(creds); cli_creds = PyCredentials_AsCliCredentials(creds);
} }
req = cli_full_connection_send( req = cli_full_connection_creds_send(
NULL, self->ev, "myname", host, NULL, 0, share, "?????", NULL, self->ev, "myname", host, NULL, 0, share, "?????",
cli_credentials_get_username(cli_creds), cli_creds, 0, 0);
cli_credentials_get_domain(cli_creds),
cli_credentials_get_password(cli_creds),
0, 0);
if (!py_tevent_req_wait_exc(self->ev, req)) { if (!py_tevent_req_wait_exc(self->ev, req)) {
return -1; return -1;
} }
status = cli_full_connection_recv(req, &self->cli); status = cli_full_connection_creds_recv(req, &self->cli);
TALLOC_FREE(req); TALLOC_FREE(req);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {