示例#1
0
static NTSTATUS ep_register(TALLOC_CTX *mem_ctx,
			    const struct ndr_interface_table *iface,
			    const struct dcerpc_binding_vector *bind_vec,
			    const struct GUID *object_guid,
			    const char *annotation,
			    uint32_t replace,
			    uint32_t unregister,
			    struct dcerpc_binding_handle **pbh)
{
	struct rpc_pipe_client *cli = NULL;
	struct dcerpc_binding_handle *h;
	struct pipe_auth_data *auth;
	const char *ncalrpc_sock;
	const char *rpcsrv_type;
	struct epm_entry_t *entries;
	uint32_t num_ents, i;
	TALLOC_CTX *tmp_ctx;
	uint32_t result = EPMAPPER_STATUS_OK;
	NTSTATUS status;

	if (iface == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (bind_vec == NULL || bind_vec->count == 0) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	tmp_ctx = talloc_stackframe();
	if (tmp_ctx == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM,
					   "rpc_server", "epmapper",
					   "none");

	if (StrCaseCmp(rpcsrv_type, "embedded") == 0) {
		static struct client_address client_id;

		strlcpy(client_id.addr, "localhost", sizeof(client_id.addr));
		client_id.name = "localhost";

		status = rpcint_binding_handle(tmp_ctx,
					       &ndr_table_epmapper,
					       &client_id,
					       get_session_info_system(),
					       server_messaging_context(),
					       &h);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("dcerpc_ep_register: Could not connect to "
				  "epmapper (%s)", nt_errstr(status)));
			goto done;
		}
	} else if (StrCaseCmp(rpcsrv_type, "daemon") == 0) {
		/* Connect to the endpoint mapper locally */
		ncalrpc_sock = talloc_asprintf(tmp_ctx,
					      "%s/%s",
					      lp_ncalrpc_dir(),
					      "EPMAPPER");
		if (ncalrpc_sock == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto done;
		}

		status = rpc_pipe_open_ncalrpc(tmp_ctx,
					       ncalrpc_sock,
					       &ndr_table_epmapper.syntax_id,
					       &cli);
		if (!NT_STATUS_IS_OK(status)) {
			goto done;
		}

		status = rpccli_ncalrpc_bind_data(cli, &auth);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Failed to initialize anonymous bind.\n"));
			goto done;
		}

		status = rpc_pipe_bind(cli, auth);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2, ("Failed to bind ncalrpc socket.\n"));
			goto done;
		}

		h = cli->binding_handle;
	} else {
		status = NT_STATUS_INVALID_PARAMETER;
		goto done;
	}

	num_ents = bind_vec->count;
	entries = talloc_array(tmp_ctx, struct epm_entry_t, num_ents);

	for (i = 0; i < num_ents; i++) {
		struct dcerpc_binding *map_binding = &bind_vec->bindings[i];
		struct epm_twr_t *map_tower;

		map_tower = talloc_zero(entries, struct epm_twr_t);
		if (map_tower == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto done;
		}

		status = dcerpc_binding_build_tower(entries,
						    map_binding,
						    &map_tower->tower);
		if (!NT_STATUS_IS_OK(status)) {
			goto done;
		}

		entries[i].tower = map_tower;
		if (annotation == NULL) {
			entries[i].annotation = talloc_strdup(entries, "");
		} else {
			entries[i].annotation = talloc_strndup(entries,
							       annotation,
							       EPM_MAX_ANNOTATION_SIZE);
		}
		if (entries[i].annotation == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto done;
		}

		if (object_guid != NULL) {
			entries[i].object = *object_guid;
		} else {
			entries[i].object = map_binding->object.uuid;
		}
	}

	if (unregister) {
		status = dcerpc_epm_Delete(h,
					   tmp_ctx,
					   num_ents,
					   entries,
					   &result);
	} else {
		status = dcerpc_epm_Insert(h,
					   tmp_ctx,
					   num_ents,
					   entries,
					   replace,
					   &result);
	}
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("dcerpc_ep_register: Could not insert tower (%s)\n",
			  nt_errstr(status)));
		goto done;
	}
	if (result != EPMAPPER_STATUS_OK) {
		DEBUG(0, ("dcerpc_ep_register: Could not insert tower (0x%.8x)\n",
			  result));
		status = NT_STATUS_UNSUCCESSFUL;
		goto done;
	}

	if (pbh != NULL) {
		*pbh = talloc_move(mem_ctx, &h);
		talloc_steal(*pbh, cli);
	}

done:
	talloc_free(tmp_ctx);

	return status;
}
示例#2
0
NTSTATUS dcerpc_binding_vector_create(TALLOC_CTX *mem_ctx,
				      const struct ndr_interface_table *iface,
				      uint16_t port,
				      const char *ncalrpc,
				      struct dcerpc_binding_vector **pbvec)
{
	struct dcerpc_binding_vector *bvec;
	uint32_t ep_count;
	uint32_t count = 0;
	uint32_t i;
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx;

	tmp_ctx = talloc_stackframe();
	if (tmp_ctx == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	ep_count = iface->endpoints->count;

	bvec = talloc_zero(tmp_ctx, struct dcerpc_binding_vector);
	if (bvec == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	bvec->bindings = talloc_zero_array(bvec, struct dcerpc_binding, ep_count);
	if (bvec->bindings == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	for (i = 0; i < ep_count; i++) {
		struct dcerpc_binding *b;

		b = talloc_zero(bvec->bindings, struct dcerpc_binding);
		if (b == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto done;
		}

		status = dcerpc_parse_binding(b, iface->endpoints->names[i], &b);
		if (!NT_STATUS_IS_OK(status)) {
			status = NT_STATUS_UNSUCCESSFUL;
			goto done;
		}

		b->object = iface->syntax_id;

		switch (b->transport) {
			case NCACN_NP:
				b->host = talloc_asprintf(b, "\\\\%s", global_myname());
				if (b->host == NULL) {
					status = NT_STATUS_NO_MEMORY;
					goto done;
				}
				break;
			case NCACN_IP_TCP:
				if (port == 0) {
					talloc_free(b);
					continue;
				}

				b->endpoint = talloc_asprintf(b, "%u", port);
				if (b->endpoint == NULL) {
					status = NT_STATUS_NO_MEMORY;
					goto done;
				}

				break;
			case NCALRPC:
				if (ncalrpc == NULL) {
					talloc_free(b);
					continue;
				}

				b->endpoint = talloc_asprintf(b,
							      "%s/%s",
							      lp_ncalrpc_dir(),
							      ncalrpc);
				if (b->endpoint == NULL) {
					status = NT_STATUS_NO_MEMORY;
					goto done;
				}
				break;
			default:
				talloc_free(b);
				continue;
		}

		bvec->bindings[count] = *b;
		count++;
	}

	bvec->count = count;

	*pbvec = talloc_move(mem_ctx, &bvec);

	status = NT_STATUS_OK;
done:
	talloc_free(tmp_ctx);

	return status;
}
示例#3
0
static void smbXsrv_session_global_verify_record(struct db_record *db_rec,
					bool *is_free,
					bool *was_free,
					TALLOC_CTX *mem_ctx,
					struct smbXsrv_session_global0 **_g)
{
	TDB_DATA key;
	TDB_DATA val;
	DATA_BLOB blob;
	struct smbXsrv_session_globalB global_blob;
	enum ndr_err_code ndr_err;
	struct smbXsrv_session_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_session_globalB);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1,("smbXsrv_session_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_session_global_verify_record\n"));
	if (DEBUGLVL(10)) {
		NDR_PRINT_DEBUG(smbXsrv_session_globalB, &global_blob);
	}

	if (global_blob.version != SMBXSRV_VERSION_0) {
		DEBUG(0,("smbXsrv_session_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_session_globalB, &global_blob);
		TALLOC_FREE(frame);
		return;
	}

	global = global_blob.info.info0;

	exists = serverid_exists(&global->channels[0].server_id);
	if (!exists) {
		struct server_id_buf idbuf;
		DEBUG(2,("smbXsrv_session_global_verify_record: "
			 "key '%s' server_id %s does not exist.\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 server_id_str_buf(global->channels[0].server_id,
					   &idbuf)));
		if (DEBUGLVL(2)) {
			NDR_PRINT_DEBUG(smbXsrv_session_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);
}
示例#4
0
static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
				       const char *in_path,
				       uint8_t *out_share_type,
				       uint32_t *out_share_flags,
				       uint32_t *out_capabilities,
				       uint32_t *out_maximal_access,
				       uint32_t *out_tree_id)
{
	struct smbXsrv_connection *conn = req->xconn;
	const char *share = in_path;
	char *service = NULL;
	int snum = -1;
	struct smbXsrv_tcon *tcon;
	NTTIME now = timeval_to_nttime(&req->request_time);
	connection_struct *compat_conn = NULL;
	struct user_struct *compat_vuser = req->session->compat;
	NTSTATUS status;
	bool encryption_required = req->session->global->encryption_required;
	bool guest_session = false;

	if (strncmp(share, "\\\\", 2) == 0) {
		const char *p = strchr(share+2, '\\');
		if (p) {
			share = p + 1;
		}
	}

	DEBUG(10,("smbd_smb2_tree_connect: path[%s] share[%s]\n",
		  in_path, share));

	service = talloc_strdup(talloc_tos(), share);
	if(!service) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!strlower_m(service)) {
		DEBUG(2, ("strlower_m %s failed\n", service));
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* TODO: do more things... */
	if (strequal(service,HOMES_NAME)) {
		if (compat_vuser->homes_snum == -1) {
			DEBUG(2, ("[homes] share not available for "
				"user %s because it was not found "
				"or created at session setup "
				"time\n",
				compat_vuser->session_info->unix_info->unix_name));
			return NT_STATUS_BAD_NETWORK_NAME;
		}
		snum = compat_vuser->homes_snum;
	} else if ((compat_vuser->homes_snum != -1)
                   && strequal(service,
			lp_servicename(talloc_tos(), compat_vuser->homes_snum))) {
		snum = compat_vuser->homes_snum;
	} else {
		snum = find_service(talloc_tos(), service, &service);
		if (!service) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	if (snum < 0) {
		DEBUG(3,("smbd_smb2_tree_connect: couldn't find service %s\n",
			 service));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	if (lp_smb_encrypt(snum) == SMB_SIGNING_REQUIRED) {
		encryption_required = true;
	}

	if (security_session_user_level(compat_vuser->session_info, NULL) < SECURITY_USER) {
		guest_session = true;
	}

	if (guest_session && encryption_required) {
		DEBUG(1,("reject guest as encryption is required for service %s\n",
			 service));
		return NT_STATUS_ACCESS_DENIED;
	}

	if (conn->smb2.server.cipher == 0) {
		if (encryption_required) {
			DEBUG(1,("reject tcon with dialect[0x%04X] "
				 "as encryption is required for service %s\n",
				 conn->smb2.server.dialect, service));
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	/* create a new tcon as child of the session */
	status = smb2srv_tcon_create(req->session, now, &tcon);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	tcon->global->encryption_required = encryption_required;

	compat_conn = make_connection_smb2(req,
					tcon, snum,
					req->session->compat,
					"???",
					&status);
	if (compat_conn == NULL) {
		TALLOC_FREE(tcon);
		return status;
	}

	tcon->global->share_name = lp_servicename(tcon->global,
						  SNUM(compat_conn));
	if (tcon->global->share_name == NULL) {
		conn_free(compat_conn);
		TALLOC_FREE(tcon);
		return NT_STATUS_NO_MEMORY;
	}
	tcon->global->session_global_id =
		req->session->global->session_global_id;

	tcon->compat = talloc_move(tcon, &compat_conn);

	tcon->status = NT_STATUS_OK;

	status = smbXsrv_tcon_update(tcon);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(tcon);
		return status;
	}

	if (IS_PRINT(tcon->compat)) {
		*out_share_type = SMB2_SHARE_TYPE_PRINT;
	} else if (IS_IPC(tcon->compat)) {
		*out_share_type = SMB2_SHARE_TYPE_PIPE;
	} else {
		*out_share_type = SMB2_SHARE_TYPE_DISK;
	}

	*out_share_flags = 0;

	if (lp_msdfs_root(SNUM(tcon->compat)) && lp_host_msdfs()) {
		*out_share_flags |= (SMB2_SHAREFLAG_DFS|SMB2_SHAREFLAG_DFS_ROOT);
		*out_capabilities = SMB2_SHARE_CAP_DFS;
	} else {
		*out_capabilities = 0;
	}

	switch(lp_csc_policy(SNUM(tcon->compat))) {
	case CSC_POLICY_MANUAL:
		break;
	case CSC_POLICY_DOCUMENTS:
		*out_share_flags |= SMB2_SHAREFLAG_AUTO_CACHING;
		break;
	case CSC_POLICY_PROGRAMS:
		*out_share_flags |= SMB2_SHAREFLAG_VDO_CACHING;
		break;
	case CSC_POLICY_DISABLE:
		*out_share_flags |= SMB2_SHAREFLAG_NO_CACHING;
		break;
	default:
		break;
	}

	if (lp_hide_unreadable(SNUM(tcon->compat)) ||
	    lp_hide_unwriteable_files(SNUM(tcon->compat))) {
		*out_share_flags |= SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM;
	}

	if (encryption_required) {
		*out_share_flags |= SMB2_SHAREFLAG_ENCRYPT_DATA;
	}

	*out_maximal_access = tcon->compat->share_access;

	*out_tree_id = tcon->global->tcon_wire_id;
	return NT_STATUS_OK;
}
示例#5
0
/*
 * epm_Insert
 *
 * Add the specified entries to an endpoint map.
 */
error_status_t _epm_Insert(struct pipes_struct *p,
			   struct epm_Insert *r)
{
	TALLOC_CTX *tmp_ctx;
	error_status_t rc;
	NTSTATUS status;
	uint32_t i;
	struct dcerpc_binding *b;
	struct dcesrv_endpoint *ep;
	struct dcesrv_iface_list *iflist;
	struct dcesrv_iface *iface;
	bool add_ep;

	/* If this is not a priviledged users, return */
	if (p->transport != NCALRPC ||
	    !is_priviledged_pipe(p->session_info)) {
		p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
		return EPMAPPER_STATUS_CANT_PERFORM_OP;
	}

	tmp_ctx = talloc_stackframe();
	if (tmp_ctx == NULL) {
		return EPMAPPER_STATUS_NO_MEMORY;
	}

	DEBUG(3, ("_epm_Insert: Trying to add %u new entries.\n",
		  r->in.num_ents));

	for (i = 0; i < r->in.num_ents; i++) {
		add_ep = false;
		b = NULL;

		status = dcerpc_binding_from_tower(tmp_ctx,
						   &r->in.entries[i].tower->tower,
						   &b);
		if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
			rc = EPMAPPER_STATUS_NO_MEMORY;
			goto done;
		}
		if (!NT_STATUS_IS_OK(status)) {
			rc = EPMAPPER_STATUS_CANT_PERFORM_OP;
			goto done;
		}

		DEBUG(3, ("_epm_Insert: Adding transport %s for %s\n",
			  derpc_transport_string_by_transport(b->transport),
			  r->in.entries[i].annotation));

		/* Check if the entry already exits */
		ep = find_endpoint(endpoint_table, b);
		if (ep == NULL) {
			/* No entry found, create it */
			ep = talloc_zero(NULL, struct dcesrv_endpoint);
			if (ep == NULL) {
				rc = EPMAPPER_STATUS_NO_MEMORY;
				goto done;
			}
			add_ep = true;

			ep->ep_description = talloc_steal(ep, b);
		}

		/* TODO Replace the entry if the replace flag is set */

		/* Create an interface */
		iface = talloc(tmp_ctx, struct dcesrv_iface);
		if (iface == NULL) {
			rc = EPMAPPER_STATUS_NO_MEMORY;
			goto done;
		}

		iface->name = talloc_strdup(iface, r->in.entries[i].annotation);
		if (iface->name == NULL) {
			rc = EPMAPPER_STATUS_NO_MEMORY;
			goto done;
		}
		iface->syntax_id = b->object;

		/*
		 * Check if the rpc service is alrady registered on the
		 * endpoint.
		 */
		if (find_interface(ep, iface) != NULL) {
			DEBUG(0, ("dcesrv_interface_register: interface '%s' "
				  "already registered on endpoint\n",
				  iface->name));
			/* FIXME wrong error code? */
			rc = EPMAPPER_STATUS_OK;
			goto done;
		}

		/* Create an entry for the interface */
		iflist = talloc(ep, struct dcesrv_iface_list);
		if (iflist == NULL) {
			rc = EPMAPPER_STATUS_NO_MEMORY;
			goto done;
		}
		iflist->iface = talloc_move(iflist, &iface);

		/* Finally add the interface on the endpoint */
		DLIST_ADD(ep->iface_list, iflist);

		/* If it's a new endpoint add it to the endpoint_table */
		if (add_ep) {
			DLIST_ADD(endpoint_table, ep);
		}
	}
示例#6
0
文件: service.c 项目: 285858315/samba
static connection_struct *make_connection_smb1(struct smb_request *req,
					NTTIME now,
					int snum, struct user_struct *vuser,
					const char *pdev,
					NTSTATUS *pstatus)
{
	struct smbXsrv_tcon *tcon;
	NTSTATUS status;
	struct connection_struct *conn;

	status = smb1srv_tcon_create(req->xconn, now, &tcon);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
			 nt_errstr(status)));
		*pstatus = status;
		return NULL;
	}

	conn = conn_new(req->sconn);
	if (!conn) {
		TALLOC_FREE(tcon);

		DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
		*pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}

	conn->cnum = tcon->global->tcon_wire_id;
	conn->tcon = tcon;

	*pstatus = make_connection_snum(req->xconn,
					conn,
					snum,
					vuser,
					pdev);
	if (!NT_STATUS_IS_OK(*pstatus)) {
		conn_free(conn);
		TALLOC_FREE(tcon);
		return NULL;
	}

	tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
	if (tcon->global->share_name == NULL) {
		conn_free(conn);
		TALLOC_FREE(tcon);
		*pstatus = NT_STATUS_NO_MEMORY;
		return NULL;
	}
	tcon->global->session_global_id =
		vuser->session->global->session_global_id;

	tcon->compat = talloc_move(tcon, &conn);
	tcon->status = NT_STATUS_OK;

	*pstatus = smbXsrv_tcon_update(tcon);
	if (!NT_STATUS_IS_OK(*pstatus)) {
		TALLOC_FREE(tcon);
		return NULL;
	}

	return tcon->compat;
}
/**
 * get the list of share names defined in the configuration.
 */
static WERROR smbconf_txt_get_share_names(struct smbconf_ctx *ctx,
					  TALLOC_CTX *mem_ctx,
					  uint32_t *num_shares,
					  char ***share_names)
{
	uint32_t count;
	uint32_t added_count = 0;
	TALLOC_CTX *tmp_ctx = NULL;
	WERROR werr = WERR_OK;
	char **tmp_share_names = NULL;

	if ((num_shares == NULL) || (share_names == NULL)) {
		werr = WERR_INVALID_PARAM;
		goto done;
	}

	werr = smbconf_txt_load_file(ctx);
	if (!W_ERROR_IS_OK(werr)) {
		return werr;
	}

	tmp_ctx = talloc_stackframe();

	/* make sure "global" is always listed first,
	 * possibly after NULL section */

	if (smbconf_share_exists(ctx, NULL)) {
		werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
						   0, NULL);
		if (!W_ERROR_IS_OK(werr)) {
			goto done;
		}
		added_count++;
	}

	if (smbconf_share_exists(ctx, GLOBAL_NAME)) {
		werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
						   added_count, GLOBAL_NAME);
		if (!W_ERROR_IS_OK(werr)) {
			goto done;
		}
		added_count++;
	}

	for (count = 0; count < pd(ctx)->cache->num_shares; count++) {
		if (strequal(pd(ctx)->cache->share_names[count], GLOBAL_NAME) ||
		    (pd(ctx)->cache->share_names[count] == NULL))
		{
			continue;
		}

		werr = smbconf_add_string_to_array(tmp_ctx, &tmp_share_names,
					added_count,
					pd(ctx)->cache->share_names[count]);
		if (!W_ERROR_IS_OK(werr)) {
			goto done;
		}
		added_count++;
	}

	*num_shares = added_count;
	if (added_count > 0) {
		*share_names = talloc_move(mem_ctx, &tmp_share_names);
	} else {
		*share_names = NULL;
	}

done:
	talloc_free(tmp_ctx);
	return werr;
}
示例#8
0
NTSTATUS dcerpc_winreg_enum_keys(TALLOC_CTX *mem_ctx,
				 struct dcerpc_binding_handle *h,
				 struct policy_handle *key_hnd,
				 uint32_t *pnum_subkeys,
				 const char ***psubkeys,
				 WERROR *pwerr)
{
	const char **subkeys;
	uint32_t num_subkeys, max_subkeylen, max_classlen;
	uint32_t num_values, max_valnamelen, max_valbufsize;
	uint32_t i;
	NTTIME last_changed_time;
	uint32_t secdescsize;
	struct winreg_String classname;
	WERROR result = WERR_OK;
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx;

	tmp_ctx = talloc_stackframe();
	if (tmp_ctx == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCT(classname);

	status = dcerpc_winreg_QueryInfoKey(h,
					    tmp_ctx,
					    key_hnd,
					    &classname,
					    &num_subkeys,
					    &max_subkeylen,
					    &max_classlen,
					    &num_values,
					    &max_valnamelen,
					    &max_valbufsize,
					    &secdescsize,
					    &last_changed_time,
					    &result);
	if (!NT_STATUS_IS_OK(status)) {
		goto error;
	}
	if (!W_ERROR_IS_OK(result)) {
		*pwerr = result;
		goto error;
	}

	subkeys = talloc_zero_array(tmp_ctx, const char *, num_subkeys + 2);
	if (subkeys == NULL) {
		*pwerr = WERR_NOMEM;
		goto error;
	}

	if (num_subkeys == 0) {
		subkeys[0] = talloc_strdup(subkeys, "");
		if (subkeys[0] == NULL) {
			*pwerr = WERR_NOMEM;
			goto error;
		}
		*pnum_subkeys = 0;
		if (psubkeys) {
			*psubkeys = talloc_move(mem_ctx, &subkeys);
		}

		TALLOC_FREE(tmp_ctx);
		return NT_STATUS_OK;
	}

	for (i = 0; i < num_subkeys; i++) {
		char c = '\0';
		char n = '\0';
		char *name = NULL;
		struct winreg_StringBuf class_buf;
		struct winreg_StringBuf name_buf;
		NTTIME modtime;

		class_buf.name = &c;
		class_buf.size = max_classlen + 2;
		class_buf.length = 0;

		name_buf.name = &n;
		name_buf.size = max_subkeylen + 2;
		name_buf.length = 0;

		ZERO_STRUCT(modtime);

		status = dcerpc_winreg_EnumKey(h,
					       tmp_ctx,
					       key_hnd,
					       i,
					       &name_buf,
					       &class_buf,
					       &modtime,
					       &result);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
				  nt_errstr(status)));
			goto error;
		}

		if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
			*pwerr = WERR_OK;
			break;
		}
		if (!W_ERROR_IS_OK(result)) {
			DEBUG(5, ("dcerpc_winreg_enum_keys: Could not enumerate keys: %s\n",
				  win_errstr(result)));
			*pwerr = result;
			goto error;
		}

		if (name_buf.name == NULL) {
			*pwerr = WERR_INVALID_PARAMETER;
			goto error;
		}

		name = talloc_strdup(subkeys, name_buf.name);
		if (name == NULL) {
			*pwerr = WERR_NOMEM;
			goto error;
		}

		subkeys[i] = name;
	}

	*pnum_subkeys = num_subkeys;
	if (psubkeys) {
		*psubkeys = talloc_move(mem_ctx, &subkeys);
	}

 error:
	TALLOC_FREE(tmp_ctx);

	return status;
}
示例#9
0
static NTSTATUS idmap_tdb_open_db(struct idmap_domain *dom)
{
	NTSTATUS ret;
	TALLOC_CTX *mem_ctx;
	char *tdbfile = NULL;
	struct db_context *db = NULL;
	int32_t version;
	bool config_error = false;
	struct idmap_tdb_context *ctx;

	ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);

	if (ctx->db) {
		/* it is already open */
		return NT_STATUS_OK;
	}

	/* use our own context here */
	mem_ctx = talloc_stackframe();

	/* use the old database if present */
	tdbfile = state_path("winbindd_idmap.tdb");
	if (!tdbfile) {
		DEBUG(0, ("Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	DEBUG(10,("Opening tdbfile %s\n", tdbfile ));

	/* Open idmap repository */
	db = db_open(mem_ctx, tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644,
		     DBWRAP_LOCK_ORDER_1);
	if (!db) {
		DEBUG(0, ("Unable to open idmap database\n"));
		ret = NT_STATUS_UNSUCCESSFUL;
		goto done;
	}

	/* check against earlier versions */
	ret = dbwrap_fetch_int32(db, "IDMAP_VERSION", &version);
	if (!NT_STATUS_IS_OK(ret)) {
		version = -1;
	}

	if (version != IDMAP_VERSION) {
		if (config_error) {
			DEBUG(0,("Upgrade of IDMAP_VERSION from %d to %d is not "
				 "possible with incomplete configuration\n",
				 version, IDMAP_VERSION));
			ret = NT_STATUS_UNSUCCESSFUL;
			goto done;
		}
		if (dbwrap_transaction_start(db) != 0) {
			DEBUG(0, ("Unable to start upgrade transaction!\n"));
			ret = NT_STATUS_INTERNAL_DB_ERROR;
			goto done;
		}

		if (!idmap_tdb_upgrade(dom, db)) {
			dbwrap_transaction_cancel(db);
			DEBUG(0, ("Unable to open idmap database, it's in an old format, and upgrade failed!\n"));
			ret = NT_STATUS_INTERNAL_DB_ERROR;
			goto done;
		}

		if (dbwrap_transaction_commit(db) != 0) {
			DEBUG(0, ("Unable to commit upgrade transaction!\n"));
			ret = NT_STATUS_INTERNAL_DB_ERROR;
			goto done;
		}
	}

	ctx->db = talloc_move(ctx, &db);

	ret = idmap_tdb_init_hwm(dom);

done:
	talloc_free(mem_ctx);
	return ret;
}
示例#10
0
static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
{
    TALLOC_CTX *tmp_ctx = NULL;
    struct sss_domain_info *dom = dctx->domain;
    struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx;
    struct cli_ctx *cli_ctx = dctx->cmd_ctx->cli_ctx;
    struct ldb_result *user;
    time_t cache_expire = 0;
    struct tevent_req *dpreq;
    struct dp_callback_ctx *cb_ctx;
    const char *original_name = NULL;
    const char *extra_flag = NULL;
    char *name = NULL;
    uid_t uid = 0;
    errno_t ret;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
        return ENOMEM;
    }

    while (dom) {
       /* if it is a domainless search, skip domains that require fully
        * qualified names instead */
        while (dom && cmd_ctx->check_next && dom->fqnames) {
            dom = get_next_domain(dom, false);
        }

        if (!dom) break;

        /* make sure to update the dctx if we changed domain */
        dctx->domain = dom;

        talloc_free(name);
        name = sss_get_cased_name(tmp_ctx, cmd_ctx->username,
                                  dom->case_sensitive);
        if (name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
            ret = ENOMEM;
            goto done;
        }

        name = sss_reverse_replace_space(tmp_ctx, name,
                                         cmd_ctx->sudo_ctx->rctx->override_space);
        if (name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "sss_reverse_replace_whitespaces failed\n");
            return ENOMEM;
        }

        DEBUG(SSSDBG_FUNC_DATA, "Requesting info about [%s@%s]\n",
              name, dom->name);

        ret = sysdb_getpwnam_with_views(dctx, dctx->domain, name, &user);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  "Failed to make request to our cache!\n");
            ret = EIO;
            goto done;
        }

        if (user->count > 1) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "getpwnam call returned more than one result !?!\n");
            ret = EIO;
            goto done;
        }

        if (user->count == 0 && !dctx->check_provider) {
            /* if a multidomain search, try with next */
            if (cmd_ctx->check_next) {
                dctx->check_provider = true;
                dom = get_next_domain(dom, false);
                if (dom) continue;
            }

            DEBUG(SSSDBG_MINOR_FAILURE, "No results for getpwnam call\n");
            ret = ENOENT;
            goto done;
        }

        /* One result found, check cache expiry */
        if (user->count == 1) {
            cache_expire = ldb_msg_find_attr_as_uint64(user->msgs[0],
                                                       SYSDB_CACHE_EXPIRE, 0);
        }

        /* If cache miss and we haven't checked DP yet OR the entry is
         * outdated, go to DP */
        if ((user->count == 0 || cache_expire < time(NULL))
            && dctx->check_provider) {

            if (DOM_HAS_VIEWS(dom) && user->count == 0) {
                extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
            }

            dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx,
                                            dom, false, SSS_DP_INITGROUPS,
                                            cmd_ctx->username, 0, extra_flag);
            if (!dpreq) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      "Out of memory sending data provider request\n");
                ret = ENOMEM;
                goto done;
            }

            cb_ctx = talloc_zero(cli_ctx, struct dp_callback_ctx);
            if(!cb_ctx) {
                talloc_zfree(dpreq);
                ret = ENOMEM;
                goto done;
            }

            cb_ctx->callback = sudosrv_check_user_dp_callback;
            cb_ctx->ptr = dctx;
            cb_ctx->cctx = cli_ctx;
            cb_ctx->mem_ctx = cli_ctx;

            tevent_req_set_callback(dpreq, sudosrv_dp_send_acct_req_done, cb_ctx);

            /* tell caller we are in an async call */
            ret = EAGAIN;
            goto done;
        }

        /* check uid */
        uid = sss_view_ldb_msg_find_attr_as_uint64(dom, user->msgs[0],
                                                   SYSDB_UIDNUM, 0);
        if (uid != cmd_ctx->uid) {
            /* if a multidomain search, try with next */
            if (cmd_ctx->check_next) {
                dctx->check_provider = true;
                dom = get_next_domain(dom, false);
                if (dom) continue;
            }

            DEBUG(SSSDBG_MINOR_FAILURE, "UID does not match\n");
            ret = ENOENT;
            goto done;
        }

        /* user is stored in cache, remember cased and original name */
        original_name = ldb_msg_find_attr_as_string(user->msgs[0],
                                                    SYSDB_NAME, NULL);
        if (original_name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n");
            ret = EFAULT;
            goto done;
        }

        cmd_ctx->cased_username = talloc_move(cmd_ctx, &name);
        cmd_ctx->orig_username = talloc_strdup(cmd_ctx, original_name);
        if (cmd_ctx->orig_username == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
            ret = ENOMEM;
            goto done;
        }

        /* and set domain */
        cmd_ctx->domain = dom;

        DEBUG(SSSDBG_TRACE_FUNC, "Returning info for user [%s@%s]\n",
              cmd_ctx->username, dctx->domain->name);
        ret = EOK;
        goto done;
    }

    ret = ENOENT;
done:
    talloc_free(tmp_ctx);
    return ret;
}
示例#11
0
static NTSTATUS smbd_smb2_bind_auth_return(struct smbXsrv_session *session,
					   struct smbXsrv_session_auth0 **_auth,
					   struct smbd_smb2_request *smb2req,
					   struct auth_session_info *session_info,
					   uint16_t *out_session_flags,
					   uint64_t *out_session_id)
{
	NTSTATUS status;
	struct smbXsrv_session *x = session;
	struct smbXsrv_session_auth0 *auth = *_auth;
	struct smbXsrv_connection *xconn = smb2req->xconn;
	struct smbXsrv_channel_global0 *c = NULL;
	uint8_t session_key[16];
	size_t i;
	struct _derivation {
		DATA_BLOB label;
		DATA_BLOB context;
	};
	struct {
		struct _derivation signing;
	} derivation = { };
	bool ok;

	*_auth = NULL;

	if (xconn->protocol >= PROTOCOL_SMB3_10) {
		struct smbXsrv_preauth *preauth;
		struct _derivation *d;
		DATA_BLOB p;
		struct hc_sha512state sctx;

		preauth = talloc_move(smb2req, &auth->preauth);

		samba_SHA512_Init(&sctx);
		samba_SHA512_Update(&sctx, preauth->sha512_value,
				    sizeof(preauth->sha512_value));
		for (i = 1; i < smb2req->in.vector_count; i++) {
			samba_SHA512_Update(&sctx,
					    smb2req->in.vector[i].iov_base,
					    smb2req->in.vector[i].iov_len);
		}
		samba_SHA512_Final(preauth->sha512_value, &sctx);

		p = data_blob_const(preauth->sha512_value,
				    sizeof(preauth->sha512_value));

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMBSigningKey");
		d->context = p;

	} else if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d;

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMB2AESCMAC");
		d->context = data_blob_string_const_null("SmbSign");
	}

	status = smbXsrv_session_find_channel(session, xconn, &c);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	ok = security_token_is_sid(session_info->security_token,
			&x->global->auth_session_info->security_token->sids[0]);
	if (!ok) {
		return NT_STATUS_NOT_SUPPORTED;
	}

	if (session_info->session_key.length == 0) {
		/* See [MS-SMB2] 3.3.5.2.4 for the return code. */
		return NT_STATUS_NOT_SUPPORTED;
	}

	ZERO_STRUCT(session_key);
	memcpy(session_key, session_info->session_key.data,
	       MIN(session_info->session_key.length, sizeof(session_key)));

	c->signing_key = data_blob_talloc(x->global,
					  session_key,
					  sizeof(session_key));
	if (c->signing_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.signing;

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    c->signing_key.data);
	}
	ZERO_STRUCT(session_key);

	TALLOC_FREE(auth);
	status = smbXsrv_session_update(session);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
			  (unsigned long long)session->compat->vuid,
			  nt_errstr(status)));
		return NT_STATUS_LOGON_FAILURE;
	}

	*out_session_id = session->global->session_wire_id;

	return NT_STATUS_OK;
}
示例#12
0
NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
				  TALLOC_CTX *out_mem_ctx,
				  const DATA_BLOB in, DATA_BLOB *out)
{
	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;
	uint32_t chal_flags, ntlmssp_command, unkn1 = 0, unkn2 = 0;
	DATA_BLOB server_domain_blob;
	DATA_BLOB challenge_blob;
	DATA_BLOB target_info = data_blob(NULL, 0);
	char *server_domain;
	const char *chal_parse_string;
	const char *chal_parse_string_short = NULL;
	const char *auth_gen_string;
	DATA_BLOB lm_response = data_blob(NULL, 0);
	DATA_BLOB nt_response = data_blob(NULL, 0);
	DATA_BLOB session_key = data_blob(NULL, 0);
	DATA_BLOB lm_session_key = data_blob(NULL, 0);
	DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
	NTSTATUS nt_status;
	int flags = 0;
	const char *user = NULL, *domain = NULL, *workstation = NULL;
	bool is_anonymous = false;
	const DATA_BLOB version_blob = ntlmssp_version_blob();

	TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
	if (!mem_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!msrpc_parse(mem_ctx,
			 &in, "CdBd",
			 "NTLMSSP",
			 &ntlmssp_command,
			 &server_domain_blob,
			 &chal_flags)) {
		DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
		dump_data(2, in.data, in.length);
		talloc_free(mem_ctx);

		return NT_STATUS_INVALID_PARAMETER;
	}

	data_blob_free(&server_domain_blob);

	DEBUG(3, ("Got challenge flags:\n"));
	debug_ntlmssp_flags(chal_flags);

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

	if (ntlmssp_state->unicode) {
		if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
			chal_parse_string = "CdUdbddB";
		} else {
			chal_parse_string = "CdUdbdd";
			chal_parse_string_short = "CdUdb";
		}
		auth_gen_string = "CdBBUUUBdb";
	} else {
		if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) {
			chal_parse_string = "CdAdbddB";
		} else {
			chal_parse_string = "CdAdbdd";
			chal_parse_string_short = "CdAdb";
		}

		auth_gen_string = "CdBBAAABdb";
	}

	if (!msrpc_parse(mem_ctx,
			 &in, chal_parse_string,
			 "NTLMSSP",
			 &ntlmssp_command,
			 &server_domain,
			 &chal_flags,
			 &challenge_blob, 8,
			 &unkn1, &unkn2,
			 &target_info)) {

		bool ok = false;

		DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));

		if (chal_parse_string_short != NULL) {
			/*
			 * In the case where NTLMSSP_NEGOTIATE_TARGET_INFO
			 * is not used, some NTLMSSP servers don't return
			 * the unused unkn1 and unkn2 fields.
			 * See bug:
			 * https://bugzilla.samba.org/show_bug.cgi?id=10016
			 * for packet traces.
			 * Try and parse again without them.
			 */
			ok = msrpc_parse(mem_ctx,
				&in, chal_parse_string_short,
				"NTLMSSP",
				&ntlmssp_command,
				&server_domain,
				&chal_flags,
				&challenge_blob, 8);
			if (!ok) {
				DEBUG(1, ("Failed to short parse "
					"the NTLMSSP Challenge: (#2)\n"));
			}
		}

		if (!ok) {
			dump_data(2, in.data, in.length);
			talloc_free(mem_ctx);
			return NT_STATUS_INVALID_PARAMETER;
		}
	}

	if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) {
		ntlmssp_state->server.is_standalone = true;
	} else {
		ntlmssp_state->server.is_standalone = false;
	}
	/* TODO: parse struct_blob and fill in the rest */
	ntlmssp_state->server.netbios_name = "";
	ntlmssp_state->server.netbios_domain = talloc_move(ntlmssp_state, &server_domain);
	ntlmssp_state->server.dns_name = "";
	ntlmssp_state->server.dns_domain = "";

	if (challenge_blob.length != 8) {
		talloc_free(mem_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	is_anonymous = cli_credentials_is_anonymous(gensec_security->credentials);
	cli_credentials_get_ntlm_username_domain(gensec_security->credentials, mem_ctx,
						 &user, &domain);

	workstation = cli_credentials_get_workstation(gensec_security->credentials);

	if (user == NULL) {
		DEBUG(10, ("User is NULL, returning INVALID_PARAMETER\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (domain == NULL) {
		DEBUG(10, ("Domain is NULL, returning INVALID_PARAMETER\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (workstation == NULL) {
		DEBUG(10, ("Workstation is NULL, returning INVALID_PARAMETER\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (is_anonymous) {
		ntlmssp_state->neg_flags |= NTLMSSP_ANONYMOUS;
		/*
		 * don't use the ccache for anonymous auth
		 */
		ntlmssp_state->use_ccache = false;
	}
	if (ntlmssp_state->use_ccache) {
		struct samr_Password *nt_hash = NULL;

		/*
		 * If we have a password given we don't
		 * use the ccache
		 */
		nt_hash = cli_credentials_get_nt_hash(gensec_security->credentials,
						      mem_ctx);
		if (nt_hash != NULL) {
			ZERO_STRUCTP(nt_hash);
			TALLOC_FREE(nt_hash);
			ntlmssp_state->use_ccache = false;
		}
	}

	if (ntlmssp_state->use_ccache) {
		struct wbcCredentialCacheParams params;
		struct wbcCredentialCacheInfo *info = NULL;
		struct wbcAuthErrorInfo *error = NULL;
		struct wbcNamedBlob auth_blobs[1];
		const struct wbcBlob *wbc_auth_blob = NULL;
		const struct wbcBlob *wbc_session_key = NULL;
		wbcErr wbc_status;
		int i;

		params.account_name = user;
		params.domain_name = domain;
		params.level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP;

		auth_blobs[0].name = "challenge_blob";
		auth_blobs[0].flags = 0;
		auth_blobs[0].blob.data = in.data;
		auth_blobs[0].blob.length = in.length;
		params.num_blobs = ARRAY_SIZE(auth_blobs);
		params.blobs = auth_blobs;

		wbc_status = wbcCredentialCache(&params, &info, &error);
		wbcFreeMemory(error);
		if (!WBC_ERROR_IS_OK(wbc_status)) {
			return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
		}

		for (i=0; i<info->num_blobs; i++) {
			if (strequal(info->blobs[i].name, "auth_blob")) {
				wbc_auth_blob = &info->blobs[i].blob;
			}
			if (strequal(info->blobs[i].name, "session_key")) {
				wbc_session_key = &info->blobs[i].blob;
			}
		}
		if ((wbc_auth_blob == NULL) || (wbc_session_key == NULL)) {
			wbcFreeMemory(info);
			return NT_STATUS_WRONG_CREDENTIAL_HANDLE;
		}

		session_key = data_blob_talloc(mem_ctx,
					       wbc_session_key->data,
					       wbc_session_key->length);
		if (session_key.length != wbc_session_key->length) {
			wbcFreeMemory(info);
			return NT_STATUS_NO_MEMORY;
		}
		*out = data_blob_talloc(mem_ctx,
					wbc_auth_blob->data,
					wbc_auth_blob->length);
		if (out->length != wbc_auth_blob->length) {
			wbcFreeMemory(info);
			return NT_STATUS_NO_MEMORY;
		}

		wbcFreeMemory(info);
		goto done;
	}

	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
		flags |= CLI_CRED_NTLM2;
	}
	if (ntlmssp_state->use_ntlmv2) {
		flags |= CLI_CRED_NTLMv2_AUTH;
	}
	if (ntlmssp_state->use_nt_response) {
		flags |= CLI_CRED_NTLM_AUTH;
	}
	if (lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx)) {
		flags |= CLI_CRED_LANMAN_AUTH;
	}

	nt_status = cli_credentials_get_ntlm_response(gensec_security->credentials, mem_ctx,
						      &flags, challenge_blob, target_info,
						      &lm_response, &nt_response,
						      &lm_session_key, &session_key);

	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	if (!(flags & CLI_CRED_LANMAN_AUTH)) {
		/* LM Key is still possible, just silly, so we do not
		 * allow it. Fortunetly all LM crypto is off by
		 * default and we require command line options to end
		 * up here */
		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
	}

	if (!(flags & CLI_CRED_NTLM2)) {
		/* NTLM2 is incompatible... */
		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
	}

	if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)
	    && lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx) && lm_session_key.length == 16) {
		DATA_BLOB new_session_key = data_blob_talloc(mem_ctx, NULL, 16);
		if (lm_response.length == 24) {
			SMBsesskeygen_lm_sess_key(lm_session_key.data, lm_response.data,
						  new_session_key.data);
		} else {
			static const uint8_t zeros[24];
			SMBsesskeygen_lm_sess_key(lm_session_key.data, zeros,
						  new_session_key.data);
		}
		session_key = new_session_key;
		dump_data_pw("LM session key\n", session_key.data, session_key.length);
	}


	/* Key exchange encryptes a new client-generated session key with
	   the password-derived key */
	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
		/* Make up a new session key */
		uint8_t client_session_key[16];
		generate_secret_buffer(client_session_key, sizeof(client_session_key));

		/* Encrypt the new session key with the old one */
		encrypted_session_key = data_blob_talloc(ntlmssp_state,
							 client_session_key, sizeof(client_session_key));
		dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
		arcfour_crypt(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
		dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);

		/* Mark the new session key as the 'real' session key */
		session_key = data_blob_talloc(mem_ctx, client_session_key, sizeof(client_session_key));
	}

	/* this generates the actual auth packet */
	nt_status = msrpc_gen(mem_ctx,
		       out, auth_gen_string,
		       "NTLMSSP",
		       NTLMSSP_AUTH,
		       lm_response.data, lm_response.length,
		       nt_response.data, nt_response.length,
		       domain,
		       user,
		       workstation,
		       encrypted_session_key.data, encrypted_session_key.length,
		       ntlmssp_state->neg_flags,
		       version_blob.data, version_blob.length);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(mem_ctx);
		return nt_status;
	}

done:
	ntlmssp_state->session_key = session_key;
	talloc_steal(ntlmssp_state, session_key.data);

	DEBUG(3, ("NTLMSSP: Set final flags:\n"));
	debug_ntlmssp_flags(ntlmssp_state->neg_flags);

	talloc_steal(out_mem_ctx, out->data);

	ntlmssp_state->expected_state = NTLMSSP_DONE;

	if (gensec_security->want_features & (GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL)) {
		nt_status = ntlmssp_sign_init(ntlmssp_state);
		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n",
				  nt_errstr(nt_status)));
			talloc_free(mem_ctx);
			return nt_status;
		}
	}

	talloc_free(mem_ctx);
	return NT_STATUS_OK;
}
示例#13
0
文件: nss_obfuscate.c 项目: 3van/sssd
int sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded,
                         char **password)
{
    SECStatus sret;
    int ret;
    TALLOC_CTX *tmp_ctx = NULL;
    struct crypto_mech_data *mech_props;
    struct sss_nss_crypto_ctx *cctx;

    int plainlen;
    unsigned int digestlen;
    unsigned char *obfbuf = NULL;
    size_t obflen;
    char *pwdbuf;

    /* for unmarshaling data */
    uint16_t meth;
    uint16_t ctsize;
    size_t p = 0;
    unsigned char *cryptotext;
    unsigned char *keybuf;
    unsigned char *ivbuf;
    unsigned char sentinel_check[OBF_BUFFER_SENTINEL_SIZE];

    tmp_ctx = talloc_new(mem_ctx);
    if (!tmp_ctx) {
        return ENOMEM;
    }

    /* initialize NSS if needed */
    ret = nspr_nss_init();
    if (ret != EOK) {
        ret = EIO;
        goto done;
    }

    /* Base64 decode the incoming buffer */
    obfbuf = sss_base64_decode(tmp_ctx, b64encoded, &obflen);
    if (!obfbuf) {
        ret = ENOMEM;
        goto done;
    }

    /* unpack obfuscation buffer */
    SAFEALIGN_COPY_UINT16_CHECK(&meth, obfbuf+p, obflen, &p);
    DEBUG(SSSDBG_TRACE_INTERNAL, "Read method: %d\n", meth);
    SAFEALIGN_COPY_UINT16_CHECK(&ctsize, obfbuf+p, obflen, &p);
    DEBUG(SSSDBG_TRACE_INTERNAL, "Read bufsize: %d\n", ctsize);

    mech_props = get_crypto_mech_data(meth);
    if (mech_props == NULL) {
        ret = EINVAL;
        goto done;
    }

    /* check that we got sane mechanism properties and cryptotext size */
    memcpy(sentinel_check,
           obfbuf + p + mech_props->keylen + mech_props->bsize + ctsize,
           OBF_BUFFER_SENTINEL_SIZE);
    if (memcmp(sentinel_check, OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE) != 0) {
        DEBUG(SSSDBG_FATAL_FAILURE,
              "Obfuscation buffer seems corrupt, aborting\n");
        ret = EFAULT;
        goto done;
    }

    /* copy out key, ivbuf and cryptotext */
    keybuf = talloc_array(tmp_ctx, unsigned char, mech_props->keylen);
    if (keybuf == NULL) {
        ret = ENOMEM;
        goto done;
    }
    safealign_memcpy(keybuf, obfbuf+p, mech_props->keylen, &p);

    ivbuf = talloc_array(tmp_ctx, unsigned char, mech_props->bsize);
    if (ivbuf == NULL) {
        ret = ENOMEM;
        goto done;
    }
    safealign_memcpy(ivbuf, obfbuf+p, mech_props->bsize, &p);

    cryptotext = talloc_array(tmp_ctx, unsigned char, ctsize);
    if (cryptotext == NULL) {
        ret = ENOMEM;
        goto done;
    }
    safealign_memcpy(cryptotext, obfbuf+p, ctsize, &p);

    ret = nss_ctx_init(tmp_ctx, mech_props, &cctx);
    if (ret) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n");
        goto done;
    }

    cctx->iv = talloc_zero(cctx, SECItem);
    cctx->key = talloc_zero(cctx, SECItem);
    if (!cctx->iv || !cctx->key) {
        ret = ENOMEM;
        goto done;
    }

    MAKE_SECITEM(ivbuf, mech_props->bsize, cctx->iv);
    MAKE_SECITEM(keybuf, mech_props->keylen, cctx->key);

    ret = nss_encrypt_decrypt_init(mech_props, false, cctx);
    if (ret) {
        goto done;
    }

    pwdbuf = talloc_array(tmp_ctx, char, ctsize);
    if (!pwdbuf) {
        ret = ENOMEM;
        goto done;
    }

    sret = PK11_CipherOp(cctx->ectx, (unsigned char *) pwdbuf, &plainlen, ctsize,
                         cryptotext, ctsize);
    if (sret != SECSuccess) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Cannot execute the encryption operation (err %d)\n",
                   PR_GetError());
        ret = EIO;
        goto done;
    }

    sret = PK11_DigestFinal(cctx->ectx, (unsigned char *) pwdbuf+plainlen, &digestlen,
                            ctsize - plainlen);
    if (sret != SECSuccess) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Cannot execute the encryption operation (err %d)\n",
                   PR_GetError());
        ret = EIO;
        goto done;
    }

    *password = talloc_move(mem_ctx, &pwdbuf);
    ret = EOK;
done:
    talloc_free(tmp_ctx);
    nspr_nss_cleanup();
    return ret;
}
示例#14
0
bool is_printer_published(TALLOC_CTX *mem_ctx,
			  const struct auth_session_info *session_info,
			  struct messaging_context *msg_ctx,
			  const char *servername, char *printer, struct GUID *guid,
			  struct spoolss_PrinterInfo2 **info2)
{
	struct spoolss_PrinterInfo2 *pinfo2 = NULL;
	enum winreg_Type type;
	uint8_t *data;
	uint32_t data_size;
	WERROR result;
	NTSTATUS status;
	struct dcerpc_binding_handle *b;

	result = winreg_printer_binding_handle(mem_ctx,
					       session_info,
					       msg_ctx,
					       &b);
	if (!W_ERROR_IS_OK(result)) {
		return false;
	}

	result = winreg_get_printer(mem_ctx, b,
				    printer, &pinfo2);
	if (!W_ERROR_IS_OK(result)) {
		return false;
	}

	if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
		TALLOC_FREE(pinfo2);
		return false;
	}

	if (!guid) {
		goto done;
	}

	/* fetching printer guids really ought to be a separate function. */

	result = winreg_get_printer_dataex(mem_ctx, b,
					   printer,
					   SPOOL_DSSPOOLER_KEY, "objectGUID",
					   &type, &data, &data_size);
	if (!W_ERROR_IS_OK(result)) {
		TALLOC_FREE(pinfo2);
		return false;
	}

	/* We used to store the guid as REG_BINARY, then swapped
	   to REG_SZ for Vista compatibility so check for both */

	switch (type) {
	case REG_SZ:
		status = GUID_from_string((char *)data, guid);
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_FREE(pinfo2);
			return false;
		}
		break;

	case REG_BINARY:
		if (data_size != sizeof(struct GUID)) {
			TALLOC_FREE(pinfo2);
			return false;
		}
		memcpy(guid, data, sizeof(struct GUID));
		break;
	default:
		DEBUG(0,("is_printer_published: GUID value stored as "
			 "invaluid type (%d)\n", type));
		break;
	}

done:
	if (info2) {
		*info2 = talloc_move(mem_ctx, &pinfo2);
	}
	talloc_free(pinfo2);
	return true;
}
/**
 * get a definition of a share (service) from configuration.
 */
static WERROR smbconf_txt_get_share(struct smbconf_ctx *ctx,
				    TALLOC_CTX *mem_ctx,
				    const char *servicename,
				    struct smbconf_service **service)
{
	WERROR werr;
	uint32_t sidx, count;
	bool found;
	TALLOC_CTX *tmp_ctx = NULL;
	struct smbconf_service *tmp_service = NULL;

	werr = smbconf_txt_load_file(ctx);
	if (!W_ERROR_IS_OK(werr)) {
		return werr;
	}

	found = smbconf_find_in_array(servicename,
				      pd(ctx)->cache->share_names,
				      pd(ctx)->cache->num_shares,
				      &sidx);
	if (!found) {
		return WERR_NO_SUCH_SERVICE;
	}

	tmp_ctx = talloc_stackframe();

	tmp_service = TALLOC_ZERO_P(tmp_ctx, struct smbconf_service);
	if (tmp_service == NULL) {
		werr = WERR_NOMEM;
		goto done;
	}

	if (servicename != NULL) {
		tmp_service->name = talloc_strdup(tmp_service, servicename);
		if (tmp_service->name == NULL) {
			werr = WERR_NOMEM;
			goto done;
		}
	}

	for (count = 0; count < pd(ctx)->cache->num_params[sidx]; count++) {
		werr = smbconf_add_string_to_array(tmp_service,
				&(tmp_service->param_names),
				count,
				pd(ctx)->cache->param_names[sidx][count]);
		if (!W_ERROR_IS_OK(werr)) {
			goto done;
		}
		werr = smbconf_add_string_to_array(tmp_service,
				&(tmp_service->param_values),
				count,
				pd(ctx)->cache->param_values[sidx][count]);
		if (!W_ERROR_IS_OK(werr)) {
			goto done;
		}
	}

	tmp_service->num_params = count;
	if (count > 0) {
		*service = talloc_move(mem_ctx, &tmp_service);
	} else {
		*service = NULL;
	}

done:
	talloc_free(tmp_ctx);
	return werr;
}
示例#16
0
static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx,
				   const struct auth_context *auth_context,
				   const char *ncalrpc_sockname,
				   struct netlogon_creds_CredentialState *creds,
				   const struct auth_usersupplied_info *user_info,
				   struct netr_SamInfo3 **pinfo3,
				   NTSTATUS *schannel_bind_result)
{
	struct rpc_pipe_client *p = NULL;
	struct pipe_auth_data *auth = NULL;
	struct netr_SamInfo3 *info3 = NULL;
	NTSTATUS status;

	*schannel_bind_result = NT_STATUS_OK;

	status = rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpc_sockname,
				       &ndr_table_netlogon.syntax_id, &p);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n",
			   nt_errstr(status)));
		return status;
	}

	p->dc = creds;

	status = rpccli_schannel_bind_data(p, lp_workgroup(),
					   DCERPC_AUTH_LEVEL_PRIVACY,
					   p->dc, &auth);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpccli_schannel_bind_data failed: %s\n",
			   nt_errstr(status)));
		TALLOC_FREE(p);
		return status;
	}

	status = rpc_pipe_bind(p, auth);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
		TALLOC_FREE(p);
		*schannel_bind_result = status;
		return status;
	}

	status = rpccli_netlogon_sam_network_logon_ex(
		p, p,
		user_info->logon_parameters,           /* flags such as 'allow
					                * workstation logon' */
		lp_netbios_name(),                       /* server name */
		user_info->client.account_name,        /* user name logging on. */
		user_info->client.domain_name,         /* domain name */
		user_info->workstation_name,           /* workstation name */
		(uchar *)auth_context->challenge.data, /* 8 byte challenge. */
		3,				       /* validation level */
		user_info->password.response.lanman,   /* lanman 24 byte response */
		user_info->password.response.nt,       /* nt 24 byte response */
		&info3);                               /* info3 out */

	DEBUG(10, ("rpccli_netlogon_sam_network_logon_ex returned %s\n",
		   nt_errstr(status)));

	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(p);
		return status;
	}

	*pinfo3 = talloc_move(mem_ctx, &info3);

	TALLOC_FREE(p);
	return NT_STATUS_OK;
}
示例#17
0
static NTSTATUS smbd_smb2_auth_generic_return(struct smbXsrv_session *session,
					struct smbXsrv_session_auth0 **_auth,
					struct smbd_smb2_request *smb2req,
					uint8_t in_security_mode,
					struct auth_session_info *session_info,
					uint16_t *out_session_flags,
					uint64_t *out_session_id)
{
	NTSTATUS status;
	bool guest = false;
	uint8_t session_key[16];
	struct smbXsrv_session *x = session;
	struct smbXsrv_session_auth0 *auth = *_auth;
	struct smbXsrv_connection *xconn = smb2req->xconn;
	size_t i;
	struct _derivation {
		DATA_BLOB label;
		DATA_BLOB context;
	};
	struct {
		struct _derivation signing;
		struct _derivation encryption;
		struct _derivation decryption;
		struct _derivation application;
	} derivation = { };

	*_auth = NULL;

	if (xconn->protocol >= PROTOCOL_SMB3_10) {
		struct smbXsrv_preauth *preauth;
		struct _derivation *d;
		DATA_BLOB p;
		struct hc_sha512state sctx;

		preauth = talloc_move(smb2req, &auth->preauth);

		samba_SHA512_Init(&sctx);
		samba_SHA512_Update(&sctx, preauth->sha512_value,
				    sizeof(preauth->sha512_value));
		for (i = 1; i < smb2req->in.vector_count; i++) {
			samba_SHA512_Update(&sctx,
					    smb2req->in.vector[i].iov_base,
					    smb2req->in.vector[i].iov_len);
		}
		samba_SHA512_Final(preauth->sha512_value, &sctx);

		p = data_blob_const(preauth->sha512_value,
				    sizeof(preauth->sha512_value));

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMBSigningKey");
		d->context = p;

		d = &derivation.decryption;
		d->label = data_blob_string_const_null("SMBC2SCipherKey");
		d->context = p;

		d = &derivation.encryption;
		d->label = data_blob_string_const_null("SMBS2CCipherKey");
		d->context = p;

		d = &derivation.application;
		d->label = data_blob_string_const_null("SMBAppKey");
		d->context = p;

	} else if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d;

		d = &derivation.signing;
		d->label = data_blob_string_const_null("SMB2AESCMAC");
		d->context = data_blob_string_const_null("SmbSign");

		d = &derivation.decryption;
		d->label = data_blob_string_const_null("SMB2AESCCM");
		d->context = data_blob_string_const_null("ServerIn ");

		d = &derivation.encryption;
		d->label = data_blob_string_const_null("SMB2AESCCM");
		d->context = data_blob_string_const_null("ServerOut");

		d = &derivation.application;
		d->label = data_blob_string_const_null("SMB2APP");
		d->context = data_blob_string_const_null("SmbRpc");
	}

	if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
	    lp_server_signing() == SMB_SIGNING_REQUIRED) {
		x->global->signing_flags = SMBXSRV_SIGNING_REQUIRED;
	}

	if ((lp_smb_encrypt(-1) >= SMB_SIGNING_DESIRED) &&
	    (xconn->smb2.client.capabilities & SMB2_CAP_ENCRYPTION)) {
		x->global->encryption_flags = SMBXSRV_ENCRYPTION_DESIRED;
	}

	if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
		x->global->encryption_flags = SMBXSRV_ENCRYPTION_REQUIRED |
			SMBXSRV_ENCRYPTION_DESIRED;
	}

	if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
		/* we map anonymous to guest internally */
		*out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
		*out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
		/* force no signing */
		x->global->signing_flags &= ~SMBXSRV_SIGNING_REQUIRED;
		guest = true;
	}

	if (guest && (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED)) {
		DEBUG(1,("reject guest session as encryption is required\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	if (xconn->smb2.server.cipher == 0) {
		if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_REQUIRED) {
			DEBUG(1,("reject session with dialect[0x%04X] "
				 "as encryption is required\n",
				 xconn->smb2.server.dialect));
			return NT_STATUS_ACCESS_DENIED;
		}
	} else {
		x->global->channels[0].encryption_cipher = xconn->smb2.server.cipher;
	}

	if (x->global->encryption_flags & SMBXSRV_ENCRYPTION_DESIRED) {
		*out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
	}

	ZERO_STRUCT(session_key);
	memcpy(session_key, session_info->session_key.data,
	       MIN(session_info->session_key.length, sizeof(session_key)));

	x->global->signing_key = data_blob_talloc(x->global,
						  session_key,
						  sizeof(session_key));
	if (x->global->signing_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.signing;

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->signing_key.data);
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.decryption;

		x->global->decryption_key = data_blob_talloc(x->global,
							     session_key,
							     sizeof(session_key));
		if (x->global->decryption_key.data == NULL) {
			ZERO_STRUCT(session_key);
			return NT_STATUS_NO_MEMORY;
		}

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->decryption_key.data);
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.encryption;
		size_t nonce_size;

		x->global->encryption_key = data_blob_talloc(x->global,
							     session_key,
							     sizeof(session_key));
		if (x->global->encryption_key.data == NULL) {
			ZERO_STRUCT(session_key);
			return NT_STATUS_NO_MEMORY;
		}

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->encryption_key.data);

		/*
		 * CCM and GCM algorithms must never have their
		 * nonce wrap, or the security of the whole
		 * communication and the keys is destroyed.
		 * We must drop the connection once we have
		 * transfered too much data.
		 *
		 * NOTE: We assume nonces greater than 8 bytes.
		 */
		generate_random_buffer((uint8_t *)&x->nonce_high_random,
				       sizeof(x->nonce_high_random));
		switch (xconn->smb2.server.cipher) {
		case SMB2_ENCRYPTION_AES128_CCM:
			nonce_size = AES_CCM_128_NONCE_SIZE;
			break;
		case SMB2_ENCRYPTION_AES128_GCM:
			nonce_size = AES_GCM_128_IV_SIZE;
			break;
		default:
			nonce_size = 0;
			break;
		}
		x->nonce_high_max = SMB2_NONCE_HIGH_MAX(nonce_size);
		x->nonce_high = 0;
		x->nonce_low = 0;
	}

	x->global->application_key = data_blob_dup_talloc(x->global,
						x->global->signing_key);
	if (x->global->application_key.data == NULL) {
		ZERO_STRUCT(session_key);
		return NT_STATUS_NO_MEMORY;
	}

	if (xconn->protocol >= PROTOCOL_SMB2_24) {
		struct _derivation *d = &derivation.application;

		smb2_key_derivation(session_key, sizeof(session_key),
				    d->label.data, d->label.length,
				    d->context.data, d->context.length,
				    x->global->application_key.data);
	}
	ZERO_STRUCT(session_key);

	x->global->channels[0].signing_key = data_blob_dup_talloc(x->global->channels,
						x->global->signing_key);
	if (x->global->channels[0].signing_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	data_blob_clear_free(&session_info->session_key);
	session_info->session_key = data_blob_dup_talloc(session_info,
						x->global->application_key);
	if (session_info->session_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	session->compat = talloc_zero(session, struct user_struct);
	if (session->compat == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	session->compat->session = session;
	session->compat->homes_snum = -1;
	session->compat->session_info = session_info;
	session->compat->session_keystr = NULL;
	session->compat->vuid = session->global->session_wire_id;
	DLIST_ADD(smb2req->sconn->users, session->compat);
	smb2req->sconn->num_users++;

	if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
		session->compat->homes_snum =
			register_homes_share(session_info->unix_info->unix_name);
	}

	set_current_user_info(session_info->unix_info->sanitized_username,
			      session_info->unix_info->unix_name,
			      session_info->info->domain_name);

	reload_services(smb2req->sconn, conn_snum_used, true);

	session->status = NT_STATUS_OK;
	session->global->auth_session_info = talloc_move(session->global,
							 &session_info);
	session->global->auth_session_info_seqnum += 1;
	for (i=0; i < session->global->num_channels; i++) {
		struct smbXsrv_channel_global0 *_c =
			&session->global->channels[i];

		_c->auth_session_info_seqnum =
			session->global->auth_session_info_seqnum;
	}
	session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
	session->global->expiration_time = gensec_expire_time(auth->gensec);

	if (!session_claim(session)) {
		DEBUG(1, ("smb2: Failed to claim session "
			"for vuid=%llu\n",
			(unsigned long long)session->compat->vuid));
		return NT_STATUS_LOGON_FAILURE;
	}

	TALLOC_FREE(auth);
	status = smbXsrv_session_update(session);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
			  (unsigned long long)session->compat->vuid,
			  nt_errstr(status)));
		return NT_STATUS_LOGON_FAILURE;
	}

	/*
	 * we attach the session to the request
	 * so that the response can be signed
	 */
	if (!guest) {
		smb2req->do_signing = true;
	}

	global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);

	*out_session_id = session->global->session_wire_id;

	return NT_STATUS_OK;
}
示例#18
0
文件: authdata.c 项目: hef/samba
/*
 * Given the username/password, do a kinit, store the ticket in
 * cache_name if specified, and return the PAC_LOGON_INFO (the
 * structure containing the important user information such as
 * groups).
 */
NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx,
			     const char *name,
			     const char *pass,
			     time_t time_offset,
			     time_t *expire_time,
			     time_t *renew_till_time,
			     const char *cache_name,
			     bool request_pac,
			     bool add_netbios_addr,
			     time_t renewable_time,
			     const char *impersonate_princ_s,
			     const char *local_service,
			     struct PAC_DATA_CTR **_pac_data_ctr)
{
	krb5_error_code ret;
	NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
	DATA_BLOB tkt, tkt_wrapped, ap_rep, sesskey1;
	const char *auth_princ = NULL;
	const char *cc = "MEMORY:kerberos_return_pac";
	struct auth_session_info *session_info;
	struct gensec_security *gensec_server_context;
	const struct gensec_security_ops **backends;
	struct gensec_settings *gensec_settings;
	size_t idx = 0;
	struct auth4_context *auth_context;
	struct loadparm_context *lp_ctx;
	struct PAC_DATA_CTR *pac_data_ctr = NULL;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	ZERO_STRUCT(tkt);
	ZERO_STRUCT(ap_rep);
	ZERO_STRUCT(sesskey1);

	if (!name || !pass) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (cache_name) {
		cc = cache_name;
	}

	if (!strchr_m(name, '@')) {
		auth_princ = talloc_asprintf(mem_ctx, "%s@%s", name,
			lp_realm());
	} else {
		auth_princ = name;
	}
	NT_STATUS_HAVE_NO_MEMORY(auth_princ);

	ret = kerberos_kinit_password_ext(auth_princ,
					  pass,
					  time_offset,
					  expire_time,
					  renew_till_time,
					  cc,
					  request_pac,
					  add_netbios_addr,
					  renewable_time,
					  &status);
	if (ret) {
		DEBUG(1,("kinit failed for '%s' with: %s (%d)\n",
			auth_princ, error_message(ret), ret));
		/* status already set */
		goto out;
	}

	DEBUG(10,("got TGT for %s in %s\n", auth_princ, cc));
	if (expire_time) {
		DEBUGADD(10,("\tvalid until: %s (%d)\n",
			http_timestring(talloc_tos(), *expire_time),
			(int)*expire_time));
	}
	if (renew_till_time) {
		DEBUGADD(10,("\trenewable till: %s (%d)\n",
			http_timestring(talloc_tos(), *renew_till_time),
			(int)*renew_till_time));
	}

	/* we cannot continue with krb5 when UF_DONT_REQUIRE_PREAUTH is set,
	 * in that case fallback to NTLM - gd */

	if (expire_time && renew_till_time &&
	    (*expire_time == 0) && (*renew_till_time == 0)) {
		return NT_STATUS_INVALID_LOGON_TYPE;
	}

	ret = cli_krb5_get_ticket(mem_ctx,
				  local_service,
				  time_offset,
				  &tkt,
				  &sesskey1,
				  0,
				  cc,
				  NULL,
				  impersonate_princ_s);
	if (ret) {
		DEBUG(1,("failed to get ticket for %s: %s\n",
			local_service, error_message(ret)));
		if (impersonate_princ_s) {
			DEBUGADD(1,("tried S4U2SELF impersonation as: %s\n",
				impersonate_princ_s));
		}
		status = krb5_to_nt_status(ret);
		goto out;
	}

	/* wrap that up in a nice GSS-API wrapping */
	tkt_wrapped = spnego_gen_krb5_wrap(tmp_ctx, tkt, TOK_ID_KRB_AP_REQ);
	if (tkt_wrapped.data == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	auth_context = talloc_zero(tmp_ctx, struct auth4_context);
	if (auth_context == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	auth_context->generate_session_info_pac = kerberos_fetch_pac;

	lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_helpers());
	if (lp_ctx == NULL) {
		status = NT_STATUS_INVALID_SERVER_STATE;
		DEBUG(10, ("loadparm_init_s3 failed\n"));
		goto out;
	}

	gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
	if (lp_ctx == NULL) {
		status = NT_STATUS_NO_MEMORY;
		DEBUG(10, ("lpcfg_gensec_settings failed\n"));
		goto out;
	}

	backends = talloc_zero_array(gensec_settings,
				     const struct gensec_security_ops *, 2);
	if (backends == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	gensec_settings->backends = backends;

	gensec_init();

	backends[idx++] = &gensec_gse_krb5_security_ops;

	status = gensec_server_start(tmp_ctx, gensec_settings,
					auth_context, &gensec_server_context);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, (__location__ "Failed to start server-side GENSEC to validate a Kerberos ticket: %s\n", nt_errstr(status)));
		goto out;
	}

	talloc_unlink(tmp_ctx, lp_ctx);
	talloc_unlink(tmp_ctx, gensec_settings);
	talloc_unlink(tmp_ctx, auth_context);

	status = gensec_start_mech_by_oid(gensec_server_context, GENSEC_OID_KERBEROS5);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, (__location__ "Failed to start server-side GENSEC krb5 to validate a Kerberos ticket: %s\n", nt_errstr(status)));
		goto out;
	}

	/* Do a client-server update dance */
	status = gensec_update(gensec_server_context, tmp_ctx, tkt_wrapped, &ap_rep);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("gensec_update() failed: %s\n", nt_errstr(status)));
		goto out;
	}

	/* Now return the PAC information to the callers.  We ingore
	 * the session_info and instead pick out the PAC via the
	 * private_data on the auth_context */
	status = gensec_session_info(gensec_server_context, tmp_ctx, &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Unable to obtain PAC via gensec_session_info\n"));
		goto out;
	}

	pac_data_ctr = talloc_get_type_abort(gensec_server_context->auth_context->private_data,
					     struct PAC_DATA_CTR);
	if (pac_data_ctr == NULL) {
		DEBUG(1,("no PAC\n"));
		status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	*_pac_data_ctr = talloc_move(mem_ctx, &pac_data_ctr);

out:
	talloc_free(tmp_ctx);
	if (cc != cache_name) {
		ads_kdestroy(cc);
	}

	data_blob_free(&tkt);
	data_blob_free(&ap_rep);
	data_blob_free(&sesskey1);

	return status;
}
示例#19
0
static NTSTATUS smbd_smb2_reauth_generic_return(struct smbXsrv_session *session,
					struct smbXsrv_session_auth0 **_auth,
					struct smbd_smb2_request *smb2req,
					struct auth_session_info *session_info,
					uint16_t *out_session_flags,
					uint64_t *out_session_id)
{
	NTSTATUS status;
	struct smbXsrv_session *x = session;
	struct smbXsrv_session_auth0 *auth = *_auth;
	struct smbXsrv_connection *xconn = smb2req->xconn;
	size_t i;

	*_auth = NULL;

	data_blob_clear_free(&session_info->session_key);
	session_info->session_key = data_blob_dup_talloc(session_info,
						x->global->application_key);
	if (session_info->session_key.data == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	session->compat->session_info = session_info;
	session->compat->vuid = session->global->session_wire_id;

	session->compat->homes_snum =
			register_homes_share(session_info->unix_info->unix_name);

	set_current_user_info(session_info->unix_info->sanitized_username,
			      session_info->unix_info->unix_name,
			      session_info->info->domain_name);

	reload_services(smb2req->sconn, conn_snum_used, true);

	session->status = NT_STATUS_OK;
	TALLOC_FREE(session->global->auth_session_info);
	session->global->auth_session_info = talloc_move(session->global,
							 &session_info);
	session->global->auth_session_info_seqnum += 1;
	for (i=0; i < session->global->num_channels; i++) {
		struct smbXsrv_channel_global0 *_c =
			&session->global->channels[i];

		_c->auth_session_info_seqnum =
			session->global->auth_session_info_seqnum;
	}
	session->global->auth_time = timeval_to_nttime(&smb2req->request_time);
	session->global->expiration_time = gensec_expire_time(auth->gensec);

	TALLOC_FREE(auth);
	status = smbXsrv_session_update(session);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("smb2: Failed to update session for vuid=%llu - %s\n",
			  (unsigned long long)session->compat->vuid,
			  nt_errstr(status)));
		return NT_STATUS_LOGON_FAILURE;
	}

	conn_clear_vuid_caches(xconn->client->sconn, session->compat->vuid);

	if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
		smb2req->do_signing = true;
	}

	*out_session_id = session->global->session_wire_id;

	return NT_STATUS_OK;
}
示例#20
0
文件: service.c 项目: 285858315/samba
NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
{
	NTSTATUS status;

	if (*lp_force_user(talloc_tos(), snum)) {

		/*
		 * Replace conn->session_info with a completely faked up one
		 * from the username we are forced into :-)
		 */

		char *fuser;
		char *sanitized_username;
		struct auth_session_info *forced_serverinfo;
		bool guest;

		fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), snum), "%S",
					  lp_const_servicename(snum));
		if (fuser == NULL) {
			return NT_STATUS_NO_MEMORY;
		}

		guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;

		status = make_session_info_from_username(
			conn, fuser,
			guest,
			&forced_serverinfo);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		/* We don't want to replace the original sanitized_username
		   as it is the original user given in the connect attempt.
		   This is used in '%U' substitutions. */
		sanitized_username = discard_const_p(char,
			forced_serverinfo->unix_info->sanitized_username);
		TALLOC_FREE(sanitized_username);
		forced_serverinfo->unix_info->sanitized_username =
			talloc_move(forced_serverinfo->unix_info,
				&conn->session_info->unix_info->sanitized_username);

		TALLOC_FREE(conn->session_info);
		conn->session_info = forced_serverinfo;

		conn->force_user = true;
		DEBUG(3,("Forced user %s\n", fuser));
	}

	/*
	 * If force group is true, then override
	 * any groupid stored for the connecting user.
	 */

	if (*lp_force_group(talloc_tos(), snum)) {

		status = find_forced_group(
			conn->force_user, snum, conn->session_info->unix_info->unix_name,
			&conn->session_info->security_token->sids[1],
			&conn->session_info->unix_token->gid);

		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		/*
		 * We need to cache this gid, to use within
		 * change_to_user() separately from the conn->session_info
		 * struct. We only use conn->session_info directly if
		 * "force_user" was set.
		 */
		conn->force_group_gid = conn->session_info->unix_token->gid;
	}

	return NT_STATUS_OK;
}
示例#21
0
文件: cldap.c 项目: Distrotech/samba
/*
  handle recv events on a cldap socket
*/
static bool cldap_socket_recv_dgram(struct cldap_socket *c,
				    struct cldap_incoming *in)
{
	DATA_BLOB blob;
	struct asn1_data *asn1;
	void *p;
	struct cldap_search_state *search;
	NTSTATUS status;

	if (in->recv_errno != 0) {
		goto error;
	}

	blob = data_blob_const(in->buf, in->len);

	asn1 = asn1_init(in);
	if (!asn1) {
		goto nomem;
	}

	if (!asn1_load(asn1, blob)) {
		goto nomem;
	}

	in->ldap_msg = talloc(in, struct ldap_message);
	if (in->ldap_msg == NULL) {
		goto nomem;
	}

	/* this initial decode is used to find the message id */
	status = ldap_decode(asn1, NULL, in->ldap_msg);
	if (!NT_STATUS_IS_OK(status)) {
		goto nterror;
	}

	/* find the pending request */
	p = idr_find(c->searches.idr, in->ldap_msg->messageid);
	if (p == NULL) {
		if (!c->incoming.handler) {
			TALLOC_FREE(in);
			return true;
		}

		/* this function should free or steal 'in' */
		c->incoming.handler(c, c->incoming.private_data, in);
		return false;
	}

	search = talloc_get_type_abort(p, struct cldap_search_state);
	search->response.in = talloc_move(search, &in);
	search->response.asn1 = asn1;
	search->response.asn1->ofs = 0;

	DLIST_REMOVE(c->searches.list, search);

	if (cldap_recvfrom_setup(c)) {
		tevent_req_done(search->req);
		return true;
	}

	/*
	 * This request was ok, just defer the notify of the caller
	 * and then just fail the next request if needed
	 */
	tevent_req_defer_callback(search->req, search->caller.ev);
	tevent_req_done(search->req);

	status = NT_STATUS_NO_MEMORY;
	/* in is NULL it this point */
	goto nterror;
nomem:
	in->recv_errno = ENOMEM;
error:
	status = map_nt_error_from_unix_common(in->recv_errno);
nterror:
	TALLOC_FREE(in);
	/* in connected mode the first pending search gets the error */
	if (!c->connected) {
		/* otherwise we just ignore the error */
		return false;
	}
	if (!c->searches.list) {
		return false;
	}
	/*
	 * We might called tevent_req_done() for a successful
	 * search before, so we better deliver the failure
	 * after the success, that is why we better also
	 * use tevent_req_defer_callback() here.
	 */
	tevent_req_defer_callback(c->searches.list->req,
				  c->searches.list->caller.ev);
	tevent_req_nterror(c->searches.list->req, status);
	return false;
}
示例#22
0
static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
				       const char *in_path,
				       uint8_t *out_share_type,
				       uint32_t *out_share_flags,
				       uint32_t *out_capabilities,
				       uint32_t *out_maximal_access,
				       uint32_t *out_tree_id)
{
	const char *share = in_path;
	char *service = NULL;
	int snum = -1;
	struct smbd_smb2_tcon *tcon;
	connection_struct *compat_conn = NULL;
	user_struct *compat_vuser = req->session->compat_vuser;
	int id;
	NTSTATUS status;

	if (strncmp(share, "\\\\", 2) == 0) {
		const char *p = strchr(share+2, '\\');
		if (p) {
			share = p + 1;
		}
	}

	DEBUG(10,("smbd_smb2_tree_connect: path[%s] share[%s]\n",
		  in_path, share));

	service = talloc_strdup(talloc_tos(), share);
	if(!service) {
		return NT_STATUS_NO_MEMORY;
	}

	strlower_m(service);

	/* TODO: do more things... */
	if (strequal(service,HOMES_NAME)) {
		if (compat_vuser->homes_snum == -1) {
			DEBUG(2, ("[homes] share not available for "
				"user %s because it was not found "
				"or created at session setup "
				"time\n",
				compat_vuser->session_info->unix_info->unix_name));
			return NT_STATUS_BAD_NETWORK_NAME;
		}
		snum = compat_vuser->homes_snum;
	} else if ((compat_vuser->homes_snum != -1)
                   && strequal(service,
			lp_servicename(compat_vuser->homes_snum))) {
		snum = compat_vuser->homes_snum;
	} else {
		snum = find_service(talloc_tos(), service, &service);
		if (!service) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	if (snum < 0) {
		DEBUG(3,("smbd_smb2_tree_connect: couldn't find service %s\n",
			 service));
		return NT_STATUS_BAD_NETWORK_NAME;
	}

	/* create a new tcon as child of the session */
	tcon = talloc_zero(req->session, struct smbd_smb2_tcon);
	if (tcon == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	id = idr_get_new_random(req->session->tcons.idtree,
				tcon,
				req->session->tcons.limit);
	if (id == -1) {
		TALLOC_FREE(tcon);
		return NT_STATUS_INSUFFICIENT_RESOURCES;
	}
	tcon->tid = id;
	tcon->snum = snum;

	DLIST_ADD_END(req->session->tcons.list, tcon,
		      struct smbd_smb2_tcon *);
	tcon->session = req->session;
	tcon->session->sconn->num_tcons_open++;
	talloc_set_destructor(tcon, smbd_smb2_tcon_destructor);

	compat_conn = make_connection_smb2(req->sconn,
					tcon,
					req->session->compat_vuser,
					data_blob_null, "???",
					&status);
	if (compat_conn == NULL) {
		TALLOC_FREE(tcon);
		return status;
	}
	tcon->compat_conn = talloc_move(tcon, &compat_conn);

	if (IS_PRINT(tcon->compat_conn)) {
		*out_share_type = SMB2_SHARE_TYPE_PRINT;
	} else if (IS_IPC(tcon->compat_conn)) {
		*out_share_type = SMB2_SHARE_TYPE_PIPE;
	} else {
		*out_share_type = SMB2_SHARE_TYPE_DISK;
	}

	*out_share_flags = 0;

	if (lp_msdfs_root(SNUM(tcon->compat_conn)) && lp_host_msdfs()) {
		*out_share_flags |= (SMB2_SHAREFLAG_DFS|SMB2_SHAREFLAG_DFS_ROOT);
		*out_capabilities = SMB2_SHARE_CAP_DFS;
	} else {
		*out_capabilities = 0;
	}

	switch(lp_csc_policy(SNUM(tcon->compat_conn))) {
	case CSC_POLICY_MANUAL:
		break;
	case CSC_POLICY_DOCUMENTS:
		*out_share_flags |= SMB2_SHAREFLAG_AUTO_CACHING;
		break;
	case CSC_POLICY_PROGRAMS:
		*out_share_flags |= SMB2_SHAREFLAG_VDO_CACHING;
		break;
	case CSC_POLICY_DISABLE:
		*out_share_flags |= SMB2_SHAREFLAG_NO_CACHING;
		break;
	default:
		break;
	}

	if (lp_hideunreadable(SNUM(tcon->compat_conn)) ||
	    lp_hideunwriteable_files(SNUM(tcon->compat_conn))) {
		*out_share_flags |= SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM;
	}

	*out_maximal_access = tcon->compat_conn->share_access;

	*out_tree_id = tcon->tid;
	return NT_STATUS_OK;
}
示例#23
0
static enum ndr_err_code get_blob_sequence_number(DATA_BLOB *blob,
						uint64_t *pseq)
{
	struct ndr_pull ndr = {.data = blob->data, .data_size = blob->length};
	NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pseq));
	return NDR_ERR_SUCCESS;
}

static int share_mode_data_nofree_destructor(struct share_mode_data *d)
{
	return -1;
}

static struct share_mode_data *share_mode_memcache_fetch(TALLOC_CTX *mem_ctx,
					const TDB_DATA id_key,
					DATA_BLOB *blob)
{
	enum ndr_err_code ndr_err;
	struct share_mode_data *d;
	uint64_t sequence_number;
	void *ptr;
	struct file_id id;
	DATA_BLOB key;

	/* Ensure this is a locking_key record. */
	if (id_key.dsize != sizeof(id)) {
		return NULL;
	}

	memcpy(&id, id_key.dptr, id_key.dsize);
	key = memcache_key(&id);

	ptr = memcache_lookup_talloc(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);
	if (ptr == NULL) {
		DEBUG(10,("failed to find entry for key %s\n",
			file_id_string(mem_ctx, &id)));
		return NULL;
	}
	/* sequence number key is at start of blob. */
	ndr_err = get_blob_sequence_number(blob, &sequence_number);
	if (ndr_err != NDR_ERR_SUCCESS) {
		/* Bad blob. Remove entry. */
		DEBUG(10,("bad blob %u key %s\n",
			(unsigned int)ndr_err,
			file_id_string(mem_ctx, &id)));
		memcache_delete(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);
		return NULL;
	}

	d = (struct share_mode_data *)ptr;
	if (d->sequence_number != sequence_number) {
		DEBUG(10,("seq changed (cached 0x%llu) (new 0x%llu) "
			"for key %s\n",
			(unsigned long long)d->sequence_number,
			(unsigned long long)sequence_number,
			file_id_string(mem_ctx, &id)));
		/* Cache out of date. Remove entry. */
		memcache_delete(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);
		return NULL;
	}

	/* Move onto mem_ctx. */
	d = talloc_move(mem_ctx, &ptr);

	/*
	 * Now we own d, prevent the cache from freeing it
	 * when we delete the entry.
	 */
	talloc_set_destructor(d, share_mode_data_nofree_destructor);

	/* Remove from the cache. We own it now. */
	memcache_delete(NULL,
			SHARE_MODE_LOCK_CACHE,
			key);

	/* And reset the destructor to none. */
	talloc_set_destructor(d, NULL);

	DEBUG(10,("fetched entry for file %s seq 0x%llu key %s\n",
		d->base_name,
		(unsigned long long)d->sequence_number,
		file_id_string(mem_ctx, &id)));

	return d;
}

/*******************************************************************
 Get all share mode entries for a dev/inode pair.
********************************************************************/

static struct share_mode_data *parse_share_modes(TALLOC_CTX *mem_ctx,
						const TDB_DATA key,
						const TDB_DATA dbuf)
{
	struct share_mode_data *d;
	enum ndr_err_code ndr_err;
	uint32_t i;
	DATA_BLOB blob;

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

	/* See if we already have a cached copy of this key. */
	d = share_mode_memcache_fetch(mem_ctx, key, &blob);
	if (d != NULL) {
		return d;
	}

	d = talloc(mem_ctx, struct share_mode_data);
	if (d == NULL) {
		DEBUG(0, ("talloc failed\n"));
		goto fail;
	}

	ndr_err = ndr_pull_struct_blob_all(
		&blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n",
			  ndr_errstr(ndr_err)));
		goto fail;
	}

	/*
	 * Initialize the values that are [skip] in the idl. The NDR code does
	 * not initialize them.
	 */

	for (i=0; i<d->num_share_modes; i++) {
		struct share_mode_entry *e = &d->share_modes[i];

		e->stale = false;
		e->lease = NULL;
		if (e->op_type != LEASE_OPLOCK) {
			continue;
		}
		if (e->lease_idx >= d->num_leases) {
			continue;
		}
		e->lease = &d->leases[e->lease_idx];
	}
	d->modified = false;
	d->fresh = false;

	if (DEBUGLEVEL >= 10) {
		DEBUG(10, ("parse_share_modes:\n"));
		NDR_PRINT_DEBUG(share_mode_data, d);
	}

	return d;
fail:
	TALLOC_FREE(d);
	return NULL;
}

/*******************************************************************
 Create a storable data blob from a modified share_mode_data struct.
********************************************************************/

static TDB_DATA unparse_share_modes(struct share_mode_data *d)
{
	DATA_BLOB blob;
	enum ndr_err_code ndr_err;

	if (DEBUGLEVEL >= 10) {
		DEBUG(10, ("unparse_share_modes:\n"));
		NDR_PRINT_DEBUG(share_mode_data, d);
	}

	share_mode_memcache_delete(d);

	/* Update the sequence number. */
	d->sequence_number += 1;

	remove_stale_share_mode_entries(d);

	if (d->num_share_modes == 0) {
		DEBUG(10, ("No used share mode found\n"));
		return make_tdb_data(NULL, 0);
	}

	ndr_err = ndr_push_struct_blob(
		&blob, d, d, (ndr_push_flags_fn_t)ndr_push_share_mode_data);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		smb_panic("ndr_push_share_mode_lock failed");
	}

	return make_tdb_data(blob.data, blob.length);
}
示例#24
0
static sbcErr smbconf_reg_get_includes_internal(TALLOC_CTX *mem_ctx,
						struct registry_key *key,
						uint32_t *num_includes,
						char ***includes)
{
	WERROR werr;
	sbcErr err;
	uint32_t count;
	struct registry_value *value = NULL;
	char **tmp_includes = NULL;
	const char **array = NULL;
	TALLOC_CTX *tmp_ctx = talloc_stackframe();

	if (!smbconf_value_exists(key, INCLUDES_VALNAME)) {
		/* no includes */
		*num_includes = 0;
		*includes = NULL;
		err = SBC_ERR_OK;
		goto done;
	}

	werr = reg_queryvalue(tmp_ctx, key, INCLUDES_VALNAME, &value);
	if (!W_ERROR_IS_OK(werr)) {
		err = SBC_ERR_ACCESS_DENIED;
		goto done;
	}

	if (value->type != REG_MULTI_SZ) {
		/* wrong type -- ignore */
		err = SBC_ERR_OK;
		goto done;
	}

	if (!pull_reg_multi_sz(tmp_ctx, &value->data, &array)) {
		err = SBC_ERR_NOMEM;
		goto done;
	}

	for (count = 0; array[count] != NULL; count++) {
		err = smbconf_add_string_to_array(tmp_ctx,
					&tmp_includes,
					count,
					array[count]);
		if (!SBC_ERROR_IS_OK(err)) {
			goto done;
		}
	}

	if (count > 0) {
		*includes = talloc_move(mem_ctx, &tmp_includes);
		if (*includes == NULL) {
			err = SBC_ERR_NOMEM;
			goto done;
		}
		*num_includes = count;
	} else {
		*num_includes = 0;
		*includes = NULL;
	}

	err = SBC_ERR_OK;
done:
	talloc_free(tmp_ctx);
	return err;
}
示例#25
0
/*
  initialise a server_context from a open socket and register a event handler
  for reading from that socket
*/
static void ldapsrv_accept(struct stream_connection *c,
			   struct auth_session_info *session_info)
{
	struct ldapsrv_service *ldapsrv_service = 
		talloc_get_type(c->private_data, struct ldapsrv_service);
	struct ldapsrv_connection *conn;
	struct cli_credentials *server_credentials;
	struct socket_address *socket_address;
	NTSTATUS status;
	int port;

	conn = talloc_zero(c, struct ldapsrv_connection);
	if (!conn) {
		stream_terminate_connection(c, "ldapsrv_accept: out of memory");
		return;
	}

	conn->packet      = NULL;
	conn->connection  = c;
	conn->service     = ldapsrv_service;
	conn->sockets.raw = c->socket;
	conn->lp_ctx      = ldapsrv_service->task->lp_ctx;

	c->private_data   = conn;

	socket_address = socket_get_my_addr(c->socket, conn);
	if (!socket_address) {
		ldapsrv_terminate_connection(conn, "ldapsrv_accept: failed to obtain local socket address!");
		return;
	}
	port = socket_address->port;
	talloc_free(socket_address);

	if (port == 636) {
		struct socket_context *tls_socket = tls_init_server(ldapsrv_service->tls_params, c->socket, 
								    c->event.fde, NULL);
		if (!tls_socket) {
			ldapsrv_terminate_connection(conn, "ldapsrv_accept: tls_init_server() failed");
			return;
		}
		talloc_steal(c, tls_socket);
		c->socket = tls_socket;
		conn->sockets.tls = tls_socket;

	} else if (port == 3268) /* Global catalog */ {
		conn->global_catalog = true;
	}
	conn->packet = packet_init(conn);
	if (conn->packet == NULL) {
		ldapsrv_terminate_connection(conn, "out of memory");
		return;
	}

	packet_set_private(conn->packet, conn);
	packet_set_socket(conn->packet, c->socket);
	packet_set_callback(conn->packet, ldapsrv_decode);
	packet_set_full_request(conn->packet, ldap_full_packet);
	packet_set_error_handler(conn->packet, ldapsrv_error_handler);
	packet_set_event_context(conn->packet, c->event.ctx);
	packet_set_fde(conn->packet, c->event.fde);
	packet_set_serialise(conn->packet);

	if (conn->sockets.tls) {
		packet_set_unreliable_select(conn->packet);
	}

	/* Ensure we don't get packets until the database is ready below */
	packet_recv_disable(conn->packet);

	server_credentials = cli_credentials_init(conn);
	if (!server_credentials) {
		stream_terminate_connection(c, "Failed to init server credentials\n");
		return;
	}

	cli_credentials_set_conf(server_credentials, conn->lp_ctx);
	status = cli_credentials_set_machine_account(server_credentials, conn->lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		stream_terminate_connection(c, talloc_asprintf(conn, "Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
		return;
	}
	conn->server_credentials = server_credentials;

	conn->session_info = talloc_move(conn, &session_info);

	if (!NT_STATUS_IS_OK(ldapsrv_backend_Init(conn))) {
		ldapsrv_terminate_connection(conn, "backend Init failed");
		return;
	}

	/* load limits from the conf partition */
	ldapsrv_load_limits(conn); /* should we fail on error ? */

	/* register the server */	
	irpc_add_name(c->msg_ctx, "ldap_server");

	/* set connections limits */
	conn->limits.ite = event_add_timed(c->event.ctx, conn, 
					   timeval_current_ofs(conn->limits.initial_timeout, 0),
					   ldapsrv_conn_init_timeout, conn);

	packet_recv_enable(conn->packet);

}