*
* 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
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* 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.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* this module apparently provides an implementation of DCE/RPC over a
auth->a_u.auth_ntlmssp_state = NULL;
}
+static DATA_BLOB generic_session_key(void)
+{
+ return data_blob("SystemLibraryDTC", 16);
+}
+
/*******************************************************************
Generate the next PDU to be returned from the data in p->rdata.
Handle NTLMSSP.
********************************************************************/
-static BOOL create_next_pdu_ntlmssp(pipes_struct *p)
+static bool create_next_pdu_ntlmssp(pipes_struct *p)
{
RPC_HDR_RESP hdr_resp;
uint32 ss_padding_len = 0;
* data.
*/
- prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
+ prs_init_empty( &outgoing_pdu, p->mem_ctx, MARSHALL);
prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
/* Store the header in the data stream. */
Return an schannel authenticated fragment.
********************************************************************/
-static BOOL create_next_pdu_schannel(pipes_struct *p)
+static bool create_next_pdu_schannel(pipes_struct *p)
{
RPC_HDR_RESP hdr_resp;
uint32 ss_padding_len = 0;
* data.
*/
- prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
+ prs_init_empty( &outgoing_pdu, p->mem_ctx, MARSHALL);
prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
/* Store the header in the data stream. */
No authentication done.
********************************************************************/
-static BOOL create_next_pdu_noauth(pipes_struct *p)
+static bool create_next_pdu_noauth(pipes_struct *p)
{
RPC_HDR_RESP hdr_resp;
uint32 data_len;
* data.
*/
- prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
+ prs_init_empty( &outgoing_pdu, p->mem_ctx, MARSHALL);
prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
/* Store the header in the data stream. */
Generate the next PDU to be returned from the data in p->rdata.
********************************************************************/
-BOOL create_next_pdu(pipes_struct *p)
+bool create_next_pdu(pipes_struct *p)
{
switch(p->auth.auth_level) {
case PIPE_AUTH_LEVEL_NONE:
the pipe struct.
*******************************************************************/
-static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
+static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
{
DATA_BLOB reply;
NTSTATUS status;
p->pipe_user.ut.ngroups = 0;
SAFE_FREE( p->pipe_user.ut.groups);
+ /* this has to be done as root in order to verify the password */
+ become_root();
status = auth_ntlmssp_update(a, *p_resp_blob, &reply);
+ unbecome_root();
/* Don't generate a reply. */
data_blob_free(&reply);
p->pipe_user.ut.gid = a->server_info->gid;
/*
- * Copy the session key from the ntlmssp state.
+ * We're an authenticated bind over smbd, so the session key needs to
+ * be set to "SystemLibraryDTC". Weird, but this is what Windows
+ * does. See the RPC-SAMBA3SESSIONKEY.
*/
data_blob_free(&p->session_key);
- p->session_key = data_blob(a->ntlmssp_state->session_key.data, a->ntlmssp_state->session_key.length);
+ p->session_key = generic_session_key();
if (!p->session_key.data) {
return False;
}
p->pipe_user.ut.ngroups = a->server_info->n_groups;
if (p->pipe_user.ut.ngroups) {
- if (!(p->pipe_user.ut.groups = memdup(a->server_info->groups,
+ if (!(p->pipe_user.ut.groups = (gid_t *)memdup(a->server_info->groups,
sizeof(gid_t) * p->pipe_user.ut.ngroups))) {
DEBUG(0,("failed to memdup group list to p->pipe_user.groups\n"));
return False;
const char *clnt;
const char *srv;
} pipe;
- struct api_struct *cmds;
+ const struct api_struct *cmds;
int n_cmds;
};
This is the "stage3" NTLMSSP response after a bind request and reply.
*******************************************************************/
-BOOL api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p)
+bool api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p)
{
RPC_HDR_AUTH auth_info;
uint32 pad;
Marshall a bind_nak pdu.
*******************************************************************/
-static BOOL setup_bind_nak(pipes_struct *p)
+static bool setup_bind_nak(pipes_struct *p)
{
prs_struct outgoing_rpc;
RPC_HDR nak_hdr;
* header and are never sending more than one PDU here.
*/
- prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL);
+ prs_init_empty( &outgoing_rpc, p->mem_ctx, MARSHALL);
prs_give_memory( &outgoing_rpc, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
/*
Marshall a fault pdu.
*******************************************************************/
-BOOL setup_fault_pdu(pipes_struct *p, NTSTATUS status)
+bool setup_fault_pdu(pipes_struct *p, NTSTATUS status)
{
prs_struct outgoing_pdu;
RPC_HDR fault_hdr;
* header and are never sending more than one PDU here.
*/
- prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
+ prs_init_empty( &outgoing_pdu, p->mem_ctx, MARSHALL);
prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
/*
We should probably check the auth-verifier here.
*******************************************************************/
-BOOL setup_cancel_ack_reply(pipes_struct *p, prs_struct *rpc_in_p)
+bool setup_cancel_ack_reply(pipes_struct *p, prs_struct *rpc_in_p)
{
prs_struct outgoing_pdu;
RPC_HDR ack_reply_hdr;
* header and are never sending more than one PDU here.
*/
- prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
+ prs_init_empty( &outgoing_pdu, p->mem_ctx, MARSHALL);
prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
/*
Used to reject unknown binds from Win2k.
*******************************************************************/
-BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract,
+bool check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract,
RPC_IFACE* transfer, uint32 context_id)
{
char *pipe_name = p->name;
/* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */
for ( i=0; pipe_names[i].client_pipe; i++ ) {
- DEBUG(10,("checking %s\n", pipe_names[i].client_pipe));
+ DEBUGADD(10,("checking %s\n", pipe_names[i].client_pipe));
if ( strequal(pipe_names[i].client_pipe, pname)
&& (abstract->version == pipe_names[i].abstr_syntax.version)
- && (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(struct uuid)) == 0)
+ && (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(struct GUID)) == 0)
&& (transfer->version == pipe_names[i].trans_syntax.version)
- && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct uuid)) == 0) ) {
+ && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct GUID)) == 0) ) {
struct api_struct *fns = NULL;
int n_fns = 0;
PIPE_RPC_FNS *context_fns;
ZERO_STRUCTP(rpc_entry);
rpc_entry->pipe.clnt = SMB_STRDUP(clnt);
rpc_entry->pipe.srv = SMB_STRDUP(srv);
- rpc_entry->cmds = SMB_REALLOC_ARRAY(rpc_entry->cmds, struct api_struct, rpc_entry->n_cmds + size);
- if (!rpc_entry->cmds) {
- return NT_STATUS_NO_MEMORY;
- }
- memcpy(rpc_entry->cmds + rpc_entry->n_cmds, cmds, size * sizeof(struct api_struct));
- rpc_entry->n_cmds += size;
+ rpc_entry->cmds = cmds;
+ rpc_entry->n_cmds = size;
return NT_STATUS_OK;
}
Handle a SPNEGO krb5 bind auth.
*******************************************************************/
-static BOOL pipe_spnego_auth_bind_kerberos(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info,
+static bool pipe_spnego_auth_bind_kerberos(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info,
DATA_BLOB *psecblob, prs_struct *pout_auth)
{
return False;
Handle the first part of a SPNEGO bind auth.
*******************************************************************/
-static BOOL pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_p,
+static bool pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_p,
RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
{
DATA_BLOB blob;
char *OIDs[ASN1_MAX_OIDS];
int i;
NTSTATUS status;
- BOOL got_kerberos_mechanism = False;
+ bool got_kerberos_mechanism = false;
AUTH_NTLMSSP_STATE *a = NULL;
RPC_HDR_AUTH auth_info;
}
if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
- got_kerberos_mechanism = True;
+ got_kerberos_mechanism = true;
}
for (i=0;OIDs[i];i++) {
DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
- BOOL ret = pipe_spnego_auth_bind_kerberos(p, rpc_in_p, pauth_info, &secblob, pout_auth);
+ bool ret = pipe_spnego_auth_bind_kerberos(p, rpc_in_p, pauth_info, &secblob, pout_auth);
data_blob_free(&secblob);
data_blob_free(&blob);
return ret;
free_pipe_ntlmssp_auth_data(&p->auth);
}
- /* Initialize the NTLM engine. */
- status = auth_ntlmssp_start(&a);
- if (!NT_STATUS_IS_OK(status)) {
- goto err;
- }
+ if (!got_kerberos_mechanism) {
+ /* Initialize the NTLM engine. */
+ status = auth_ntlmssp_start(&a);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err;
+ }
- /*
- * Pass the first security blob of data to it.
- * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED
- * which means we need another packet to complete the bind.
- */
+ /*
+ * Pass the first security blob of data to it.
+ * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED
+ * which means we need another packet to complete the bind.
+ */
- status = auth_ntlmssp_update(a, secblob, &chal);
+ status = auth_ntlmssp_update(a, secblob, &chal);
- if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n"));
- goto err;
- }
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+ DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n"));
+ goto err;
+ }
- /* Generate the response blob we need for step 2 of the bind. */
- response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+ /* Generate the response blob we need for step 2 of the bind. */
+ response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+ } else {
+ /*
+ * SPNEGO negotiate down to NTLMSSP. The subsequent
+ * code to process follow-up packets is not complete
+ * yet. JRA.
+ */
+ response = spnego_gen_auth_response(NULL,
+ NT_STATUS_MORE_PROCESSING_REQUIRED,
+ OID_NTLMSSP);
+ }
/* Copy the blob into the pout_auth parse struct */
init_rpc_hdr_auth(&auth_info, RPC_SPNEGO_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
Handle the second part of a SPNEGO bind auth.
*******************************************************************/
-static BOOL pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p,
+static bool pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p,
RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
{
RPC_HDR_AUTH auth_info;
ZERO_STRUCT(auth_reply);
ZERO_STRUCT(response);
+ /*
+ * NB. If we've negotiated down from krb5 to NTLMSSP we'll currently
+ * fail here as 'a' == NULL.
+ */
if (p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP || !a) {
DEBUG(0,("pipe_spnego_auth_bind_continue: not in NTLMSSP auth state.\n"));
goto err;
* The following call actually checks the challenge/response data.
* for correctness against the given DOMAIN\user name.
*/
-
+
if (!pipe_ntlmssp_verify_final(p, &auth_blob)) {
goto err;
}
Handle an schannel bind auth.
*******************************************************************/
-static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
+static bool pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
{
RPC_HDR_AUTH auth_info;
RPC_AUTH_SCHANNEL_NEG neg;
RPC_AUTH_VERIFIER auth_verifier;
- BOOL ret;
+ bool ret;
struct dcinfo *pdcinfo;
uint32 flags;
* JRA. Should we also copy the schannel session key into the pipe session key p->session_key
* here ? We do that for NTLMSSP, but the session key is already set up from the vuser
* struct of the person who opened the pipe. I need to test this further. JRA.
+ *
+ * VL. As we are mapping this to guest set the generic key
+ * "SystemLibraryDTC" key here. It's a bit difficult to test against
+ * W2k3, as it does not allow schannel binds against SAMR and LSA
+ * anymore.
*/
+ data_blob_free(&p->session_key);
+ p->session_key = generic_session_key();
+ if (p->session_key.data == NULL) {
+ DEBUG(0, ("pipe_schannel_auth_bind: Could not alloc session"
+ " key\n"));
+ return False;
+ }
+
init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) {
DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n"));
Handle an NTLMSSP bind auth.
*******************************************************************/
-static BOOL pipe_ntlmssp_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
+static bool pipe_ntlmssp_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
{
RPC_HDR_AUTH auth_info;
Respond to a pipe bind request.
*******************************************************************/
-BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
+bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
{
RPC_HDR_BA hdr_ba;
RPC_HDR_RB hdr_rb;
return setup_bind_nak(p);
}
- prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL);
+ prs_init_empty( &outgoing_rpc, p->mem_ctx, MARSHALL);
/*
* Marshall directly into the outgoing PDU space. We
}
}
+ ZERO_STRUCT(hdr_rb);
+
/* decode the bind request */
if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_in_p, 0)) {
DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_RB struct.\n"));
case RPC_ANONYMOUS_AUTH_TYPE:
/* Unauthenticated bind request. */
+ /* Get the authenticated pipe user from current_user */
+ if (!copy_current_user(&p->pipe_user, ¤t_user)) {
+ DEBUG(10, ("Could not copy current user\n"));
+ goto err_exit;
+ }
/* We're finished - no more packets. */
p->auth.auth_type = PIPE_AUTH_TYPE_NONE;
/* We must set the pipe auth_level here also. */
p->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
p->pipe_bound = True;
+ /* The session key was initialized from the SMB
+ * session in make_internal_rpc_pipe_p */
break;
default:
SPNEGO calls.
****************************************************************************/
-BOOL api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p)
+bool api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p)
{
RPC_HDR_BA hdr_ba;
RPC_HDR_RB hdr_rb;
prs_struct outgoing_rpc;
int auth_len = 0;
- prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL);
+ prs_init_empty( &outgoing_rpc, p->mem_ctx, MARSHALL);
/*
* Marshall directly into the outgoing PDU space. We
Deal with NTLMSSP sign & seal processing on an RPC request.
****************************************************************************/
-BOOL api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in,
+bool api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in,
uint32 *p_ss_padding_len, NTSTATUS *pstatus)
{
RPC_HDR_AUTH auth_info;
Deal with schannel processing on an RPC request.
****************************************************************************/
-BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss_padding_len)
+bool api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss_padding_len)
{
uint32 data_len;
uint32 auth_len;
before doing the call.
****************************************************************************/
-BOOL api_pipe_request(pipes_struct *p)
+bool api_pipe_request(pipes_struct *p)
{
- BOOL ret = False;
- BOOL changed_user = False;
+ bool ret = False;
+ bool changed_user = False;
PIPE_RPC_FNS *pipe_fns;
if (p->pipe_bound &&
pipe_fns = find_pipe_fns_by_context(p->contexts, p->hdr_req.context_id);
if ( pipe_fns ) {
- set_current_rpc_talloc(p->mem_ctx);
+ TALLOC_CTX *frame = talloc_stackframe();
ret = api_rpcTNP(p, p->name, pipe_fns->cmds, pipe_fns->n_cmds);
- set_current_rpc_talloc(NULL);
+ TALLOC_FREE(frame);
}
else {
DEBUG(0,("api_pipe_request: No rpc function table associated with context [%d] on pipe [%s]\n",
Calls the underlying RPC function for a named pipe.
********************************************************************/
-BOOL api_rpcTNP(pipes_struct *p, const char *rpc_name,
+bool api_rpcTNP(pipes_struct *p, const char *rpc_name,
const struct api_struct *api_rpc_cmds, int n_cmds)
{
int fn_num;
return True;
}
+ if (p->rng_fault_state) {
+ DEBUG(4, ("api_rpcTNP: rng fault return\n"));
+ p->rng_fault_state = False;
+ setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
+ return True;
+ }
+
slprintf(name, sizeof(name)-1, "out_%s", rpc_name);
offset2 = prs_offset(&p->out_data.rdata);
prs_set_offset(&p->out_data.rdata, offset1);
if ((DEBUGLEVEL >= 10) &&
(prs_offset(&p->in_data.data) != prs_data_size(&p->in_data.data))) {
size_t data_len = prs_data_size(&p->in_data.data) - prs_offset(&p->in_data.data);
- char *data = SMB_MALLOC(data_len);
+ char *data = (char *)SMB_MALLOC(data_len);
DEBUG(10, ("api_rpcTNP: rpc input buffer underflow (parse error?)\n"));
if (data) {
switch ( idx ) {
case PI_LSARPC:
- lsa_get_pipe_fns( &cmds, &n_cmds );
+ lsarpc_get_pipe_fns( &cmds, &n_cmds );
break;
- case PI_LSARPC_DS:
- lsa_ds_get_pipe_fns( &cmds, &n_cmds );
+ case PI_DSSETUP:
+ dssetup_get_pipe_fns( &cmds, &n_cmds );
break;
case PI_SAMR:
samr_get_pipe_fns( &cmds, &n_cmds );
break;
case PI_NETLOGON:
- netlog_get_pipe_fns( &cmds, &n_cmds );
+ netlogon_get_pipe_fns( &cmds, &n_cmds );
break;
case PI_SRVSVC:
srvsvc_get_pipe_fns( &cmds, &n_cmds );
wkssvc_get_pipe_fns( &cmds, &n_cmds );
break;
case PI_WINREG:
- reg_get_pipe_fns( &cmds, &n_cmds );
+ winreg_get_pipe_fns( &cmds, &n_cmds );
break;
case PI_SPOOLSS:
spoolss_get_pipe_fns( &cmds, &n_cmds );
netdfs_get_pipe_fns( &cmds, &n_cmds );
break;
case PI_SVCCTL:
- svcctl_get_pipe_fns( &cmds, &n_cmds );
+ svcctl2_get_pipe_fns( &cmds, &n_cmds );
break;
case PI_EVENTLOG:
- eventlog_get_pipe_fns( &cmds, &n_cmds );
+ eventlog2_get_pipe_fns( &cmds, &n_cmds );
break;
case PI_NTSVCS:
- ntsvcs_get_pipe_fns( &cmds, &n_cmds );
+ ntsvcs2_get_pipe_fns( &cmds, &n_cmds );
break;
#ifdef DEVELOPER
- case PI_ECHO:
- echo_get_pipe_fns( &cmds, &n_cmds );
+ case PI_RPCECHO:
+ rpcecho_get_pipe_fns( &cmds, &n_cmds );
break;
#endif
default: