* Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
* Copyright (C) Paul Ashton 1998.
* Copyright (C) Jeremy Allison 1999.
+ * Copyright (C) Andrew Bartlett 2003.
*
* 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
extern struct pipe_id_info pipe_names[];
-static void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level)
+/* convert pipe auth flags into the RPC auth type and level */
+
+void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level)
{
*auth_type = 0;
*auth_level = 0;
RPC_HDR_AUTH rhdr_auth;
+ char *dp = prs_data_p(rdata) + fragment_start + len -
+ RPC_HDR_AUTH_LEN - auth_len;
+ prs_struct auth_verf;
+
*pauth_padding_len = 0;
if (auth_len == 0) {
BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SIGN),
BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SEAL)));
- {
- int auth_type;
- int auth_level;
- char *dp = prs_data_p(rdata) + fragment_start + len -
- RPC_HDR_AUTH_LEN - auth_len;
- prs_struct auth_verf;
-
- if (dp - prs_data_p(rdata) > prs_data_size(rdata)) {
- DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n"));
- return False;
- }
-
- DEBUG(10,("rpc_auth_pipe: packet:\n"));
- dump_data(100, dp, auth_len);
-
- prs_init(&auth_verf, RPC_HDR_AUTH_LEN, cli->mem_ctx, UNMARSHALL);
-
- /* The endinness must be preserved. JRA. */
- prs_set_endian_data( &auth_verf, rdata->bigendian_data);
+ if (dp - prs_data_p(rdata) > prs_data_size(rdata)) {
+ DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n"));
+ return False;
+ }
- prs_copy_data_in(&auth_verf, dp, RPC_HDR_AUTH_LEN);
- prs_set_offset(&auth_verf, 0);
+ DEBUG(10,("rpc_auth_pipe: packet:\n"));
+ dump_data(100, dp, auth_len);
+ prs_init(&auth_verf, 0, cli->mem_ctx, UNMARSHALL);
+
+ /* The endinness must be preserved. JRA. */
+ prs_set_endian_data( &auth_verf, rdata->bigendian_data);
+
+ /* Point this new parse struct at the auth section of the main
+ parse struct - rather than copying it. Avoids needing to
+ free it on every error
+ */
+ prs_give_memory(&auth_verf, dp, RPC_HDR_AUTH_LEN + auth_len, False /* not dynamic */);
+ prs_set_offset(&auth_verf, 0);
+ {
+ int auth_type;
+ int auth_level;
if (!smb_io_rpc_hdr_auth("auth_hdr", &rhdr_auth, &auth_verf, 0)) {
DEBUG(0, ("rpc_auth_pipe: Could not parse auth header\n"));
return False;
if (pkt_type == RPC_BINDACK) {
if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
- char *dp = prs_data_p(rdata) + len - auth_len;
-
- if(dp - prs_data_p(rdata) > prs_data_size(rdata)) {
- DEBUG(0,("rpc_auth_pipe: auth data > data size !\n"));
- return False;
- }
-
+ /* copy the next auth_len bytes into a buffer for
+ later use */
+
+ DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len);
+ BOOL store_ok;
+
/* save the reply away, for use a little later */
- return (NT_STATUS_IS_OK(ntlmssp_client_store_response(cli->ntlmssp_pipe_state,
- data_blob(dp, auth_len))));
- }
- if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
- /* nothing to do here - we don't seem to be able to validate the
- bindack based on VL's comments */
+ prs_copy_data_out((char *)ntlmssp_verf.data, &auth_verf, auth_len);
+
+ store_ok = (NT_STATUS_IS_OK(ntlmssp_store_response(cli->ntlmssp_pipe_state,
+ ntlmssp_verf)));
+
+ data_blob_free(&ntlmssp_verf);
+ return store_ok;
+ }
+ else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
+ /* nothing to do here - we don't seem to be able to
+ validate the bindack based on VL's comments */
return True;
}
}
DATA_BLOB sig;
if ((cli->pipe_auth_flags & AUTH_PIPE_SIGN) ||
(cli->pipe_auth_flags & AUTH_PIPE_SEAL)) {
- char *dp = prs_data_p(rdata) + len - auth_len;
-
- if(dp - prs_data_p(rdata) > prs_data_size(rdata)) {
- DEBUG(0,("rpc_auth_pipe: auth data > data size !\n"));
- return False;
- }
-
if (auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) {
DEBUG(0,("rpc_auth_pipe: wrong ntlmssp auth len %d\n", auth_len));
return False;
}
-
- sig = data_blob(dp, auth_len);
+ sig = data_blob(NULL, auth_len);
+ prs_copy_data_out((char *)sig.data, &auth_verf, auth_len);
}
/*
DEBUG(1, ("Can't unseal - data_len < 0!!\n"));
return False;
}
- nt_status = ntlmssp_client_unseal_packet(cli->ntlmssp_pipe_state,
- reply_data, data_len,
- &sig);
+ nt_status = ntlmssp_unseal_packet(cli->ntlmssp_pipe_state,
+ (unsigned char *)reply_data, data_len,
+ &sig);
}
else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
- nt_status = ntlmssp_client_check_packet(cli->ntlmssp_pipe_state,
- reply_data, data_len,
+ nt_status = ntlmssp_check_packet(cli->ntlmssp_pipe_state,
+ (const unsigned char *)reply_data, data_len,
&sig);
}
if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
RPC_AUTH_NETSEC_CHK chk;
- prs_struct netsec_verf;
-
- char *dp = prs_data_p(rdata) + fragment_start + len - auth_len;
-
- if(dp - prs_data_p(rdata) > prs_data_size(rdata)) {
- DEBUG(0,("rpc_auth_pipe: auth data > data size !\n"));
- return False;
- }
if (auth_len != RPC_AUTH_NETSEC_CHK_LEN) {
DEBUG(0,("rpc_auth_pipe: wrong schannel auth len %d\n", auth_len));
return False;
}
- prs_init(&netsec_verf, RPC_AUTH_NETSEC_CHK_LEN,
- cli->mem_ctx, UNMARSHALL);
-
- /* The endinness must be preserved. JRA. */
- prs_set_endian_data( &netsec_verf, rdata->bigendian_data);
-
- prs_copy_data_in(&netsec_verf, dp, auth_len);
- prs_set_offset(&netsec_verf, 0);
-
if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign",
- &chk, &netsec_verf, 0)) {
+ &chk, &auth_verf, 0)) {
DEBUG(0, ("rpc_auth_pipe: schannel unmarshalling "
"RPC_AUTH_NETSECK_CHK failed\n"));
- prs_mem_free(&netsec_verf);
return False;
}
SENDER_IS_ACCEPTOR,
&chk, reply_data, data_len)) {
DEBUG(0, ("rpc_auth_pipe: Could not decode schannel\n"));
- prs_mem_free(&netsec_verf);
return False;
}
cli->auth_info.seq_num++;
- prs_mem_free(&netsec_verf);
}
return True;
}
RPC_HDR_AUTH hdr_auth;
int auth_len = 0;
int auth_type, auth_level;
- size_t saved_hdr_offset;
+ size_t saved_hdr_offset = 0;
prs_struct auth_info;
prs_init(&auth_info, RPC_HDR_AUTH_LEN, /* we will need at least this much */
DATA_BLOB request;
DEBUG(5, ("Processing NTLMSSP Negotiate\n"));
- nt_status = ntlmssp_client_update(cli->ntlmssp_pipe_state,
- null_blob,
- &request);
+ nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
+ null_blob,
+ &request);
if (!NT_STATUS_EQUAL(nt_status,
NT_STATUS_MORE_PROCESSING_REQUIRED)) {
/* Auth len in the rpc header doesn't include auth_header. */
auth_len = request.length;
- prs_copy_data_in(&auth_info, request.data, request.length);
+ prs_copy_data_in(&auth_info, (char *)request.data, request.length);
DEBUG(5, ("NTLMSSP Negotiate:\n"));
- dump_data(5, request.data, request.length);
+ dump_data(5, (const char *)request.data, request.length);
data_blob_free(&request);
- }
- else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
+ } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
RPC_AUTH_NETSEC_NEG netsec_neg;
/* Use lp_workgroup() if domain not specified */
- if (!domain || !domain[0])
+ if (!domain || !domain[0]) {
+ DEBUG(10,("create_rpc_bind_req: no domain; assuming my own\n"));
domain = lp_workgroup();
+ }
init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name);
/* Auth len in the rpc header doesn't include auth_header. */
auth_len = prs_offset(&auth_info) - saved_hdr_offset;
}
- /* create the request RPC_HDR */
+
+ /* Create the request RPC_HDR */
init_rpc_hdr(&hdr, RPC_BIND, 0x3, rpc_call_id,
RPC_HEADER_LEN + RPC_HDR_RB_LEN + prs_offset(&auth_info),
auth_len);
return NT_STATUS_NO_MEMORY;
}
}
+ prs_mem_free(&auth_info);
return NT_STATUS_OK;
}
/* The response is picked up from the internal cache,
where it was placed by the rpc_auth_pipe() code */
- nt_status = ntlmssp_client_update(cli->ntlmssp_pipe_state,
- ntlmssp_null_response,
- &ntlmssp_reply);
+ nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
+ ntlmssp_null_response,
+ &ntlmssp_reply);
if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
return nt_status;
* Append the auth data to the outgoing buffer.
*/
- if(!prs_copy_data_in(rpc_out, ntlmssp_reply.data, ntlmssp_reply.length)) {
+ if(!prs_copy_data_in(rpc_out, (char *)ntlmssp_reply.data, ntlmssp_reply.length)) {
DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n"));
data_blob_free(&ntlmssp_reply);
return NT_STATUS_NO_MEMORY;
}
- if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
- nt_status = ntlmssp_client_sign_init(cli->ntlmssp_pipe_state);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- return nt_status;
- }
- }
-
data_blob_free(&ntlmssp_reply);
return NT_STATUS_OK;
}
uint32 data_len, send_size;
uint8 flags = 0;
uint32 auth_padding = 0;
- RPC_AUTH_NETSEC_CHK verf;
DATA_BLOB sign_blob;
/*
*/
if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
- nt_status = ntlmssp_client_seal_packet(cli->ntlmssp_pipe_state,
+ nt_status = ntlmssp_seal_packet(cli->ntlmssp_pipe_state,
(unsigned char*)prs_data_p(&sec_blob),
data_and_padding_size,
&sign_blob);
}
else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
- nt_status = ntlmssp_client_sign_packet(cli->ntlmssp_pipe_state,
+ nt_status = ntlmssp_sign_packet(cli->ntlmssp_pipe_state,
(unsigned char*)prs_data_p(&sec_blob),
data_and_padding_size, &sign_blob);
if (!NT_STATUS_IS_OK(nt_status)) {
/* write auth footer onto the packet */
real_auth_len = sign_blob.length;
- prs_copy_data_in(&sec_blob, sign_blob.data, sign_blob.length);
+ prs_copy_data_in(&sec_blob, (char *)sign_blob.data, sign_blob.length);
data_blob_free(&sign_blob);
}
else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
- static const uchar netsec_sig[8] = NETSEC_SIGNATURE;
- static const uchar nullbytes[8] = { 0,0,0,0,0,0,0,0 };
size_t parse_offset_marker;
- if ((cli->auth_info.seq_num & 1) != 0) {
- DEBUG(0,("SCHANNEL ERROR: seq_num must be even in client (seq_num=%d)\n",
- cli->auth_info.seq_num));
- }
-
+ RPC_AUTH_NETSEC_CHK verf;
DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num));
- init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes,
- nullbytes, nullbytes);
-
netsec_encode(&cli->auth_info,
cli->pipe_auth_flags,
SENDER_IS_INITIATOR,
{
int i = 0;
+# if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
if ( hdr_ba->addr.len <= 0)
return False;
- if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe ))
+ if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&
+ !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )
{
DEBUG(4,("bind_rpc_pipe: pipe_name %s != expected pipe %s. oh well!\n",
pipe_names[i].server_pipe ,hdr_ba->addr.str));
DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
return False;
}
+#endif /* JERRY */
/* check the transfer syntax */
if ((hdr_ba->transfer.version != transfer->version) ||
prs_init(&rpc_out, RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN, /* need at least this much */
cli->mem_ctx, MARSHALL);
- create_rpc_bind_resp(cli, rpc_call_id,
- &rpc_out);
+ if (!NT_STATUS_IS_OK(create_rpc_bind_resp(cli, rpc_call_id,
+ &rpc_out))) {
+ return False;
+ }
if ((ret = cli_write(cli, cli->nt_pipe_fnum, 0x8, prs_data_p(&rpc_out),
0, (size_t)prs_offset(&rpc_out))) != (ssize_t)prs_offset(&rpc_out)) {
if (!NT_STATUS_IS_OK(nt_status))
return False;
+ /* Currently the NTLMSSP code does not implement NTLM2 correctly for signing or sealing */
+
+ cli->ntlmssp_pipe_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
+
nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state,
cli->user_name);
if (!NT_STATUS_IS_OK(nt_status))
if (!NT_STATUS_IS_OK(nt_status))
return False;
- pwd_get_cleartext(&cli->pwd, password);
- nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state,
- password);
- if (!NT_STATUS_IS_OK(nt_status))
- return False;
+ if (cli->pwd.null_pwd) {
+ nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state,
+ NULL);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return False;
+ } else {
+ pwd_get_cleartext(&cli->pwd, password);
+ nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state,
+ password);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return False;
+ }
if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
cli->nt_pipe_fnum = (uint16)fnum;
} else {
if ((fnum = cli_open(cli, pipe_names[pipe_idx].client_pipe, O_CREAT|O_RDWR, DENY_NONE)) == -1) {
- DEBUG(0,("cli_nt_session_open: cli_open failed on pipe %s to machine %s. Error was %s\n",
+ DEBUG(1,("cli_nt_session_open: cli_open failed on pipe %s to machine %s. Error was %s\n",
pipe_names[pipe_idx].client_pipe, cli->desthost, cli_errstr(cli)));
return False;
}
return False;
}
+ cli->pipe_idx = pipe_idx;
+
/*
* Setup the remote server name prefixed by \ and the machine account name.
*/
const uchar trust_password[16])
{
NTSTATUS result;
- uint32 neg_flags = 0x000001ff;
+ uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
int fnum;
cli_nt_netlogon_netsec_session_close(cli);
}
}
- /* doing schannel, not per-user auth */
- cli->pipe_auth_flags = AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL;
-
if (!rpc_pipe_bind(cli, PI_NETLOGON, global_myname())) {
DEBUG(2,("rpc bind to %s failed\n", PIPE_NETLOGON));
cli_close(cli, cli->nt_pipe_fnum);
}
+NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, int auth_flags,
+ const uchar trust_password[16])
+{
+ NTSTATUS result;
+ uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+ cli->pipe_auth_flags = 0;
+
+ if (lp_client_schannel() == False) {
+ return NT_STATUS_OK;
+ }
+
+ if (!cli_nt_session_open(cli, PI_NETLOGON)) {
+ DEBUG(0, ("Could not initialise %s\n",
+ get_pipe_name_from_index(PI_NETLOGON)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (lp_client_schannel() != False)
+ neg_flags |= NETLOGON_NEG_SCHANNEL;
+
+ neg_flags |= NETLOGON_NEG_SCHANNEL;
+
+ result = cli_nt_setup_creds(cli, sec_chan, trust_password,
+ &neg_flags, 2);
+
+ if (!(neg_flags & NETLOGON_NEG_SCHANNEL)
+ && lp_client_schannel() == True) {
+ DEBUG(1, ("Could not negotiate SCHANNEL with the DC!\n"));
+ result = NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!NT_STATUS_IS_OK(result)) {
+ ZERO_STRUCT(cli->auth_info.sess_key);
+ ZERO_STRUCT(cli->sess_key);
+ cli->pipe_auth_flags = 0;
+ cli_nt_session_close(cli);
+ return result;
+ }
+
+ memcpy(cli->auth_info.sess_key, cli->sess_key,
+ sizeof(cli->auth_info.sess_key));
+
+ cli->saved_netlogon_pipe_fnum = cli->nt_pipe_fnum;
+ cli->nt_pipe_fnum = 0;
+
+ /* doing schannel, not per-user auth */
+ cli->pipe_auth_flags = auth_flags;
+
+ return NT_STATUS_OK;
+}
+
const char *cli_pipe_get_name(struct cli_state *cli)
{
return cli->pipe_name;