NTSTATUS leases_db_add(const struct GUID *client_guid,
		       const struct smb2_lease_key *lease_key,
		       const struct file_id *id,
		       const char *servicepath,
		       const char *base_name,
		       const char *stream_name)
{
	TDB_DATA db_key, db_value;
	DATA_BLOB blob;
	struct db_record *rec;
	NTSTATUS status;
	bool ok;
	struct leases_db_value new_value;
	struct leases_db_file new_file;
	struct leases_db_value *value = NULL;
	enum ndr_err_code ndr_err;

	if (!leases_db_init(false)) {
		return NT_STATUS_INTERNAL_ERROR;
	}

	ok = leases_db_key(talloc_tos(), client_guid, lease_key, &db_key);
	if (!ok) {
		DEBUG(10, ("%s: leases_db_key failed\n", __func__));
		return NT_STATUS_NO_MEMORY;
	}

	rec = dbwrap_fetch_locked(leases_db, talloc_tos(), db_key);
	TALLOC_FREE(db_key.dptr);
	if (rec == NULL) {
		return NT_STATUS_INTERNAL_ERROR;
	}

	db_value = dbwrap_record_get_value(rec);
	if (db_value.dsize != 0) {
		uint32_t i;

		DEBUG(10, ("%s: record exists\n", __func__));

		value = talloc(talloc_tos(), struct leases_db_value);
		if (value == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}

		blob.data = db_value.dptr;
		blob.length = db_value.dsize;

		ndr_err = ndr_pull_struct_blob_all(
			&blob, value, value,
			(ndr_pull_flags_fn_t)ndr_pull_leases_db_value);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			DEBUG(10, ("%s: ndr_pull_struct_blob_failed: %s\n",
				   __func__, ndr_errstr(ndr_err)));
			status = ndr_map_error2ntstatus(ndr_err);
			goto out;
		}

		/* id must be unique. */
		for (i = 0; i < value->num_files; i++) {
			if (file_id_equal(id, &value->files[i].id)) {
				status = NT_STATUS_OBJECT_NAME_COLLISION;
				goto out;
			}
		}

		value->files = talloc_realloc(value, value->files,
					struct leases_db_file,
					value->num_files + 1);
		if (value->files == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}
		value->files[value->num_files].id = *id;
		value->files[value->num_files].servicepath = servicepath;
		value->files[value->num_files].base_name = base_name;
		value->files[value->num_files].stream_name = stream_name;
		value->num_files += 1;

	} else {
Пример #2
0
static bool api_frstrans_EstablishConnection(struct pipes_struct *p)
{
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	struct ndr_push *push;
	enum ndr_err_code ndr_err;
	struct frstrans_EstablishConnection *r;

	call = &ndr_table_frstrans.calls[NDR_FRSTRANS_ESTABLISHCONNECTION];

	r = talloc(talloc_tos(), struct frstrans_EstablishConnection);
	if (r == NULL) {
		return false;
	}

	pull = ndr_pull_init_blob(&p->in_data.data, r);
	if (pull == NULL) {
		talloc_free(r);
		return false;
	}

	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	if (p->endian) {
		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
	}
	ndr_err = call->ndr_pull(pull, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(frstrans_EstablishConnection, NDR_IN, r);
	}

	ZERO_STRUCT(r->out);
	r->out.upstream_protocol_version = talloc_zero(r, enum frstrans_ProtocolVersion);
	if (r->out.upstream_protocol_version == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.upstream_flags = talloc_zero(r, uint32_t);
	if (r->out.upstream_flags == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.result = _frstrans_EstablishConnection(p, r);

	if (p->fault_state) {
		talloc_free(r);
		/* Return true here, srv_pipe_hnd.c will take care */
		return true;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(frstrans_EstablishConnection, NDR_OUT | NDR_SET_VALUES, r);
	}

	push = ndr_push_init_ctx(r);
	if (push == NULL) {
		talloc_free(r);
		return false;
	}

	/*
	 * carry over the pointer count to the reply in case we are
	 * using full pointer. See NDR specification for full pointers
	 */
	push->ptr_count = pull->ptr_count;

	ndr_err = call->ndr_push(push, NDR_OUT, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	p->out_data.rdata = ndr_push_blob(push);
	talloc_steal(p->mem_ctx, p->out_data.rdata.data);

	talloc_free(r);

	return true;
}
Пример #3
0
static bool parse_getdc_response(
	struct packet_struct *packet,
	TALLOC_CTX *mem_ctx,
	const char *domain_name,
	uint32_t *nt_version,
	const char **dc_name,
	struct netlogon_samlogon_response **samlogon_response)
{
	DATA_BLOB blob;
	struct netlogon_samlogon_response *r;
	union dgram_message_body p;
	enum ndr_err_code ndr_err;
	NTSTATUS status;

	const char *returned_dc = NULL;
	const char *returned_domain = NULL;

	blob = data_blob_const(packet->packet.dgram.data,
			       packet->packet.dgram.datasize);
	if (blob.length < 4) {
		DEBUG(1, ("invalid length: %d\n", (int)blob.length));
		return false;
	}

	if (RIVAL(blob.data,0) != DGRAM_SMB) {
		DEBUG(1, ("invalid packet\n"));
		return false;
	}

	blob.data += 4;
	blob.length -= 4;

	ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, &p, DGRAM_SMB,
		       (ndr_pull_flags_fn_t)ndr_pull_dgram_smb_packet);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(1, ("failed to parse packet\n"));
		return false;
	}

	if (p.smb.smb_command != SMB_TRANSACTION) {
		DEBUG(1, ("invalid smb_command: %d\n", p.smb.smb_command));
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_DEBUG(dgram_smb_packet, &p);
	}

	blob = p.smb.body.trans.data;

	r = talloc_zero(mem_ctx, struct netlogon_samlogon_response);
	if (!r) {
		return false;
	}

	status = pull_netlogon_samlogon_response(&blob, r, r);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(r);
		return false;
	}

	map_netlogon_samlogon_response(r);

	/* do we still need this ? */
	*nt_version = r->ntver;

	returned_domain = r->data.nt5_ex.domain_name;
	returned_dc = r->data.nt5_ex.pdc_name;

	if (!strequal(returned_domain, domain_name)) {
		DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
			  domain_name, returned_domain));
		TALLOC_FREE(r);
		return false;
	}

	if (*returned_dc == '\\') returned_dc += 1;
	if (*returned_dc == '\\') returned_dc += 1;

	*dc_name = talloc_strdup(mem_ctx, returned_dc);
	if (!*dc_name) {
		TALLOC_FREE(r);
		return false;
	}

	if (samlogon_response) {
		*samlogon_response = r;
	} else {
		TALLOC_FREE(r);
	}

	DEBUG(10, ("GetDC gave name %s for domain %s\n",
		   *dc_name, returned_domain));

	return True;
}
Пример #4
0
 krb5_error_code kerberos_encode_pac(TALLOC_CTX *mem_ctx,
				    struct PAC_DATA *pac_data,
				    krb5_context context,
				    const krb5_keyblock *krbtgt_keyblock,
				    const krb5_keyblock *service_keyblock,
				    DATA_BLOB *pac)
{
	NTSTATUS nt_status;
	krb5_error_code ret;
	enum ndr_err_code ndr_err;
	DATA_BLOB zero_blob = data_blob(NULL, 0);
	DATA_BLOB tmp_blob = data_blob(NULL, 0);
	struct PAC_SIGNATURE_DATA *kdc_checksum = NULL;
	struct PAC_SIGNATURE_DATA *srv_checksum = NULL;
	int i;

	/* First, just get the keytypes filled in (and lengths right, eventually) */
	for (i=0; i < pac_data->num_buffers; i++) {
		if (pac_data->buffers[i].type != PAC_TYPE_KDC_CHECKSUM) {
			continue;
		}
		kdc_checksum = &pac_data->buffers[i].info->kdc_cksum,
		ret = smb_krb5_make_pac_checksum(mem_ctx,
						 &zero_blob,
						 context,
						 krbtgt_keyblock,
						 &kdc_checksum->type,
						 &kdc_checksum->signature);
		if (ret) {
			DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
				  smb_get_krb5_error_message(context, ret, mem_ctx)));
			talloc_free(pac_data);
			return ret;
		}
	}

	for (i=0; i < pac_data->num_buffers; i++) {
		if (pac_data->buffers[i].type != PAC_TYPE_SRV_CHECKSUM) {
			continue;
		}
		srv_checksum = &pac_data->buffers[i].info->srv_cksum;
		ret = smb_krb5_make_pac_checksum(mem_ctx,
						 &zero_blob,
						 context,
						 service_keyblock,
						 &srv_checksum->type,
						 &srv_checksum->signature);
		if (ret) {
			DEBUG(2, ("making service PAC checksum failed: %s\n",
				  smb_get_krb5_error_message(context, ret, mem_ctx)));
			talloc_free(pac_data);
			return ret;
		}
	}

	if (!kdc_checksum) {
		DEBUG(2, ("Invalid PAC constructed for signing, no KDC checksum present!"));
		return EINVAL;
	}
	if (!srv_checksum) {
		DEBUG(2, ("Invalid PAC constructed for signing, no SRV checksum present!"));
		return EINVAL;
	}

	/* But wipe out the actual signatures */
	memset(kdc_checksum->signature.data, '\0', kdc_checksum->signature.length);
	memset(srv_checksum->signature.data, '\0', srv_checksum->signature.length);

	ndr_err = ndr_push_struct_blob(&tmp_blob, mem_ctx,
				       pac_data,
				       (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		nt_status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status)));
		talloc_free(pac_data);
		return EINVAL;
	}

	/* Then sign the result of the previous push, where the sig was zero'ed out */
	ret = smb_krb5_make_pac_checksum(mem_ctx,
					 &tmp_blob,
					 context,
					 service_keyblock,
					 &srv_checksum->type,
					 &srv_checksum->signature);

	/* Then sign Server checksum */
	ret = smb_krb5_make_pac_checksum(mem_ctx,
					 &srv_checksum->signature,
					 context,
					 krbtgt_keyblock,
					 &kdc_checksum->type,
					 &kdc_checksum->signature);
	if (ret) {
		DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
			  smb_get_krb5_error_message(context, ret, mem_ctx)));
		talloc_free(pac_data);
		return ret;
	}

	/* And push it out again, this time to the world.  This relies on determanistic pointer values */
	ndr_err = ndr_push_struct_blob(&tmp_blob, mem_ctx,
				       pac_data,
				       (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		nt_status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status)));
		talloc_free(pac_data);
		return EINVAL;
	}

	*pac = tmp_blob;

	return ret;
}
Пример #5
0
static bool api_frstrans_InitializeFileTransferAsync(struct pipes_struct *p)
{
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	struct ndr_push *push;
	enum ndr_err_code ndr_err;
	struct frstrans_InitializeFileTransferAsync *r;

	call = &ndr_table_frstrans.calls[NDR_FRSTRANS_INITIALIZEFILETRANSFERASYNC];

	r = talloc(talloc_tos(), struct frstrans_InitializeFileTransferAsync);
	if (r == NULL) {
		return false;
	}

	pull = ndr_pull_init_blob(&p->in_data.data, r);
	if (pull == NULL) {
		talloc_free(r);
		return false;
	}

	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	if (p->endian) {
		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
	}
	ndr_err = call->ndr_pull(pull, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(frstrans_InitializeFileTransferAsync, NDR_IN, r);
	}

	ZERO_STRUCT(r->out);
	r->out.frs_update = r->in.frs_update;
	r->out.staging_policy = r->in.staging_policy;
	r->out.server_context = talloc_zero(r, struct policy_handle);
	if (r->out.server_context == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.rdc_file_info = talloc_zero(r, struct frstrans_RdcFileInfo *);
	if (r->out.rdc_file_info == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.data_buffer = talloc_zero_array(r, uint8_t, r->in.buffer_size);
	if (r->out.data_buffer == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.size_read = talloc_zero(r, uint32_t);
	if (r->out.size_read == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.is_end_of_file = talloc_zero(r, uint32_t);
	if (r->out.is_end_of_file == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.result = _frstrans_InitializeFileTransferAsync(p, r);

	if (p->fault_state) {
		talloc_free(r);
		/* Return true here, srv_pipe_hnd.c will take care */
		return true;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(frstrans_InitializeFileTransferAsync, NDR_OUT | NDR_SET_VALUES, r);
	}

	push = ndr_push_init_ctx(r);
	if (push == NULL) {
		talloc_free(r);
		return false;
	}

	/*
	 * carry over the pointer count to the reply in case we are
	 * using full pointer. See NDR specification for full pointers
	 */
	push->ptr_count = pull->ptr_count;

	ndr_err = call->ndr_push(push, NDR_OUT, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	p->out_data.rdata = ndr_push_blob(push);
	talloc_steal(p->mem_ctx, p->out_data.rdata.data);

	talloc_free(r);

	return true;
}
Пример #6
0
static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
                                        const char *domain_name,
                                        const struct GUID *domain_guid,
                                        uint32_t flags,
                                        struct netr_DsRGetDCNameInfo **info_p)
{
    char *key;
    DATA_BLOB blob;
    enum ndr_err_code ndr_err;
    struct netr_DsRGetDCNameInfo *info;
    struct NETLOGON_SAM_LOGON_RESPONSE_EX r;
    NTSTATUS status;

    key = dsgetdcname_cache_key(mem_ctx, domain_name);
    if (!key) {
        return NT_STATUS_NO_MEMORY;
    }

    if (!gencache_get_data_blob(key, &blob, NULL, NULL)) {
        return NT_STATUS_NOT_FOUND;
    }

    info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
    if (!info) {
        return NT_STATUS_NO_MEMORY;
    }

    ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
                                   (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX);

    data_blob_free(&blob);
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
        dsgetdcname_cache_delete(mem_ctx, domain_name);
        return ndr_map_error2ntstatus(ndr_err);
    }

    status = make_dc_info_from_cldap_reply(mem_ctx, flags, NULL,
                                           &r, &info);
    if (!NT_STATUS_IS_OK(status)) {
        return status;
    }

    if (DEBUGLEVEL >= 10) {
        NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, info);
    }

    /* check flags */
    if (!check_cldap_reply_required_flags(info->dc_flags, flags)) {
        DEBUG(10,("invalid flags\n"));
        return NT_STATUS_INVALID_PARAMETER;
    }

    if ((flags & DS_IP_REQUIRED) &&
            (info->dc_address_type != DS_ADDRESS_TYPE_INET)) {
        return NT_STATUS_INVALID_PARAMETER_MIX;
    }

    *info_p = info;

    return NT_STATUS_OK;
}
Пример #7
0
/*
  send a create request
*/
struct smb2_request *smb2_create_send(struct smb2_tree *tree, struct smb2_create *io)
{
	struct smb2_request *req;
	NTSTATUS status;
	DATA_BLOB blob;
	struct smb2_create_blobs blobs;
	int i;

	ZERO_STRUCT(blobs);

	req = smb2_request_init_tree(tree, SMB2_OP_CREATE, 0x38, true, 0);
	if (req == NULL) return NULL;

	SCVAL(req->out.body, 0x02, io->in.security_flags);
	SCVAL(req->out.body, 0x03, io->in.oplock_level);
	SIVAL(req->out.body, 0x04, io->in.impersonation_level);
	SBVAL(req->out.body, 0x08, io->in.create_flags);
	SBVAL(req->out.body, 0x10, io->in.reserved);
	SIVAL(req->out.body, 0x18, io->in.desired_access);
	SIVAL(req->out.body, 0x1C, io->in.file_attributes);
	SIVAL(req->out.body, 0x20, io->in.share_access);
	SIVAL(req->out.body, 0x24, io->in.create_disposition);
	SIVAL(req->out.body, 0x28, io->in.create_options);

	status = smb2_push_o16s16_string(&req->out, 0x2C, io->in.fname);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	/* now add all the optional blobs */
	if (io->in.eas.num_eas != 0) {
		DATA_BLOB b = data_blob_talloc(req, NULL, 
					       ea_list_size_chained(io->in.eas.num_eas, io->in.eas.eas, 4));
		ea_put_list_chained(b.data, io->in.eas.num_eas, io->in.eas.eas, 4);
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_EXTA, b);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
		data_blob_free(&b);
	}

	/* an empty MxAc tag seems to be used to ask the server to
	   return the maximum access mask allowed on the file */
	if (io->in.query_maximal_access) {
		/* TODO: MS-SMB2 2.2.13.2.5 says this can contain a timestamp? What to do
		   with that if it doesn't match? */
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_MXAC, data_blob(NULL, 0));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.alloc_size != 0) {
		uint8_t data[8];
		SBVAL(data, 0, io->in.alloc_size);
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_ALSI, data_blob_const(data, 8));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.durable_open) {
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_DHNQ, data_blob_talloc_zero(req, 16));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.durable_handle) {
		uint8_t data[16];
		smb2_push_handle(data, io->in.durable_handle);
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_DHNC, data_blob_const(data, 16));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.timewarp) {
		uint8_t data[8];
		SBVAL(data, 0, io->in.timewarp);		
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_TWRP, data_blob_const(data, 8));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.sec_desc) {
		enum ndr_err_code ndr_err;
		DATA_BLOB sd_blob;
		ndr_err = ndr_push_struct_blob(&sd_blob, req, io->in.sec_desc,
					       (ndr_push_flags_fn_t)ndr_push_security_descriptor);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			talloc_free(req);
			return NULL;
		}
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_SECD, sd_blob);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.query_on_disk_id) {
		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_QFID, data_blob(NULL, 0));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	if (io->in.lease_request) {
		uint8_t data[32];

		memcpy(&data[0], &io->in.lease_request->lease_key, 16);
		SIVAL(data, 16, io->in.lease_request->lease_state);
		SIVAL(data, 20, io->in.lease_request->lease_flags);
		SBVAL(data, 24, io->in.lease_request->lease_duration);

		status = smb2_create_blob_add(req, &blobs,
					      SMB2_CREATE_TAG_RQLS,
					      data_blob_const(data, 32));
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}

	/* and any custom blobs */
	for (i=0;i<io->in.blobs.num_blobs;i++) {
		status = smb2_create_blob_add(req, &blobs,
					      io->in.blobs.blobs[i].tag, 
					      io->in.blobs.blobs[i].data);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(req);
			return NULL;
		}
	}


	status = smb2_create_blob_push(req, &blob, blobs);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	status = smb2_push_o32s32_blob(&req->out, 0x30, blob);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(req);
		return NULL;
	}

	data_blob_free(&blob);

	smb2_transport_send(req);

	return req;
}
Пример #8
0
/*
  convert a ldif formatted prefixMap to a NDR formatted blob
*/
static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
                               const struct ldb_val *in, struct ldb_val *out)
{
    struct prefixMapBlob *blob;
    enum ndr_err_code ndr_err;
    char *string, *line, *p, *oid;
    DATA_BLOB oid_blob;

    TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);

    if (tmp_ctx == NULL) {
        return -1;
    }

    blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
    if (blob == NULL) {
        talloc_free(tmp_ctx);
        return -1;
    }

    /* use the switch value to detect if this is in the binary
     * format
     */
    if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
        ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
                                       (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
        if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
            ndr_err = ndr_push_struct_blob(out, mem_ctx,
                                           blob,
                                           (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
            talloc_free(tmp_ctx);
            if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return -1;
            }
            return 0;
        }
    }

    /* If this does not parse, then it is probably the text version, and we should try it that way */
    blob->version = PREFIX_MAP_VERSION_DSDB;

    string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
    if (string == NULL) {
        talloc_free(blob);
        return -1;
    }

    line = string;
    while (line && line[0]) {
        p=strchr(line, ';');
        if (p) {
            p[0] = '\0';
        } else {
            p=strchr(line, '\n');
            if (p) {
                p[0] = '\0';
            }
        }
        /* allow a trailing separator */
        if (line == p) {
            break;
        }

        blob->ctr.dsdb.mappings = talloc_realloc(blob,
                                  blob->ctr.dsdb.mappings,
                                  struct drsuapi_DsReplicaOIDMapping,
                                  blob->ctr.dsdb.num_mappings+1);
        if (!blob->ctr.dsdb.mappings) {
            talloc_free(tmp_ctx);
            return -1;
        }

        blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);

        if (oid[0] != ':') {
            talloc_free(tmp_ctx);
            return -1;
        }

        /* we know there must be at least ":" */
        oid++;

        if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
            talloc_free(tmp_ctx);
            return -1;
        }
        blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
        blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;

        blob->ctr.dsdb.num_mappings++;

        /* Now look past the terminator we added above */
        if (p) {
            line = p + 1;
        } else {
            line = NULL;
        }
    }

    ndr_err = ndr_push_struct_blob(out, mem_ctx,
                                   blob,
                                   (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
    talloc_free(tmp_ctx);
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
        return -1;
    }
    return 0;
}
Пример #9
0
/*
  convert a NDR formatted blob to a ldif formatted prefixMap
*/
static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
                                const struct ldb_val *in, struct ldb_val *out)
{
    struct prefixMapBlob *blob;
    enum ndr_err_code ndr_err;
    char *string;
    uint32_t i;

    if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
        int err;
        /* try to decode the blob as S4 prefixMap */
        err = ldif_write_NDR(ldb, mem_ctx, in, out,
                             sizeof(struct prefixMapBlob),
                             (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
                             (ndr_print_fn_t)ndr_print_prefixMapBlob,
                             false);
        if (0 == err) {
            return err;
        }
        /* try parsing it as Windows PrefixMap value */
        return ldif_write_NDR(ldb, mem_ctx, in, out,
                              sizeof(struct drsuapi_MSPrefixMap_Ctr),
                              (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
                              (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
                              true);
    }

    blob = talloc(mem_ctx, struct prefixMapBlob);
    if (blob == NULL) {
        return -1;
    }
    ndr_err = ndr_pull_struct_blob_all(in, blob,
                                       blob,
                                       (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
    if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
        goto failed;
    }
    if (blob->version != PREFIX_MAP_VERSION_DSDB) {
        goto failed;
    }
    string = talloc_strdup(mem_ctx, "");
    if (string == NULL) {
        goto failed;
    }

    for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
        DATA_BLOB oid_blob;
        char *partial_oid = NULL;

        if (i > 0) {
            string = talloc_asprintf_append(string, ";");
        }

        oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
                                   blob->ctr.dsdb.mappings[i].oid.length);
        if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
            DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X",
                      blob->ctr.dsdb.mappings[i].id_prefix));
            goto failed;
        }
        string = talloc_asprintf_append(string, "%u:%s",
                                        blob->ctr.dsdb.mappings[i].id_prefix,
                                        partial_oid);
        talloc_free(discard_const(partial_oid));
        if (string == NULL) {
            goto failed;
        }
    }

    talloc_free(blob);
    *out = data_blob_string_const(string);
    return 0;

failed:
    talloc_free(blob);
    return -1;
}
Пример #10
0
static bool api_fss_GetShareMapping(struct pipes_struct *p)
{
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	struct ndr_push *push;
	enum ndr_err_code ndr_err;
	struct fss_GetShareMapping *r;

	call = &ndr_table_FileServerVssAgent.calls[NDR_FSS_GETSHAREMAPPING];

	r = talloc(talloc_tos(), struct fss_GetShareMapping);
	if (r == NULL) {
		return false;
	}

	pull = ndr_pull_init_blob(&p->in_data.data, r);
	if (pull == NULL) {
		talloc_free(r);
		return false;
	}

	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	if (p->endian) {
		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
	}
	ndr_err = call->ndr_pull(pull, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(fss_GetShareMapping, NDR_IN, r);
	}

	ZERO_STRUCT(r->out);
	r->out.ShareMapping = talloc_zero(r, union fssagent_share_mapping);
	if (r->out.ShareMapping == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.result = _fss_GetShareMapping(p, r);

	if (p->fault_state) {
		talloc_free(r);
		/* Return true here, srv_pipe_hnd.c will take care */
		return true;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(fss_GetShareMapping, NDR_OUT | NDR_SET_VALUES, r);
	}

	push = ndr_push_init_ctx(r);
	if (push == NULL) {
		talloc_free(r);
		return false;
	}

	/*
	 * carry over the pointer count to the reply in case we are
	 * using full pointer. See NDR specification for full pointers
	 */
	push->ptr_count = pull->ptr_count;

	ndr_err = call->ndr_push(push, NDR_OUT, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	p->out_data.rdata = ndr_push_blob(push);
	talloc_steal(p->mem_ctx, p->out_data.rdata.data);

	talloc_free(r);

	return true;
}
Пример #11
0
/**
* @brief Decode a blob containing a NDR envoded PAC structure
*
* @param mem_ctx	  - The memory context
* @param pac_data_blob	  - The data blob containing the NDR encoded data
* @param context	  - The Kerberos Context
* @param service_keyblock - The Service Key used to verify the checksum
* @param client_principal - The client principal
* @param tgs_authtime     - The ticket timestamp
* @param pac_data_out	  - [out] The decoded PAC
*
* @return - A NTSTATUS error code
*/
NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
			     DATA_BLOB pac_data_blob,
			     krb5_context context,
			     const krb5_keyblock *krbtgt_keyblock,
			     const krb5_keyblock *service_keyblock,
			     krb5_const_principal client_principal,
			     time_t tgs_authtime,
			     struct PAC_DATA **pac_data_out)
{
	NTSTATUS status;
	enum ndr_err_code ndr_err;
	krb5_error_code ret;
	DATA_BLOB modified_pac_blob;

	NTTIME tgs_authtime_nttime;
	krb5_principal client_principal_pac = NULL;
	int i;

	struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
	struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
	struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
	struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
	struct PAC_LOGON_NAME *logon_name = NULL;
	struct PAC_LOGON_INFO *logon_info = NULL;
	struct PAC_DATA *pac_data = NULL;
	struct PAC_DATA_RAW *pac_data_raw = NULL;

	DATA_BLOB *srv_sig_blob = NULL;
	DATA_BLOB *kdc_sig_blob = NULL;

	bool bool_ret;

	*pac_data_out = NULL;

	pac_data = talloc(mem_ctx, struct PAC_DATA);
	pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
	kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
	srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
	if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
		return NT_STATUS_NO_MEMORY;
	}

	ndr_err = ndr_pull_struct_blob(&pac_data_blob, pac_data, pac_data,
		       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	if (pac_data->num_buffers < 4) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("less than 4 PAC buffers\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	ndr_err = ndr_pull_struct_blob(
				&pac_data_blob, pac_data_raw, pac_data_raw,
				(ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	if (pac_data_raw->num_buffers < 4) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("less than 4 PAC buffers\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (pac_data->num_buffers != pac_data_raw->num_buffers) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0, ("misparse! PAC_DATA has %d buffers while "
			  "PAC_DATA_RAW has %d\n", pac_data->num_buffers,
			  pac_data_raw->num_buffers));
		return NT_STATUS_INVALID_PARAMETER;
	}

	for (i=0; i < pac_data->num_buffers; i++) {
		struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
		struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i];

		if (data_buf->type != raw_buf->type) {
			DEBUG(0, ("misparse! PAC_DATA buffer %d has type "
				  "%d while PAC_DATA_RAW has %d\n", i,
				  data_buf->type, raw_buf->type));
			return NT_STATUS_INVALID_PARAMETER;
		}
		switch (data_buf->type) {
		case PAC_TYPE_LOGON_INFO:
			if (!data_buf->info) {
				break;
			}
			logon_info = data_buf->info->logon_info.info;
			break;
		case PAC_TYPE_SRV_CHECKSUM:
			if (!data_buf->info) {
				break;
			}
			srv_sig_ptr = &data_buf->info->srv_cksum;
			srv_sig_blob = &raw_buf->info->remaining;
			break;
		case PAC_TYPE_KDC_CHECKSUM:
			if (!data_buf->info) {
				break;
			}
			kdc_sig_ptr = &data_buf->info->kdc_cksum;
			kdc_sig_blob = &raw_buf->info->remaining;
			break;
		case PAC_TYPE_LOGON_NAME:
			logon_name = &data_buf->info->logon_name;
			break;
		default:
			break;
		}
	}

	if (!logon_info) {
		DEBUG(0,("PAC no logon_info\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!logon_name) {
		DEBUG(0,("PAC no logon_name\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!srv_sig_ptr || !srv_sig_blob) {
		DEBUG(0,("PAC no srv_key\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!kdc_sig_ptr || !kdc_sig_blob) {
		DEBUG(0,("PAC no kdc_key\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Find and zero out the signatures,
	 * as required by the signing algorithm */

	/* We find the data blobs above,
	 * now we parse them to get at the exact portion we should zero */
	ndr_err = ndr_pull_struct_blob(
			kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe,
			(ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the KDC signature: %s\n",
			nt_errstr(status)));
		return status;
	}

	ndr_err = ndr_pull_struct_blob(
			srv_sig_blob, srv_sig_wipe, srv_sig_wipe,
			(ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the SRV signature: %s\n",
			nt_errstr(status)));
		return status;
	}

	/* Now zero the decoded structure */
	memset(kdc_sig_wipe->signature.data,
		'\0', kdc_sig_wipe->signature.length);
	memset(srv_sig_wipe->signature.data,
		'\0', srv_sig_wipe->signature.length);

	/* and reencode, back into the same place it came from */
	ndr_err = ndr_push_struct_blob(
			kdc_sig_blob, pac_data_raw, kdc_sig_wipe,
			(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the KDC signature: %s\n",
			nt_errstr(status)));
		return status;
	}
	ndr_err = ndr_push_struct_blob(
			srv_sig_blob, pac_data_raw, srv_sig_wipe,
			(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the SRV signature: %s\n",
			nt_errstr(status)));
		return status;
	}

	/* push out the whole structure, but now with zero'ed signatures */
	ndr_err = ndr_push_struct_blob(
			&modified_pac_blob, pac_data_raw, pac_data_raw,
			(ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the RAW PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	if (service_keyblock) {
		/* verify by service_key */
		ret = check_pac_checksum(mem_ctx,
					 modified_pac_blob, srv_sig_ptr,
					 context,
					 service_keyblock);
		if (ret) {
			DEBUG(1, ("PAC Decode: Failed to verify the service "
				  "signature: %s\n", error_message(ret)));
			return NT_STATUS_ACCESS_DENIED;
		}

		if (krbtgt_keyblock) {
			/* verify the service key checksum by krbtgt_key */
			ret = check_pac_checksum(mem_ctx,
						 srv_sig_ptr->signature, kdc_sig_ptr,
						 context, krbtgt_keyblock);
			if (ret) {
				DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
					  smb_get_krb5_error_message(context, ret, mem_ctx)));
				return NT_STATUS_ACCESS_DENIED;
			}
		}
	}

	if (tgs_authtime) {
		/* Convert to NT time, so as not to loose accuracy in comparison */
		unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);

		if (tgs_authtime_nttime != logon_name->logon_time) {
			DEBUG(2, ("PAC Decode: "
				  "Logon time mismatch between ticket and PAC!\n"));
			DEBUG(2, ("PAC Decode: PAC: %s\n",
				  nt_time_string(mem_ctx, logon_name->logon_time)));
			DEBUG(2, ("PAC Decode: Ticket: %s\n",
				  nt_time_string(mem_ctx, tgs_authtime_nttime)));
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	if (client_principal) {
		ret = smb_krb5_parse_name_norealm(context,
						  logon_name->account_name,
						  &client_principal_pac);
		if (ret) {
			DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n",
				  logon_name->account_name, error_message(ret)));
			return NT_STATUS_INVALID_PARAMETER;
		}

		bool_ret = smb_krb5_principal_compare_any_realm(context,
								client_principal,
								client_principal_pac);

		krb5_free_principal(context, client_principal_pac);

		if (!bool_ret) {
			DEBUG(2, ("Name in PAC [%s] does not match principal name "
				  "in ticket\n", logon_name->account_name));
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	DEBUG(3,("Found account name from PAC: %s [%s]\n",
		 logon_info->info3.base.account_name.string,
		 logon_info->info3.base.full_name.string));

	DEBUG(10,("Successfully validated Kerberos PAC\n"));

	if (DEBUGLEVEL >= 10) {
		const char *s;
		s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_DATA, pac_data);
		if (s) {
			DEBUGADD(10,("%s\n", s));
		}
	}

	*pac_data_out = pac_data;

	return NT_STATUS_OK;
}
Пример #12
0
static NTSTATUS smbXsrv_tcon_global_store(struct smbXsrv_tcon_global0 *global)
{
	struct smbXsrv_tcon_globalB global_blob;
	DATA_BLOB blob = data_blob_null;
	TDB_DATA key;
	TDB_DATA val;
	NTSTATUS status;
	enum ndr_err_code ndr_err;

	/*
	 * TODO: if we use other versions than '0'
	 * we would add glue code here, that would be able to
	 * store the information in the old format.
	 */

	if (global->db_rec == NULL) {
		return NT_STATUS_INTERNAL_ERROR;
	}

	key = dbwrap_record_get_key(global->db_rec);
	val = dbwrap_record_get_value(global->db_rec);

	ZERO_STRUCT(global_blob);
	global_blob.version = smbXsrv_version_global_current();
	if (val.dsize >= 8) {
		global_blob.seqnum = IVAL(val.dptr, 4);
	}
	global_blob.seqnum += 1;
	global_blob.info.info0 = global;

	ndr_err = ndr_push_struct_blob(&blob, global->db_rec, &global_blob,
			(ndr_push_flags_fn_t)ndr_push_smbXsrv_tcon_globalB);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1,("smbXsrv_tcon_global_store: key '%s' ndr_push - %s\n",
			 hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
			 nt_errstr(status)));
		TALLOC_FREE(global->db_rec);
		return status;
	}

	val = make_tdb_data(blob.data, blob.length);
	status = dbwrap_record_store(global->db_rec, val, TDB_REPLACE);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1,("smbXsrv_tcon_global_store: key '%s' store - %s\n",
			 hex_encode_talloc(global->db_rec, key.dptr, key.dsize),
			 nt_errstr(status)));
		TALLOC_FREE(global->db_rec);
		return status;
	}

	if (DEBUGLVL(10)) {
		DEBUG(10,("smbXsrv_tcon_global_store: key '%s' stored\n",
			 hex_encode_talloc(global->db_rec, key.dptr, key.dsize)));
		NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
	}

	TALLOC_FREE(global->db_rec);

	return NT_STATUS_OK;
}
Пример #13
0
static void smbXsrv_tcon_global_verify_record(struct db_record *db_rec,
					bool *is_free,
					bool *was_free,
					TALLOC_CTX *mem_ctx,
					struct smbXsrv_tcon_global0 **_g)
{
	TDB_DATA key;
	TDB_DATA val;
	DATA_BLOB blob;
	struct smbXsrv_tcon_globalB global_blob;
	enum ndr_err_code ndr_err;
	struct smbXsrv_tcon_global0 *global = NULL;
	bool exists;
	TALLOC_CTX *frame = talloc_stackframe();

	*is_free = false;

	if (was_free) {
		*was_free = false;
	}
	if (_g) {
		*_g = NULL;
	}

	key = dbwrap_record_get_key(db_rec);

	val = dbwrap_record_get_value(db_rec);
	if (val.dsize == 0) {
		TALLOC_FREE(frame);
		*is_free = true;
		if (was_free) {
			*was_free = true;
		}
		return;
	}

	blob = data_blob_const(val.dptr, val.dsize);

	ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
			(ndr_pull_flags_fn_t)ndr_pull_smbXsrv_tcon_globalB);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' ndr_pull_struct_blob - %s\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 nt_errstr(status)));
		TALLOC_FREE(frame);
		return;
	}

	DEBUG(10,("smbXsrv_tcon_global_verify_record\n"));
	if (DEBUGLVL(10)) {
		NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
	}

	if (global_blob.version != SMBXSRV_VERSION_0) {
		DEBUG(0,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' use unsupported version %u\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 global_blob.version));
		NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
		TALLOC_FREE(frame);
		return;
	}

	global = global_blob.info.info0;

	exists = serverid_exists(&global->server_id);
	if (!exists) {
		DEBUG(2,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' server_id %s does not exist.\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 server_id_str(frame, &global->server_id)));
		if (DEBUGLVL(2)) {
			NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
		}
		TALLOC_FREE(frame);
		dbwrap_record_delete(db_rec);
		*is_free = true;
		return;
	}

	if (_g) {
		*_g = talloc_move(mem_ctx, &global);
	}
	TALLOC_FREE(frame);
}
Пример #14
0
static void smbXsrv_session_close_loop(struct tevent_req *subreq)
{
	struct smbXsrv_connection *conn =
		tevent_req_callback_data(subreq,
		struct smbXsrv_connection);
	struct smbXsrv_session_table *table = conn->session_table;
	int ret;
	struct messaging_rec *rec = NULL;
	struct smbXsrv_session_closeB close_blob;
	enum ndr_err_code ndr_err;
	struct smbXsrv_session_close0 *close_info0 = NULL;
	struct smbXsrv_session *session = NULL;
	NTSTATUS status;
	struct timeval tv = timeval_current();
	NTTIME now = timeval_to_nttime(&tv);

	ret = msg_read_recv(subreq, talloc_tos(), &rec);
	TALLOC_FREE(subreq);
	if (ret != 0) {
		goto next;
	}

	ndr_err = ndr_pull_struct_blob(&rec->buf, rec, &close_blob,
			(ndr_pull_flags_fn_t)ndr_pull_smbXsrv_session_closeB);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1,("smbXsrv_session_close_loop: "
			 "ndr_pull_struct_blob - %s\n",
			 nt_errstr(status)));
		goto next;
	}

	DEBUG(10,("smbXsrv_session_close_loop: MSG_SMBXSRV_SESSION_CLOSE\n"));
	if (DEBUGLVL(10)) {
		NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
	}

	if (close_blob.version != SMBXSRV_VERSION_0) {
		DEBUG(0,("smbXsrv_session_close_loop: "
			 "ignore invalid version %u\n", close_blob.version));
		NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
		goto next;
	}

	close_info0 = close_blob.info.info0;
	if (close_info0 == NULL) {
		DEBUG(0,("smbXsrv_session_close_loop: "
			 "ignore NULL info %u\n", close_blob.version));
		NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
		goto next;
	}

	status = smb2srv_session_lookup(conn, close_info0->old_session_wire_id,
					now, &session);
	if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
		DEBUG(4,("smbXsrv_session_close_loop: "
			 "old_session_wire_id %llu not found\n",
			 (unsigned long long)close_info0->old_session_wire_id));
		if (DEBUGLVL(4)) {
			NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
		}
		goto next;
	}
	if (!NT_STATUS_IS_OK(status) &&
	    !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
	    !NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
		DEBUG(1,("smbXsrv_session_close_loop: "
			 "old_session_wire_id %llu - %s\n",
			 (unsigned long long)close_info0->old_session_wire_id,
			 nt_errstr(status)));
		if (DEBUGLVL(1)) {
			NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
		}
		goto next;
	}

	if (session->global->session_global_id != close_info0->old_session_global_id) {
		DEBUG(1,("smbXsrv_session_close_loop: "
			 "old_session_wire_id %llu - global %u != %u\n",
			 (unsigned long long)close_info0->old_session_wire_id,
			 session->global->session_global_id,
			 close_info0->old_session_global_id));
		if (DEBUGLVL(1)) {
			NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
		}
		goto next;
	}

	if (session->global->creation_time != close_info0->old_creation_time) {
		DEBUG(1,("smbXsrv_session_close_loop: "
			 "old_session_wire_id %llu - "
			 "creation %s (%llu) != %s (%llu)\n",
			 (unsigned long long)close_info0->old_session_wire_id,
			 nt_time_string(rec, session->global->creation_time),
			 (unsigned long long)session->global->creation_time,
			 nt_time_string(rec, close_info0->old_creation_time),
			 (unsigned long long)close_info0->old_creation_time));
		if (DEBUGLVL(1)) {
			NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
		}
		goto next;
	}

	/*
	 * TODO: cancel all outstanding requests on the session
	 */
	status = smbXsrv_session_logoff(session);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smbXsrv_session_close_loop: "
			  "smbXsrv_session_logoff(%llu) failed: %s\n",
			  (unsigned long long)session->global->session_wire_id,
			  nt_errstr(status)));
		if (DEBUGLVL(1)) {
			NDR_PRINT_DEBUG(smbXsrv_session_closeB, &close_blob);
		}
	}
	TALLOC_FREE(session);

next:
	TALLOC_FREE(rec);

	subreq = msg_read_send(table, conn->ev_ctx, table->close_channel);
	if (subreq == NULL) {
		smbd_server_connection_terminate(conn->sconn,
						 "msg_read_send() failed");
		return;
	}
	tevent_req_set_callback(subreq, smbXsrv_session_close_loop, conn);
}
Пример #15
0
WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
					      const struct dsdb_schema *schema)
{
	WERROR status;
	int ldb_ret;
	struct ldb_message *msg;
	struct ldb_dn *schema_dn;
	struct prefixMapBlob pfm_blob;
	struct ldb_val ndr_blob;
	enum ndr_err_code ndr_err;
	TALLOC_CTX *temp_ctx;
	struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;

	schema_dn = ldb_get_schema_basedn(ldb);
	if (!schema_dn) {
		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: no schema dn present\n"));
		return WERR_FOOBAR;
	}

	temp_ctx = talloc_new(mem_ctx);
	W_ERROR_HAVE_NO_MEMORY(temp_ctx);

	/* convert schema_prefixMap to prefixMap blob */
	status = dsdb_get_oid_mappings_drsuapi(schema, false, temp_ctx, &ctr);
	if (!W_ERROR_IS_OK(status)) {
		talloc_free(temp_ctx);
		return status;
	}

	pfm_blob.version	= PREFIX_MAP_VERSION_DSDB;
	pfm_blob.ctr.dsdb	= *ctr;

	ndr_err = ndr_push_struct_blob(&ndr_blob, temp_ctx,
				       &pfm_blob,
				       (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(temp_ctx);
		return WERR_FOOBAR;
	}
 
	/* write serialized prefixMap into LDB */
	msg = ldb_msg_new(temp_ctx);
	if (!msg) {
		talloc_free(temp_ctx);
		return WERR_NOMEM;
	}

	msg->dn = schema_dn;
	ldb_ret = ldb_msg_add_value(msg, "prefixMap", &ndr_blob, NULL);
	if (ldb_ret != 0) {
		talloc_free(temp_ctx);
		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: ldb_msg_add_value failed\n"));	
		return WERR_NOMEM;
 	}
 
	ldb_ret = dsdb_replace(ldb, msg, DSDB_FLAG_AS_SYSTEM);

	talloc_free(temp_ctx);

	if (ldb_ret != 0) {
		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: dsdb_replace failed\n"));
		return WERR_FOOBAR;
 	}
 
	return WERR_OK;
}
Пример #16
0
static bool api_drsuapi_DsCrackNames(struct pipes_struct *p)
{
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	struct ndr_push *push;
	enum ndr_err_code ndr_err;
	struct drsuapi_DsCrackNames *r;

	call = &ndr_table_drsuapi.calls[NDR_DRSUAPI_DSCRACKNAMES];

	r = talloc(talloc_tos(), struct drsuapi_DsCrackNames);
	if (r == NULL) {
		return false;
	}

	pull = ndr_pull_init_blob(&p->in_data.data, r);
	if (pull == NULL) {
		talloc_free(r);
		return false;
	}

	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	if (p->endian) {
		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
	}
	ndr_err = call->ndr_pull(pull, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsCrackNames, NDR_IN, r);
	}

	ZERO_STRUCT(r->out);
	r->out.level_out = talloc_zero(r, uint32_t);
	if (r->out.level_out == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.ctr = talloc_zero(r, union drsuapi_DsNameCtr);
	if (r->out.ctr == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.result = _drsuapi_DsCrackNames(p, r);

	if (p->fault_state) {
		talloc_free(r);
		/* Return true here, srv_pipe_hnd.c will take care */
		return true;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsCrackNames, NDR_OUT | NDR_SET_VALUES, r);
	}

	push = ndr_push_init_ctx(r);
	if (push == NULL) {
		talloc_free(r);
		return false;
	}

	/*
	 * carry over the pointer count to the reply in case we are
	 * using full pointer. See NDR specification for full pointers
	 */
	push->ptr_count = pull->ptr_count;

	ndr_err = call->ndr_push(push, NDR_OUT, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	p->out_data.rdata = ndr_push_blob(push);
	talloc_steal(p->mem_ctx, p->out_data.rdata.data);

	talloc_free(r);

	return true;
}
Пример #17
0
static bool srv_pipe_check_verification_trailer(struct pipes_struct *p,
						struct ncacn_packet *pkt,
						struct pipe_rpc_fns *pipe_fns)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct dcerpc_sec_verification_trailer *vt = NULL;
	const uint32_t bitmask1 =
		p->auth.client_hdr_signing ? DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
	const struct dcerpc_sec_vt_pcontext pcontext = {
		.abstract_syntax = pipe_fns->syntax,
		.transfer_syntax = ndr_transfer_syntax_ndr,
	};
	const struct dcerpc_sec_vt_header2 header2 =
	       dcerpc_sec_vt_header2_from_ncacn_packet(pkt);
	struct ndr_pull *ndr;
	enum ndr_err_code ndr_err;
	bool ret = false;

	ndr = ndr_pull_init_blob(&p->in_data.data, frame);
	if (ndr == NULL) {
		goto done;
	}

	ndr_err = ndr_pop_dcerpc_sec_verification_trailer(ndr, frame, &vt);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		goto done;
	}

	ret = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
						    &pcontext, &header2);
done:
	TALLOC_FREE(frame);
	return ret;
}

/****************************************************************************
 Find the correct RPC function to call for this request.
 If the pipe is authenticated then become the correct UNIX user
 before doing the call.
****************************************************************************/

static bool api_pipe_request(struct pipes_struct *p,
				struct ncacn_packet *pkt)
{
	TALLOC_CTX *frame = talloc_stackframe();
	bool ret = False;
	struct pipe_rpc_fns *pipe_fns;

	if (!p->pipe_bound) {
		DEBUG(1, ("Pipe not bound!\n"));
		data_blob_free(&p->out_data.rdata);
		TALLOC_FREE(frame);
		return false;
	}

	/* get the set of RPC functions for this context */
	pipe_fns = find_pipe_fns_by_context(p->contexts,
					    pkt->u.request.context_id);
	if (pipe_fns == NULL) {
		DEBUG(0, ("No rpc function table associated with context "
			  "[%d]\n",
			  pkt->u.request.context_id));
		data_blob_free(&p->out_data.rdata);
		TALLOC_FREE(frame);
		return false;
	}

	if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) {
		DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n"));
		setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED));
		data_blob_free(&p->out_data.rdata);
		TALLOC_FREE(frame);
		return true;
	}

	if (!become_authenticated_pipe_user(p->session_info)) {
		DEBUG(1, ("Failed to become pipe user!\n"));
		data_blob_free(&p->out_data.rdata);
		TALLOC_FREE(frame);
		return false;
	}

	DEBUG(5, ("Requested %s rpc service\n",
		  ndr_interface_name(&pipe_fns->syntax.uuid,
				     pipe_fns->syntax.if_version)));

	ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds,
			 &pipe_fns->syntax);
	unbecome_authenticated_pipe_user();

	TALLOC_FREE(frame);
	return ret;
}
Пример #18
0
/*
  support the old Samba3 TXT form of the info3
 */
static NTSTATUS wb_samba3_append_info3_as_txt(TALLOC_CTX *mem_ctx,
					      struct wbsrv_samba3_call *s3call,
					      DATA_BLOB info3b)
{
	struct netr_SamInfo3 *info3;
	char *ex;
	uint32_t i;
	enum ndr_err_code ndr_err;

	info3 = talloc(mem_ctx, struct netr_SamInfo3);
	NT_STATUS_HAVE_NO_MEMORY(info3);

	/* The Samba3 protocol has a redundent 4 bytes at the start */
	info3b.data += 4;
	info3b.length -= 4;

	ndr_err = ndr_pull_struct_blob(&info3b,
				       mem_ctx,
				       lp_iconv_convenience(s3call->wbconn->lp_ctx), 
				       info3,
				       (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return ndr_map_error2ntstatus(ndr_err);
	}

	s3call->response.data.auth.info3.logon_time =
		nt_time_to_unix(info3->base.last_logon);
	s3call->response.data.auth.info3.logoff_time =
		nt_time_to_unix(info3->base.last_logoff);
	s3call->response.data.auth.info3.kickoff_time =
		nt_time_to_unix(info3->base.acct_expiry);
	s3call->response.data.auth.info3.pass_last_set_time =
		nt_time_to_unix(info3->base.last_password_change);
	s3call->response.data.auth.info3.pass_can_change_time =
		nt_time_to_unix(info3->base.allow_password_change);
	s3call->response.data.auth.info3.pass_must_change_time =
		nt_time_to_unix(info3->base.force_password_change);

	s3call->response.data.auth.info3.logon_count = info3->base.logon_count;
	s3call->response.data.auth.info3.bad_pw_count = info3->base.bad_password_count;

	s3call->response.data.auth.info3.user_rid = info3->base.rid;
	s3call->response.data.auth.info3.group_rid = info3->base.primary_gid;
	fstrcpy(s3call->response.data.auth.info3.dom_sid, dom_sid_string(mem_ctx, info3->base.domain_sid));

	s3call->response.data.auth.info3.num_groups = info3->base.groups.count;
	s3call->response.data.auth.info3.user_flgs = info3->base.user_flags;

	s3call->response.data.auth.info3.acct_flags = info3->base.acct_flags;
	s3call->response.data.auth.info3.num_other_sids = info3->sidcount;

	fstrcpy(s3call->response.data.auth.info3.user_name,
		info3->base.account_name.string);
	fstrcpy(s3call->response.data.auth.info3.full_name,
		info3->base.full_name.string);
	fstrcpy(s3call->response.data.auth.info3.logon_script,
		info3->base.logon_script.string);
	fstrcpy(s3call->response.data.auth.info3.profile_path,
		info3->base.profile_path.string);
	fstrcpy(s3call->response.data.auth.info3.home_dir,
		info3->base.home_directory.string);
	fstrcpy(s3call->response.data.auth.info3.dir_drive,
		info3->base.home_drive.string);

	fstrcpy(s3call->response.data.auth.info3.logon_srv,
		info3->base.logon_server.string);
	fstrcpy(s3call->response.data.auth.info3.logon_dom,
		info3->base.domain.string);

	ex = talloc_strdup(mem_ctx, "");
	NT_STATUS_HAVE_NO_MEMORY(ex);

	for (i=0; i < info3->base.groups.count; i++) {
		ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
						   info3->base.groups.rids[i].rid,
						   info3->base.groups.rids[i].attributes);
		NT_STATUS_HAVE_NO_MEMORY(ex);
	}

	for (i=0; i < info3->sidcount; i++) {
		char *sid;

		sid = dom_sid_string(mem_ctx, info3->sids[i].sid);
		NT_STATUS_HAVE_NO_MEMORY(sid);

		ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n",
						   sid,
						   info3->sids[i].attributes);
		NT_STATUS_HAVE_NO_MEMORY(ex);

		talloc_free(sid);
	}

	s3call->response.extra_data.data = ex;
	s3call->response.length += talloc_get_size(ex);

	return NT_STATUS_OK;
}
Пример #19
0
void smb2srv_create_recv(struct smb2srv_request *req)
{
	union smb_open *io;
	DATA_BLOB blob;
	int i;

	SMB2SRV_CHECK_BODY_SIZE(req, 0x38, true);
	SMB2SRV_TALLOC_IO_PTR(io, union smb_open);
	SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_create_send, NTVFS_ASYNC_STATE_MAY_ASYNC);

	ZERO_STRUCT(io->smb2.in);
	io->smb2.level			= RAW_OPEN_SMB2;
	io->smb2.in.security_flags	= CVAL(req->in.body, 0x02);
	io->smb2.in.oplock_level	= CVAL(req->in.body, 0x03);
	io->smb2.in.impersonation_level	= IVAL(req->in.body, 0x04);
	io->smb2.in.create_flags	= BVAL(req->in.body, 0x08);
	io->smb2.in.reserved		= BVAL(req->in.body, 0x10);
	io->smb2.in.desired_access	= IVAL(req->in.body, 0x18);
	io->smb2.in.file_attributes	= IVAL(req->in.body, 0x1C);
	io->smb2.in.share_access	= IVAL(req->in.body, 0x20);
	io->smb2.in.create_disposition	= IVAL(req->in.body, 0x24);
	io->smb2.in.create_options	= IVAL(req->in.body, 0x28);
	SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, io, req->in.body+0x2C, &io->smb2.in.fname));
	SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x30, &blob));
	SMB2SRV_CHECK(smb2_create_blob_parse(io, blob, &io->smb2.in.blobs));

	/* interpret the parsed tags that a server needs to respond to */
	for (i=0;i<io->smb2.in.blobs.num_blobs;i++) {
		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_EXTA) == 0) {
			SMB2SRV_CHECK(ea_pull_list_chained(&io->smb2.in.blobs.blobs[i].data, io, 
							   &io->smb2.in.eas.num_eas,
							   &io->smb2.in.eas.eas));
		}
		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_SECD) == 0) {
			enum ndr_err_code ndr_err;
			io->smb2.in.sec_desc = talloc(io, struct security_descriptor);
			if (io->smb2.in.sec_desc == NULL) {
				smb2srv_send_error(req,  NT_STATUS_NO_MEMORY);
				return;
			}
			ndr_err = ndr_pull_struct_blob(&io->smb2.in.blobs.blobs[i].data, io, NULL,
						       io->smb2.in.sec_desc,
						       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
				smb2srv_send_error(req,  ndr_map_error2ntstatus(ndr_err));
				return;
			}
		}
		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNQ) == 0) {
			io->smb2.in.durable_open = true;
		}
		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_DHNC) == 0) {
			if (io->smb2.in.blobs.blobs[i].data.length != 16) {
				smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
				return;				
			}
			io->smb2.in.durable_handle = talloc(io, struct smb2_handle);
			if (io->smb2.in.durable_handle == NULL) {
				smb2srv_send_error(req,  NT_STATUS_NO_MEMORY);
				return;
			}
			smb2_pull_handle(io->smb2.in.blobs.blobs[i].data.data, io->smb2.in.durable_handle);
		}
		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_ALSI) == 0) {
			if (io->smb2.in.blobs.blobs[i].data.length != 8) {
				smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
				return;				
			}
			io->smb2.in.alloc_size = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);
		}
		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_MXAC) == 0) {
			io->smb2.in.query_maximal_access = true;
		}
		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_TWRP) == 0) {
			if (io->smb2.in.blobs.blobs[i].data.length != 8) {
				smb2srv_send_error(req,  NT_STATUS_INVALID_PARAMETER);
				return;				
			}
			io->smb2.in.timewarp = BVAL(io->smb2.in.blobs.blobs[i].data.data, 0);			
		}
		if (strcmp(io->smb2.in.blobs.blobs[i].tag, SMB2_CREATE_TAG_QFID) == 0) {
			io->smb2.in.query_on_disk_id = true;
		}
	}
		
	/* the VFS backend does not yet handle NULL filenames */
	if (io->smb2.in.fname == NULL) {
		io->smb2.in.fname = "";
	}

	SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, io));
}
Пример #20
0
NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security,
					 TALLOC_CTX *out_mem_ctx,
					 const DATA_BLOB request, DATA_BLOB *reply)
{
	struct gensec_ntlmssp_context *gensec_ntlmssp =
		talloc_get_type_abort(gensec_security->private_data,
				      struct gensec_ntlmssp_context);
	struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
	struct auth4_context *auth_context = gensec_security->auth_context;
	DATA_BLOB struct_blob;
	uint32_t neg_flags = 0;
	uint32_t ntlmssp_command, chal_flags;
	uint8_t cryptkey[8];
	const char *target_name;
	NTSTATUS status;

	/* parse the NTLMSSP packet */
#if 0
	file_save("ntlmssp_negotiate.dat", request.data, request.length);
#endif

	if (request.length) {
		if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd",
							  "NTLMSSP",
							  &ntlmssp_command,
							  &neg_flags)) {
			DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",
				(unsigned int)request.length));
			dump_data(2, request.data, request.length);
			return NT_STATUS_INVALID_PARAMETER;
		}
		debug_ntlmssp_flags(neg_flags);

		if (DEBUGLEVEL >= 10) {
			struct NEGOTIATE_MESSAGE *negotiate = talloc(
				ntlmssp_state, struct NEGOTIATE_MESSAGE);
			if (negotiate != NULL) {
				status = ntlmssp_pull_NEGOTIATE_MESSAGE(
					&request, negotiate, negotiate);
				if (NT_STATUS_IS_OK(status)) {
					NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
							negotiate);
				}
				TALLOC_FREE(negotiate);
			}
		}
	}

	ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, ntlmssp_state->allow_lm_key);

	/* Ask our caller what challenge they would like in the packet */
	if (auth_context->get_ntlm_challenge) {
		status = auth_context->get_ntlm_challenge(auth_context, cryptkey);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
				  nt_errstr(status)));
			return status;
		}
	} else {
		DEBUG(1, ("gensec_ntlmssp_server_negotiate: backend doesn't give a challenge\n"));
		return NT_STATUS_NOT_IMPLEMENTED;
	}

	/* The flags we send back are not just the negotiated flags,
	 * they are also 'what is in this packet'.  Therfore, we
	 * operate on 'chal_flags' from here on
	 */

	chal_flags = ntlmssp_state->neg_flags;

	/* get the right name to fill in as 'target' */
	target_name = ntlmssp_target_name(ntlmssp_state,
					  neg_flags, &chal_flags);
	if (target_name == NULL)
		return NT_STATUS_INVALID_PARAMETER;

	ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);
	ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state,
							cryptkey, 8);

	/* This creates the 'blob' of names that appears at the end of the packet */
	if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO)
	{
		status = msrpc_gen(ntlmssp_state, &struct_blob, "aaaaa",
			  MsvAvNbDomainName, target_name,
			  MsvAvNbComputerName, ntlmssp_state->server.netbios_name,
			  MsvAvDnsDomainName, ntlmssp_state->server.dns_domain,
			  MsvAvDnsComputerName, ntlmssp_state->server.dns_name,
			  MsvAvEOL, "");
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
	} else {
		struct_blob = data_blob_null;
	}

	{
		/* Marshal the packet in the right format, be it unicode or ASCII */
		const char *gen_string;
		DATA_BLOB version_blob = data_blob_null;

		if (chal_flags & NTLMSSP_NEGOTIATE_VERSION) {
			enum ndr_err_code err;
			struct ntlmssp_VERSION vers;

			/* "What Windows returns" as a version number. */
			ZERO_STRUCT(vers);
			vers.ProductMajorVersion = NTLMSSP_WINDOWS_MAJOR_VERSION_6;
			vers.ProductMinorVersion = NTLMSSP_WINDOWS_MINOR_VERSION_1;
			vers.ProductBuild = 0;
			vers.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3;

			err = ndr_push_struct_blob(&version_blob,
						ntlmssp_state,
						&vers,
						(ndr_push_flags_fn_t)ndr_push_ntlmssp_VERSION);

			if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
				data_blob_free(&struct_blob);
				return NT_STATUS_NO_MEMORY;
			}
		}

		if (ntlmssp_state->unicode) {
			gen_string = "CdUdbddBb";
		} else {
			gen_string = "CdAdbddBb";
		}

		status = msrpc_gen(out_mem_ctx, reply, gen_string,
			"NTLMSSP",
			NTLMSSP_CHALLENGE,
			target_name,
			chal_flags,
			cryptkey, 8,
			0, 0,
			struct_blob.data, struct_blob.length,
			version_blob.data, version_blob.length);

		if (!NT_STATUS_IS_OK(status)) {
			data_blob_free(&version_blob);
			data_blob_free(&struct_blob);
			return status;
		}

		data_blob_free(&version_blob);

		if (DEBUGLEVEL >= 10) {
			struct CHALLENGE_MESSAGE *challenge = talloc(
				ntlmssp_state, struct CHALLENGE_MESSAGE);
			if (challenge != NULL) {
				challenge->NegotiateFlags = chal_flags;
				status = ntlmssp_pull_CHALLENGE_MESSAGE(
					reply, challenge, challenge);
				if (NT_STATUS_IS_OK(status)) {
					NDR_PRINT_DEBUG(CHALLENGE_MESSAGE,
							challenge);
				}
				TALLOC_FREE(challenge);
			}
		}
	}

	data_blob_free(&struct_blob);

	ntlmssp_state->expected_state = NTLMSSP_AUTH;

	return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
Пример #21
0
krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx,
					     krb5_pac pac,
					     krb5_context context,
					     struct auth_user_info_dc **user_info_dc,
					     struct PAC_SIGNATURE_DATA *pac_srv_sig,
					     struct PAC_SIGNATURE_DATA *pac_kdc_sig)
{
	NTSTATUS nt_status;
	enum ndr_err_code ndr_err;
	krb5_error_code ret;

	DATA_BLOB pac_logon_info_in, pac_srv_checksum_in, pac_kdc_checksum_in;
	krb5_data k5pac_logon_info_in, k5pac_srv_checksum_in, k5pac_kdc_checksum_in;
	DATA_BLOB pac_upn_dns_info_in;
	krb5_data k5pac_upn_dns_info_in;

	union PAC_INFO info;
	union PAC_INFO _upn_dns_info;
	const struct PAC_UPN_DNS_INFO *upn_dns_info = NULL;
	struct auth_user_info_dc *user_info_dc_out;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);

	if (!tmp_ctx) {
		return ENOMEM;
	}

	ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_LOGON_INFO, &k5pac_logon_info_in);
	if (ret != 0) {
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	pac_logon_info_in = data_blob_const(k5pac_logon_info_in.data, k5pac_logon_info_in.length);

	ndr_err = ndr_pull_union_blob(&pac_logon_info_in, tmp_ctx, &info,
				      PAC_TYPE_LOGON_INFO,
				      (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
	smb_krb5_free_data_contents(context, &k5pac_logon_info_in);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		nt_status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
		talloc_free(tmp_ctx);
		return EINVAL;
	}
	if (info.logon_info.info == NULL) {
		DEBUG(0,("can't parse the PAC LOGON_INFO: missing info pointer\n"));
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_UPN_DNS_INFO,
				  &k5pac_upn_dns_info_in);
	if (ret == ENOENT) {
		ZERO_STRUCT(k5pac_upn_dns_info_in);
		ret = 0;
	}
	if (ret != 0) {
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	pac_upn_dns_info_in = data_blob_const(k5pac_upn_dns_info_in.data,
					      k5pac_upn_dns_info_in.length);

	if (pac_upn_dns_info_in.length != 0) {
		ndr_err = ndr_pull_union_blob(&pac_upn_dns_info_in, tmp_ctx,
					      &_upn_dns_info,
					      PAC_TYPE_UPN_DNS_INFO,
					      (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
		smb_krb5_free_data_contents(context, &k5pac_upn_dns_info_in);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			nt_status = ndr_map_error2ntstatus(ndr_err);
			DEBUG(0,("can't parse the PAC UPN_DNS_INFO: %s\n",
				 nt_errstr(nt_status)));
			talloc_free(tmp_ctx);
			return EINVAL;
		}
		upn_dns_info = &_upn_dns_info.upn_dns_info;
	}

	/* Pull this right into the normal auth sysstem structures */
	nt_status = make_user_info_dc_pac(mem_ctx,
					 info.logon_info.info,
					 upn_dns_info,
					 &user_info_dc_out);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return EINVAL;
	}

	if (pac_srv_sig) {
		ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_SRV_CHECKSUM, &k5pac_srv_checksum_in);
		if (ret != 0) {
			talloc_free(tmp_ctx);
			return ret;
		}

		pac_srv_checksum_in = data_blob_const(k5pac_srv_checksum_in.data, k5pac_srv_checksum_in.length);

		ndr_err = ndr_pull_struct_blob(&pac_srv_checksum_in, pac_srv_sig,
					       pac_srv_sig,
					       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
		smb_krb5_free_data_contents(context, &k5pac_srv_checksum_in);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			nt_status = ndr_map_error2ntstatus(ndr_err);
			DEBUG(0,("can't parse the KDC signature: %s\n",
				 nt_errstr(nt_status)));
			return EINVAL;
		}
	}

	if (pac_kdc_sig) {
		ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_KDC_CHECKSUM, &k5pac_kdc_checksum_in);
		if (ret != 0) {
			talloc_free(tmp_ctx);
			return ret;
		}

		pac_kdc_checksum_in = data_blob_const(k5pac_kdc_checksum_in.data, k5pac_kdc_checksum_in.length);

		ndr_err = ndr_pull_struct_blob(&pac_kdc_checksum_in, pac_kdc_sig,
					       pac_kdc_sig,
					       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
		smb_krb5_free_data_contents(context, &k5pac_kdc_checksum_in);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			nt_status = ndr_map_error2ntstatus(ndr_err);
			DEBUG(0,("can't parse the KDC signature: %s\n",
				 nt_errstr(nt_status)));
			return EINVAL;
		}
	}
	*user_info_dc = user_info_dc_out;

	return 0;
}
Пример #22
0
NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security,
					 TALLOC_CTX *out_mem_ctx,
					 const DATA_BLOB request, DATA_BLOB *reply)
{
	struct gensec_ntlmssp_context *gensec_ntlmssp =
		talloc_get_type_abort(gensec_security->private_data,
				      struct gensec_ntlmssp_context);
	struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state;
	struct auth4_context *auth_context = gensec_security->auth_context;
	DATA_BLOB struct_blob;
	uint32_t neg_flags = 0;
	uint32_t ntlmssp_command, chal_flags;
	uint8_t cryptkey[8];
	const char *target_name;
	NTSTATUS status;
	struct timeval tv_now = timeval_current();
	/*
	 * See [MS-NLMP]
	 *
	 * Windows NT 4.0, windows_2000: use 30 minutes,
	 * Windows XP, Windows Server 2003, Windows Vista,
	 * Windows Server 2008, Windows 7, and Windows Server 2008 R2
	 * use 36 hours.
	 *
	 * Newer systems doesn't check this, likely because the
	 * connectionless NTLMSSP is no longer supported.
	 *
	 * As we expect the AUTHENTICATION_MESSAGE to arrive
	 * directly after the NEGOTIATE_MESSAGE (typically less than
	 * as 1 second later). We use a hard timeout of 30 Minutes.
	 *
	 * We don't look at AUTHENTICATE_MESSAGE.NtChallengeResponse.TimeStamp
	 * instead we just remember our own time.
	 */
	uint32_t max_lifetime = 30 * 60;
	struct timeval tv_end = timeval_add(&tv_now, max_lifetime, 0);

	/* parse the NTLMSSP packet */
#if 0
	file_save("ntlmssp_negotiate.dat", request.data, request.length);
#endif

	if (request.length) {
		if (request.length > UINT16_MAX) {
			DEBUG(1, ("ntlmssp_server_negotiate: reject large request of length %u\n",
				(unsigned int)request.length));
			return NT_STATUS_INVALID_PARAMETER;
		}

		if ((request.length < 16) || !msrpc_parse(ntlmssp_state, &request, "Cdd",
							  "NTLMSSP",
							  &ntlmssp_command,
							  &neg_flags)) {
			DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate of length %u\n",
				(unsigned int)request.length));
			dump_data(2, request.data, request.length);
			return NT_STATUS_INVALID_PARAMETER;
		}
		debug_ntlmssp_flags(neg_flags);

		if (DEBUGLEVEL >= 10) {
			struct NEGOTIATE_MESSAGE *negotiate = talloc(
				ntlmssp_state, struct NEGOTIATE_MESSAGE);
			if (negotiate != NULL) {
				status = ntlmssp_pull_NEGOTIATE_MESSAGE(
					&request, negotiate, negotiate);
				if (NT_STATUS_IS_OK(status)) {
					NDR_PRINT_DEBUG(NEGOTIATE_MESSAGE,
							negotiate);
				}
				TALLOC_FREE(negotiate);
			}
		}
	}

	status = ntlmssp_handle_neg_flags(ntlmssp_state, neg_flags, "negotiate");
	if (!NT_STATUS_IS_OK(status)){
		return status;
	}

	/* Ask our caller what challenge they would like in the packet */
	if (auth_context->get_ntlm_challenge) {
		status = auth_context->get_ntlm_challenge(auth_context, cryptkey);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("gensec_ntlmssp_server_negotiate: failed to get challenge: %s\n",
				  nt_errstr(status)));
			return status;
		}
	} else {
		DEBUG(1, ("gensec_ntlmssp_server_negotiate: backend doesn't give a challenge\n"));
		return NT_STATUS_NOT_IMPLEMENTED;
	}

	/* The flags we send back are not just the negotiated flags,
	 * they are also 'what is in this packet'.  Therfore, we
	 * operate on 'chal_flags' from here on
	 */

	chal_flags = ntlmssp_state->neg_flags;
	ntlmssp_state->server.challenge_endtime = timeval_to_nttime(&tv_end);

	/* get the right name to fill in as 'target' */
	target_name = ntlmssp_target_name(ntlmssp_state,
					  neg_flags, &chal_flags);
	if (target_name == NULL)
		return NT_STATUS_INVALID_PARAMETER;

	ntlmssp_state->chal = data_blob_talloc(ntlmssp_state, cryptkey, 8);
	ntlmssp_state->internal_chal = data_blob_talloc(ntlmssp_state,
							cryptkey, 8);

	/* This creates the 'blob' of names that appears at the end of the packet */
	if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
		enum ndr_err_code err;
		struct AV_PAIR *pairs = NULL;
		uint32_t count = 5;

		pairs = talloc_zero_array(ntlmssp_state, struct AV_PAIR, count + 1);
		if (pairs == NULL) {
			return NT_STATUS_NO_MEMORY;
		}

		pairs[0].AvId			= MsvAvNbDomainName;
		pairs[0].Value.AvNbDomainName	= target_name;

		pairs[1].AvId			= MsvAvNbComputerName;
		pairs[1].Value.AvNbComputerName	= ntlmssp_state->server.netbios_name;

		pairs[2].AvId			= MsvAvDnsDomainName;
		pairs[2].Value.AvDnsDomainName	= ntlmssp_state->server.dns_domain;

		pairs[3].AvId			= MsvAvDnsComputerName;
		pairs[3].Value.AvDnsComputerName= ntlmssp_state->server.dns_name;

		if (!ntlmssp_state->force_old_spnego) {
			pairs[4].AvId			= MsvAvTimestamp;
			pairs[4].Value.AvTimestamp	=
						timeval_to_nttime(&tv_now);
			count += 1;

			pairs[5].AvId			= MsvAvEOL;
		} else {
			pairs[4].AvId			= MsvAvEOL;
		}

		ntlmssp_state->server.av_pair_list.count = count;
		ntlmssp_state->server.av_pair_list.pair = pairs;

		err = ndr_push_struct_blob(&struct_blob,
					ntlmssp_state,
					&ntlmssp_state->server.av_pair_list,
					(ndr_push_flags_fn_t)ndr_push_AV_PAIR_LIST);
		if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
			return NT_STATUS_NO_MEMORY;
		}
	} else {
Пример #23
0
static NTSTATUS rpc_service_list_internal(struct net_context *c,
					const DOM_SID *domain_sid,
					const char *domain_name,
					struct cli_state *cli,
					struct rpc_pipe_client *pipe_hnd,
					TALLOC_CTX *mem_ctx,
					int argc,
					const char **argv )
{
	struct policy_handle hSCM;
	struct ENUM_SERVICE_STATUSW *services = NULL;
	WERROR result = WERR_GENERAL_FAILURE;
	NTSTATUS status;
	int i;

	uint8_t *buffer = NULL;
	uint32_t buf_size = 0;
	uint32_t bytes_needed = 0;
	uint32_t num_services = 0;
	uint32_t resume_handle = 0;

	if (argc != 0 ) {
		d_printf("Usage: net rpc service list\n");
		return NT_STATUS_OK;
	}

	status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx,
					      pipe_hnd->srv_name_slash,
					      NULL,
					      SC_RIGHT_MGR_ENUMERATE_SERVICE,
					      &hSCM,
					      &result);
	if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
		d_fprintf(stderr, "Failed to open Service Control Manager.  [%s]\n", win_errstr(result));
		return werror_to_ntstatus(result);
	}

	do {
		status = rpccli_svcctl_EnumServicesStatusW(pipe_hnd, mem_ctx,
							   &hSCM,
							   SERVICE_TYPE_WIN32,
							   SERVICE_STATE_ALL,
							   buffer,
							   buf_size,
							   &bytes_needed,
							   &num_services,
							   &resume_handle,
							   &result);

		if (NT_STATUS_IS_ERR(status)) {
			d_fprintf(stderr, "Failed to enumerate services.  [%s]\n",
				win_errstr(result));
			break;
		}

		if (W_ERROR_EQUAL(result, WERR_MORE_DATA) && bytes_needed > 0) {
			buffer = talloc_array(mem_ctx, uint8_t, bytes_needed);
			buf_size = bytes_needed;
			continue;
		}

		if ( num_services == 0 ) {
			d_printf("No services returned\n");
			break;
		}

		{
			enum ndr_err_code ndr_err;
			DATA_BLOB blob;
			struct ndr_pull *ndr;

			blob.length = buf_size;
			blob.data = talloc_steal(mem_ctx, buffer);

			services = talloc_array(mem_ctx, struct ENUM_SERVICE_STATUSW, num_services);
			if (!services) {
				status = NT_STATUS_NO_MEMORY;
				break;
			}

			ndr = ndr_pull_init_blob(&blob, mem_ctx, NULL);
			if (ndr == NULL) {
				status = NT_STATUS_NO_MEMORY;
				break;
			}

			ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
				ndr, num_services, services);
			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
				status = ndr_map_error2ntstatus(ndr_err);
				break;
			}

			for ( i=0; i<num_services; i++ ) {
				d_printf("%-20s    \"%s\"\n",
					services[i].service_name,
					services[i].display_name);
			}
		}

	} while (W_ERROR_EQUAL(result, WERR_MORE_DATA));

	rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL);

	return status;
}
Пример #24
0
static NTSTATUS reg_parse_registry(TALLOC_CTX *mem_ctx,
				   uint32_t flags,
				   const char *filename,
				   struct gp_registry_entry **entries_p,
				   size_t *num_entries_p)
{
	DATA_BLOB blob;
	NTSTATUS status;
	enum ndr_err_code ndr_err;
	const char *real_filename = NULL;
	struct preg_file r;
	struct gp_registry_entry *entries = NULL;
	size_t num_entries = 0;
	int i;

	status = gp_find_file(mem_ctx,
			      flags,
			      filename,
			      GP_REGPOL_FILE,
			      &real_filename);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	blob.data = (uint8_t *)file_load(real_filename, &blob.length, 0, NULL);
	if (!blob.data) {
		return NT_STATUS_CANNOT_LOAD_REGISTRY_FILE;
	}

	ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
			(ndr_pull_flags_fn_t)ndr_pull_preg_file);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		goto out;
	}

	if (!strequal(r.header.signature, "PReg")) {
		status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	if (r.header.version != GP_REGPOL_FILE_VERSION) {
		status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	for (i=0; i < r.num_entries; i++) {

		struct gp_registry_entry *r_entry = NULL;

		if (!gp_reg_entry_from_file_entry(mem_ctx,
						  &r.entries[i],
						  &r_entry)) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}

		if (!add_gp_registry_entry_to_array(mem_ctx,
						    r_entry,
						    &entries,
						    &num_entries)) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}
	}

	*entries_p = entries;
	*num_entries_p = num_entries;

	status = NT_STATUS_OK;

 out:
	data_blob_free(&blob);
	return status;
}
Пример #25
0
static bool api_frstrans_RequestUpdates(struct pipes_struct *p)
{
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	struct ndr_push *push;
	enum ndr_err_code ndr_err;
	struct frstrans_RequestUpdates *r;

	call = &ndr_table_frstrans.calls[NDR_FRSTRANS_REQUESTUPDATES];

	r = talloc(talloc_tos(), struct frstrans_RequestUpdates);
	if (r == NULL) {
		return false;
	}

	pull = ndr_pull_init_blob(&p->in_data.data, r);
	if (pull == NULL) {
		talloc_free(r);
		return false;
	}

	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	if (p->endian) {
		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
	}
	ndr_err = call->ndr_pull(pull, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(frstrans_RequestUpdates, NDR_IN, r);
	}

	ZERO_STRUCT(r->out);
	r->out.frs_update = talloc_zero_array(r, struct frstrans_Update, r->in.credits_available);
	if (r->out.frs_update == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.update_count = talloc_zero(r, uint32_t);
	if (r->out.update_count == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.update_status = talloc_zero(r, enum frstrans_UpdateStatus);
	if (r->out.update_status == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.gvsn_db_guid = talloc_zero(r, struct GUID);
	if (r->out.gvsn_db_guid == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.gvsn_version = talloc_zero(r, uint64_t);
	if (r->out.gvsn_version == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.result = _frstrans_RequestUpdates(p, r);

	if (p->fault_state) {
		talloc_free(r);
		/* Return true here, srv_pipe_hnd.c will take care */
		return true;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(frstrans_RequestUpdates, NDR_OUT | NDR_SET_VALUES, r);
	}

	push = ndr_push_init_ctx(r);
	if (push == NULL) {
		talloc_free(r);
		return false;
	}

	/*
	 * carry over the pointer count to the reply in case we are
	 * using full pointer. See NDR specification for full pointers
	 */
	push->ptr_count = pull->ptr_count;

	ndr_err = call->ndr_push(push, NDR_OUT, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	p->out_data.rdata = ndr_push_blob(push);
	talloc_steal(p->mem_ctx, p->out_data.rdata.data);

	talloc_free(r);

	return true;
}
Пример #26
0
static bool api_mgmt_inq_princ_name(struct pipes_struct *p)
{
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	struct ndr_push *push;
	enum ndr_err_code ndr_err;
	struct mgmt_inq_princ_name *r;

	call = &ndr_table_mgmt.calls[NDR_MGMT_INQ_PRINC_NAME];

	r = talloc(talloc_tos(), struct mgmt_inq_princ_name);
	if (r == NULL) {
		return false;
	}

	pull = ndr_pull_init_blob(&p->in_data.data, r);
	if (pull == NULL) {
		talloc_free(r);
		return false;
	}

	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	if (p->endian) {
		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
	}
	ndr_err = call->ndr_pull(pull, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(mgmt_inq_princ_name, NDR_IN, r);
	}

	ZERO_STRUCT(r->out);
	r->out.princ_name = talloc_zero_array(r, const char, r->in.princ_name_size);
	if (r->out.princ_name == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.result = _mgmt_inq_princ_name(p, r);

	if (p->rng_fault_state) {
		talloc_free(r);
		/* Return true here, srv_pipe_hnd.c will take care */
		return true;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(mgmt_inq_princ_name, NDR_OUT | NDR_SET_VALUES, r);
	}

	push = ndr_push_init_ctx(r);
	if (push == NULL) {
		talloc_free(r);
		return false;
	}

	/*
	 * carry over the pointer count to the reply in case we are
	 * using full pointer. See NDR specification for full pointers
	 */
	push->ptr_count = pull->ptr_count;

	ndr_err = call->ndr_push(push, NDR_OUT, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	p->out_data.rdata = ndr_push_blob(push);
	talloc_steal(p->mem_ctx, p->out_data.rdata.data);

	talloc_free(r);

	return true;
}
Пример #27
0
static bool api_FRSTRANS_RDC_CLOSE(struct pipes_struct *p)
{
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	struct ndr_push *push;
	enum ndr_err_code ndr_err;
	struct FRSTRANS_RDC_CLOSE *r;

	call = &ndr_table_frstrans.calls[NDR_FRSTRANS_RDC_CLOSE];

	r = talloc(talloc_tos(), struct FRSTRANS_RDC_CLOSE);
	if (r == NULL) {
		return false;
	}

	pull = ndr_pull_init_blob(&p->in_data.data, r);
	if (pull == NULL) {
		talloc_free(r);
		return false;
	}

	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	if (p->endian) {
		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
	}
	ndr_err = call->ndr_pull(pull, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(FRSTRANS_RDC_CLOSE, NDR_IN, r);
	}

	_FRSTRANS_RDC_CLOSE(p, r);

	if (p->fault_state) {
		talloc_free(r);
		/* Return true here, srv_pipe_hnd.c will take care */
		return true;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(FRSTRANS_RDC_CLOSE, NDR_OUT | NDR_SET_VALUES, r);
	}

	push = ndr_push_init_ctx(r);
	if (push == NULL) {
		talloc_free(r);
		return false;
	}

	/*
	 * carry over the pointer count to the reply in case we are
	 * using full pointer. See NDR specification for full pointers
	 */
	push->ptr_count = pull->ptr_count;

	ndr_err = call->ndr_push(push, NDR_OUT, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	p->out_data.rdata = ndr_push_blob(push);
	talloc_steal(p->mem_ctx, p->out_data.rdata.data);

	talloc_free(r);

	return true;
}
Пример #28
0
NTSTATUS parse_netlogon_request(struct ldb_parse_tree *tree,
				struct loadparm_context *lp_ctx,
				TALLOC_CTX *tmp_ctx,
				const char **domain,
				const char **host,
				const char **user,
				const char **domain_guid,
				struct dom_sid **domain_sid,
				int *acct_control,
				int *version)
{
	unsigned int i;

	*domain = NULL;
	*host = NULL;
	*user = NULL;
	*domain_guid = NULL;
	*domain_sid = NULL;
	*acct_control = -1;
	*version = -1;

	if (tree->operation != LDB_OP_AND) goto failed;

	/* extract the query elements */
	for (i=0;i<tree->u.list.num_elements;i++) {
		struct ldb_parse_tree *t = tree->u.list.elements[i];
		if (t->operation != LDB_OP_EQUALITY) goto failed;
		if (strcasecmp(t->u.equality.attr, "DnsDomain") == 0) {
			*domain = talloc_strndup(tmp_ctx,
						(const char *)t->u.equality.value.data,
						t->u.equality.value.length);
		}
		if (strcasecmp(t->u.equality.attr, "Host") == 0) {
			*host = talloc_strndup(tmp_ctx,
					      (const char *)t->u.equality.value.data,
					      t->u.equality.value.length);
		}
		if (strcasecmp(t->u.equality.attr, "DomainGuid") == 0) {
			NTSTATUS enc_status;
			struct GUID guid;
			enc_status = ldap_decode_ndr_GUID(tmp_ctx, 
							  t->u.equality.value, &guid);
			if (NT_STATUS_IS_OK(enc_status)) {
				*domain_guid = GUID_string(tmp_ctx, &guid);
			}
		}
		if (strcasecmp(t->u.equality.attr, "DomainSid") == 0) {
			enum ndr_err_code ndr_err;

			*domain_sid = talloc(tmp_ctx, struct dom_sid);
			if (*domain_sid == NULL) {
				goto failed;
			}
			ndr_err = ndr_pull_struct_blob(&t->u.equality.value,
						       *domain_sid, *domain_sid,
						       (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
				talloc_free(*domain_sid);
				goto failed;
			}
		}
		if (strcasecmp(t->u.equality.attr, "User") == 0) {
			*user = talloc_strndup(tmp_ctx,
					       (const char *)t->u.equality.value.data,
					       t->u.equality.value.length);
		}
		if (strcasecmp(t->u.equality.attr, "NtVer") == 0 &&
		    t->u.equality.value.length == 4) {
			*version = IVAL(t->u.equality.value.data, 0);
		}
		if (strcasecmp(t->u.equality.attr, "AAC") == 0 &&
		    t->u.equality.value.length == 4) {
			*acct_control = IVAL(t->u.equality.value.data, 0);
		}
	}

	if ((*domain == NULL) && (*domain_guid == NULL) && (*domain_sid == NULL)) {
		*domain = lpcfg_dnsdomain(lp_ctx);
	}

	if (*version == -1) {
		goto failed;
	}

	return NT_STATUS_OK;

failed:
	return NT_STATUS_UNSUCCESSFUL;
}
Пример #29
0
static bool api_wbint_LookupGroupMembers(struct pipes_struct *p)
{
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	struct ndr_push *push;
	enum ndr_err_code ndr_err;
	struct wbint_LookupGroupMembers *r;

	call = &ndr_table_wbint.calls[NDR_WBINT_LOOKUPGROUPMEMBERS];

	r = talloc(talloc_tos(), struct wbint_LookupGroupMembers);
	if (r == NULL) {
		return false;
	}

	pull = ndr_pull_init_blob(&p->in_data.data, r);
	if (pull == NULL) {
		talloc_free(r);
		return false;
	}

	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	if (p->endian) {
		pull->flags |= LIBNDR_FLAG_BIGENDIAN;
	}
	ndr_err = call->ndr_pull(pull, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(wbint_LookupGroupMembers, NDR_IN, r);
	}

	ZERO_STRUCT(r->out);
	r->out.members = talloc_zero(r, struct wbint_Principals);
	if (r->out.members == NULL) {
		talloc_free(r);
		return false;
	}

	r->out.result = _wbint_LookupGroupMembers(p, r);

	if (p->fault_state) {
		talloc_free(r);
		/* Return true here, srv_pipe_hnd.c will take care */
		return true;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_FUNCTION_DEBUG(wbint_LookupGroupMembers, NDR_OUT | NDR_SET_VALUES, r);
	}

	push = ndr_push_init_ctx(r);
	if (push == NULL) {
		talloc_free(r);
		return false;
	}

	/*
	 * carry over the pointer count to the reply in case we are
	 * using full pointer. See NDR specification for full pointers
	 */
	push->ptr_count = pull->ptr_count;

	ndr_err = call->ndr_push(push, NDR_OUT, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(r);
		return false;
	}

	p->out_data.rdata = ndr_push_blob(push);
	talloc_steal(p->mem_ctx, p->out_data.rdata.data);

	talloc_free(r);

	return true;
}
Пример #30
0
/**
 * Retrieve the domain SID from the secrets database.
 * @return pointer to a SID object if the SID could be obtained, NULL otherwise
 */
struct dom_sid *secrets_get_domain_sid(TALLOC_CTX *mem_ctx,
				       struct loadparm_context *lp_ctx,
				       const char *domain,
				       enum netr_SchannelType *sec_channel_type,
				       char **errstring)
{
	struct ldb_context *ldb;
	struct ldb_message *msg;
	int ldb_ret;
	const char *attrs[] = { "objectSid", "secureChannelType", NULL };
	struct dom_sid *result = NULL;
	const struct ldb_val *v;
	enum ndr_err_code ndr_err;

	*errstring = NULL;

	ldb = secrets_db_connect(mem_ctx, lp_ctx);
	if (ldb == NULL) {
		DEBUG(5, ("secrets_db_connect failed\n"));
		return NULL;
	}

	ldb_ret = dsdb_search_one(ldb, ldb, &msg,
			      ldb_dn_new(mem_ctx, ldb, SECRETS_PRIMARY_DOMAIN_DN),
			      LDB_SCOPE_ONELEVEL,
			      attrs, 0, SECRETS_PRIMARY_DOMAIN_FILTER, domain);

	if (ldb_ret != LDB_SUCCESS) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to find record for %s in %s: %s: %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"),
					     ldb_strerror(ldb_ret), ldb_errstring(ldb));
		return NULL;
	}
	v = ldb_msg_find_ldb_val(msg, "objectSid");
	if (v == NULL) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to find a SID on record for %s in %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
		return NULL;
	}

	if (sec_channel_type) {
		int t;
		t = ldb_msg_find_attr_as_int(msg, "secureChannelType", -1);
		if (t == -1) {
			*errstring = talloc_asprintf(mem_ctx, "Failed to find secureChannelType for %s in %s",
						     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
			return NULL;
		}
		*sec_channel_type = t;
	}

	result = talloc(mem_ctx, struct dom_sid);
	if (result == NULL) {
		talloc_free(ldb);
		return NULL;
	}

	ndr_err = ndr_pull_struct_blob(v, result, result,
				       (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to parse SID on record for %s in %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
		talloc_free(result);
		talloc_free(ldb);
		return NULL;
	}

	return result;
}