Example #1
0
static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx,
					struct rpc_pipe_client **samr_pipe)
{
	struct rpc_pipe_client *cli = NULL;
	struct auth_serversupplied_info *session_info = NULL;
	NTSTATUS status;

	if (session_info == NULL) {
		status = make_session_info_system(mem_ctx, &session_info);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
				  nt_errstr(status)));
			return status;
		}
	}

	/* create a samr connection */
	status = rpc_pipe_open_interface(mem_ctx,
					&ndr_table_samr.syntax_id,
					session_info,
					NULL,
					winbind_messaging_context(),
					&cli);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
			  nt_errstr(status)));
		return status;
	}

	if (samr_pipe) {
		*samr_pipe = cli;
	}

	return NT_STATUS_OK;
}
Example #2
0
static void store_printer_guid(struct messaging_context *msg_ctx,
			       const char *printer, struct GUID guid)
{
	TALLOC_CTX *tmp_ctx;
	struct auth_serversupplied_info *session_info = NULL;
	const char *guid_str;
	DATA_BLOB blob;
	NTSTATUS status;
	WERROR result;

	tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) {
		DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
		return;
	}

	status = make_session_info_system(tmp_ctx, &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("store_printer_guid: "
			  "Could not create system session_info\n"));
		goto done;
	}

	guid_str = GUID_string(tmp_ctx, &guid);
	if (!guid_str) {
		DEBUG(0, ("store_printer_guid: Out of memory?!\n"));
		goto done;
	}

	/* We used to store this as a REG_BINARY but that causes
	   Vista to whine */

	if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
		DEBUG(0, ("store_printer_guid: "
			  "Could not marshall string %s for objectGUID\n",
			  guid_str));
		goto done;
	}

	result = winreg_set_printer_dataex(tmp_ctx, session_info, msg_ctx,
					   printer,
					   SPOOL_DSSPOOLER_KEY, "objectGUID",
					   REG_SZ, blob.data, blob.length);
	if (!W_ERROR_IS_OK(result)) {
		DEBUG(0, ("store_printer_guid: "
			  "Failed to store GUID for printer %s\n", printer));
	}

done:
	talloc_free(tmp_ctx);
}
bool nt_printing_tdb_migrate(struct messaging_context *msg_ctx)
{
	const char *drivers_path;
	const char *printers_path;
	const char *forms_path;
	bool drivers_exists;
	bool printers_exists;
	bool forms_exists;
	struct auth_session_info *session_info;
	struct rpc_pipe_client *winreg_pipe = NULL;
	TALLOC_CTX *tmp_ctx = talloc_stackframe();
	NTSTATUS status;

	/* paths talloced on new stackframe */
	drivers_path = state_path("ntdrivers.tdb");
	printers_path = state_path("ntprinters.tdb");
	forms_path = state_path("ntforms.tdb");
	if ((drivers_path == NULL) || (printers_path == NULL)
						|| (forms_path == NULL)) {
		talloc_free(tmp_ctx);
		return false;
	}
	drivers_exists = file_exist(drivers_path);
	printers_exists = file_exist(printers_path);
	forms_exists = file_exist(forms_path);

	if (!drivers_exists && !printers_exists && !forms_exists) {
		talloc_free(tmp_ctx);
		return true;
	}

	status = make_session_info_system(tmp_ctx, &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Couldn't create session_info: %s\n",
			  nt_errstr(status)));
		talloc_free(tmp_ctx);
		return false;
	}

	status = rpc_pipe_open_interface(tmp_ctx,
					&ndr_table_winreg,
					session_info,
					NULL,
					NULL,
					msg_ctx,
					&winreg_pipe);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Couldn't open internal winreg pipe: %s\n",
			  nt_errstr(status)));
		talloc_free(tmp_ctx);
		return false;
	}

	if (drivers_exists) {
		status = migrate_internal(tmp_ctx, drivers_path, winreg_pipe);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Couldn't migrate drivers tdb file: %s\n",
			  nt_errstr(status)));
			talloc_free(tmp_ctx);
			return false;
		}
	}

	if (printers_exists) {
		status = migrate_internal(tmp_ctx, printers_path, winreg_pipe);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Couldn't migrate printers tdb file: %s\n",
				  nt_errstr(status)));
			talloc_free(tmp_ctx);
			return false;
		}
	}

	if (forms_exists) {
		status = migrate_internal(tmp_ctx, forms_path, winreg_pipe);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Couldn't migrate forms tdb file: %s\n",
				  nt_errstr(status)));
			talloc_free(tmp_ctx);
			return false;
		}
	}

	talloc_free(tmp_ctx);
	return true;
}
Example #4
0
NTSTATUS auth3_generate_session_info(struct auth4_context *auth_context,
                                     TALLOC_CTX *mem_ctx,
                                     void *server_returned_info,
                                     const char *original_user_name,
                                     uint32_t session_info_flags,
                                     struct auth_session_info **session_info)
{
    struct auth_user_info_dc *user_info = NULL;
    struct auth_serversupplied_info *server_info = NULL;
    NTSTATUS nt_status;

    /*
     * This is a hack, some callers...
     *
     * Some callers pass auth_user_info_dc, the SCHANNEL and
     * NCALRPC_AS_SYSTEM gensec modules.
     *
     * While the reset passes auth3_check_password() returned.
     */
    user_info = talloc_get_type(server_returned_info,
                                struct auth_user_info_dc);
    if (user_info != NULL) {
        const struct dom_sid *sid;
        int cmp;

        /*
         * This should only be called from SCHANNEL or NCALRPC_AS_SYSTEM
         */
        if (user_info->num_sids != 1) {
            return NT_STATUS_INTERNAL_ERROR;
        }
        sid = &user_info->sids[PRIMARY_USER_SID_INDEX];

        cmp = dom_sid_compare(sid, &global_sid_System);
        if (cmp == 0) {
            return make_session_info_system(mem_ctx, session_info);
        }

        cmp = dom_sid_compare(sid, &global_sid_Anonymous);
        if (cmp == 0) {
            /*
             * TODO: use auth_anonymous_session_info() here?
             */
            return make_session_info_guest(mem_ctx, session_info);
        }

        return NT_STATUS_INTERNAL_ERROR;
    }

    server_info = talloc_get_type_abort(server_returned_info,
                                        struct auth_serversupplied_info);
    nt_status = create_local_token(mem_ctx,
                                   server_info,
                                   NULL,
                                   original_user_name,
                                   session_info);
    if (!NT_STATUS_IS_OK(nt_status)) {
        DEBUG(10, ("create_local_token failed: %s\n",
                   nt_errstr(nt_status)));
        return nt_status;
    }

    return NT_STATUS_OK;
}
Example #5
0
/**
 * @brief Purge stale printers and reload from pre-populated pcap cache.
 *
 * This function should normally only be called as a callback on a successful
 * pcap_cache_reload().
 *
 * This function can cause DELETION of printers and drivers from our registry,
 * so calling it on a failed pcap reload may REMOVE permanently all printers
 * and drivers.
 *
 * @param[in] ev        The event context.
 *
 * @param[in] msg_ctx   The messaging context.
 */
static void delete_and_reload_printers_full(struct tevent_context *ev,
					    struct messaging_context *msg_ctx)
{
	struct auth_session_info *session_info = NULL;
	struct spoolss_PrinterInfo2 *pinfo2 = NULL;
	int n_services;
	int pnum;
	int snum;
	const char *pname;
	const char *sname;
	NTSTATUS status;

	n_services = lp_numservices();
	pnum = lp_servicenumber(PRINTERS_NAME);

	status = make_session_info_system(talloc_tos(), &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(3, ("reload_printers: "
			  "Could not create system session_info\n"));
		/* can't remove stale printers before we
		 * are fully initilized */
		return;
	}

	/*
	 * Add default config for printers added to smb.conf file and remove
	 * stale printers
	 */
	for (snum = 0; snum < n_services; snum++) {
		/* avoid removing PRINTERS_NAME */
		if (snum == pnum) {
			continue;
		}

		/* skip no-printer services */
		if (!snum_is_shared_printer(snum)) {
			continue;
		}

		sname = lp_const_servicename(snum);
		pname = lp_printername(session_info, snum);

		/* check printer, but avoid removing non-autoloaded printers */
		if (lp_autoloaded(snum) && !pcap_printername_ok(pname)) {
			DEBUG(3, ("removing stale printer %s\n", pname));

			if (is_printer_published(session_info, session_info,
						 msg_ctx,
						 NULL,
						 lp_servicename(session_info,
								snum),
						 &pinfo2)) {
				nt_printer_publish(session_info,
						   session_info,
						   msg_ctx,
						   pinfo2,
						   DSPRINT_UNPUBLISH);
				TALLOC_FREE(pinfo2);
			}
			nt_printer_remove(session_info, session_info, msg_ctx,
					  pname);
		} else {
			DEBUG(8, ("Adding default registry entry for printer "
				  "[%s], if it doesn't exist.\n", sname));
			nt_printer_add(session_info, session_info, msg_ctx,
				       sname);
		}
	}

	/* finally, purge old snums */
	delete_and_reload_printers();

	TALLOC_FREE(session_info);
}
Example #6
0
WERROR check_published_printers(struct messaging_context *msg_ctx)
{
	ADS_STATUS ads_rc;
	ADS_STRUCT *ads = NULL;
	int snum;
	int n_services = lp_numservices();
	TALLOC_CTX *tmp_ctx = NULL;
	struct auth_serversupplied_info *session_info = NULL;
	struct spoolss_PrinterInfo2 *pinfo2;
	NTSTATUS status;
	WERROR result;

	tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) return WERR_NOMEM;

	ads = ads_init(lp_realm(), lp_workgroup(), NULL);
	if (!ads) {
		DEBUG(3, ("ads_init() failed\n"));
		return WERR_SERVER_UNAVAILABLE;
	}
	setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
	SAFE_FREE(ads->auth.password);
	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
		NULL, NULL);

	/* ads_connect() will find the DC for us */
	ads_rc = ads_connect(ads);
	if (!ADS_ERR_OK(ads_rc)) {
		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
		result = WERR_ACCESS_DENIED;
		goto done;
	}

	status = make_session_info_system(tmp_ctx, &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("check_published_printers: "
			  "Could not create system session_info\n"));
		result = WERR_ACCESS_DENIED;
		goto done;
	}

	for (snum = 0; snum < n_services; snum++) {
		if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
			continue;
		}

		result = winreg_get_printer(tmp_ctx, session_info, msg_ctx,
					    lp_servicename(snum),
					    &pinfo2);
		if (!W_ERROR_IS_OK(result)) {
			continue;
		}

		if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
			nt_printer_publish_ads(msg_ctx, ads, pinfo2);
		}

		TALLOC_FREE(pinfo2);
	}

	result = WERR_OK;
done:
	ads_destroy(&ads);
	ads_kdestroy("MEMORY:prtpub_cache");
	talloc_free(tmp_ctx);
	return result;
}
Example #7
0
static bool api_pipe_bind_req(struct pipes_struct *p,
				struct ncacn_packet *pkt)
{
	struct dcerpc_auth auth_info;
	uint16 assoc_gid;
	unsigned int auth_type = DCERPC_AUTH_TYPE_NONE;
	NTSTATUS status;
	struct ndr_syntax_id id;
	uint8_t pfc_flags = 0;
	union dcerpc_payload u;
	struct dcerpc_ack_ctx bind_ack_ctx;
	DATA_BLOB auth_resp = data_blob_null;
	DATA_BLOB auth_blob = data_blob_null;
	const struct ndr_interface_table *table;

	/* No rebinds on a bound pipe - use alter context. */
	if (p->pipe_bound) {
		DEBUG(2,("Rejecting bind request on bound rpc connection\n"));
		return setup_bind_nak(p, pkt);
	}

	if (pkt->u.bind.num_contexts == 0) {
		DEBUG(0, ("api_pipe_bind_req: no rpc contexts around\n"));
		goto err_exit;
	}

	/*
	 * Try and find the correct pipe name to ensure
	 * that this is a pipe name we support.
	 */
	id = pkt->u.bind.ctx_list[0].abstract_syntax;

	table = ndr_table_by_uuid(&id.uuid);
	if (table == NULL) {
		DEBUG(0,("unknown interface\n"));
		return false;
	}

	if (rpc_srv_pipe_exists_by_id(&id)) {
		DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n",
			  rpc_srv_get_pipe_cli_name(&id),
			  rpc_srv_get_pipe_srv_name(&id)));
	} else {
		status = smb_probe_module(
			"rpc", dcerpc_default_transport_endpoint(pkt,
				NCACN_NP, table));

		if (NT_STATUS_IS_ERR(status)) {
			DEBUG(3,("api_pipe_bind_req: Unknown rpc service name "
                                 "%s in bind request.\n",
				 ndr_interface_name(&id.uuid,
						    id.if_version)));

			return setup_bind_nak(p, pkt);
		}

		if (rpc_srv_get_pipe_interface_by_cli_name(
				dcerpc_default_transport_endpoint(pkt,
					NCACN_NP, table),
				&id)) {
			DEBUG(3, ("api_pipe_bind_req: %s -> %s rpc service\n",
				  rpc_srv_get_pipe_cli_name(&id),
				  rpc_srv_get_pipe_srv_name(&id)));
		} else {
			DEBUG(0, ("module %s doesn't provide functions for "
				  "pipe %s!\n",
				  ndr_interface_name(&id.uuid,
						     id.if_version),
				  ndr_interface_name(&id.uuid,
						     id.if_version)));
			return setup_bind_nak(p, pkt);
		}
	}

	DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));

	if (pkt->u.bind.assoc_group_id != 0) {
		assoc_gid = pkt->u.bind.assoc_group_id;
	} else {
		assoc_gid = 0x53f0;
	}

	/*
	 * Create the bind response struct.
	 */

	/* If the requested abstract synt uuid doesn't match our client pipe,
		reject the bind_ack & set the transfer interface synt to all 0's,
		ver 0 (observed when NT5 attempts to bind to abstract interfaces
		unknown to NT4)
		Needed when adding entries to a DACL from NT5 - SK */

	if (check_bind_req(p,
			&pkt->u.bind.ctx_list[0].abstract_syntax,
			&pkt->u.bind.ctx_list[0].transfer_syntaxes[0],
			pkt->u.bind.ctx_list[0].context_id)) {

		bind_ack_ctx.result = 0;
		bind_ack_ctx.reason.value = 0;
		bind_ack_ctx.syntax = pkt->u.bind.ctx_list[0].transfer_syntaxes[0];
	} else {
		p->pipe_bound = False;
		/* Rejection reason: abstract syntax not supported */
		bind_ack_ctx.result = DCERPC_BIND_PROVIDER_REJECT;
		bind_ack_ctx.reason.value = DCERPC_BIND_REASON_ASYNTAX;
		bind_ack_ctx.syntax = ndr_syntax_id_null;
	}

	/*
	 * Check if this is an authenticated bind request.
	 */
	if (pkt->auth_length) {
		/* Quick length check. Won't catch a bad auth footer,
		 * prevents overrun. */

		if (pkt->frag_length < RPC_HEADER_LEN +
					DCERPC_AUTH_TRAILER_LENGTH +
					pkt->auth_length) {
			DEBUG(0,("api_pipe_bind_req: auth_len (%u) "
				"too long for fragment %u.\n",
				(unsigned int)pkt->auth_length,
				(unsigned int)pkt->frag_length));
			goto err_exit;
		}

		/*
		 * Decode the authentication verifier.
		 */
		status = dcerpc_pull_dcerpc_auth(pkt,
						 &pkt->u.bind.auth_info,
						 &auth_info, p->endian);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Unable to unmarshall dcerpc_auth.\n"));
			goto err_exit;
		}

		auth_type = auth_info.auth_type;

		/* Work out if we have to sign or seal etc. */
		switch (auth_info.auth_level) {
		case DCERPC_AUTH_LEVEL_INTEGRITY:
			p->auth.auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
			break;
		case DCERPC_AUTH_LEVEL_PRIVACY:
			p->auth.auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
			break;
		case DCERPC_AUTH_LEVEL_CONNECT:
			p->auth.auth_level = DCERPC_AUTH_LEVEL_CONNECT;
			break;
		default:
			DEBUG(0, ("Unexpected auth level (%u).\n",
				(unsigned int)auth_info.auth_level ));
			goto err_exit;
		}

		switch (auth_type) {
		case DCERPC_AUTH_TYPE_NTLMSSP:
			if (!pipe_auth_generic_bind(p, pkt,
						    &auth_info, &auth_resp)) {
				goto err_exit;
			}
			assoc_gid = 0x7a77;
			break;

		case DCERPC_AUTH_TYPE_SCHANNEL:
			if (!pipe_auth_generic_bind(p, pkt,
						    &auth_info, &auth_resp)) {
				goto err_exit;
			}
			if (!session_info_set_session_key(p->session_info, generic_session_key())) {
				DEBUG(0, ("session_info_set_session_key failed\n"));
				goto err_exit;
			}
			p->pipe_bound = true;
			break;

		case DCERPC_AUTH_TYPE_SPNEGO:
		case DCERPC_AUTH_TYPE_KRB5:
			if (!pipe_auth_generic_bind(p, pkt,
						    &auth_info, &auth_resp)) {
				goto err_exit;
			}
			break;

		case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
			if (p->transport == NCALRPC && p->ncalrpc_as_system) {
				TALLOC_FREE(p->session_info);

				status = make_session_info_system(p,
								  &p->session_info);
				if (!NT_STATUS_IS_OK(status)) {
					goto err_exit;
				}

				auth_resp = data_blob_talloc(pkt,
							     "NCALRPC_AUTH_OK",
							     15);

				p->auth.auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM;
				p->pipe_bound = true;
			} else {
				goto err_exit;
			}
			break;

		case DCERPC_AUTH_TYPE_NONE:
			break;

		default:
			DEBUG(0, ("Unknown auth type %x requested.\n", auth_type));
			goto err_exit;
		}
	}

	if (auth_type == DCERPC_AUTH_TYPE_NONE) {
		/* Unauthenticated bind request. */
		/* We're finished - no more packets. */
		p->auth.auth_type = DCERPC_AUTH_TYPE_NONE;
		/* We must set the pipe auth_level here also. */
		p->auth.auth_level = DCERPC_AUTH_LEVEL_NONE;
		p->pipe_bound = True;
		/* The session key was initialized from the SMB
		 * session in make_internal_rpc_pipe_p */
	}

	ZERO_STRUCT(u.bind_ack);
	u.bind_ack.max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
	u.bind_ack.max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
	u.bind_ack.assoc_group_id = assoc_gid;

	/* name has to be \PIPE\xxxxx */
	u.bind_ack.secondary_address =
			talloc_asprintf(pkt, "\\PIPE\\%s",
					rpc_srv_get_pipe_srv_name(&id));
	if (!u.bind_ack.secondary_address) {
		DEBUG(0, ("Out of memory!\n"));
		goto err_exit;
	}
	u.bind_ack.secondary_address_size =
				strlen(u.bind_ack.secondary_address) + 1;

	u.bind_ack.num_results = 1;
	u.bind_ack.ctx_list = &bind_ack_ctx;

	/* NOTE: We leave the auth_info empty so we can calculate the padding
	 * later and then append the auth_info --simo */

	/*
	 * Marshall directly into the outgoing PDU space. We
	 * must do this as we need to set to the bind response
	 * header and are never sending more than one PDU here.
	 */

	pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;

	if (p->auth.hdr_signing) {
		pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
	}

	status = dcerpc_push_ncacn_packet(p->mem_ctx,
					  DCERPC_PKT_BIND_ACK,
					  pfc_flags,
					  auth_resp.length,
					  pkt->call_id,
					  &u,
					  &p->out_data.frag);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to marshall bind_ack packet. (%s)\n",
			  nt_errstr(status)));
	}

	if (auth_resp.length) {

		status = dcerpc_push_dcerpc_auth(pkt,
						 auth_type,
						 auth_info.auth_level,
						 0,
						 1, /* auth_context_id */
						 &auth_resp,
						 &auth_blob);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Marshalling of dcerpc_auth failed.\n"));
			goto err_exit;
		}
	}

	/* Now that we have the auth len store it into the right place in
	 * the dcerpc header */
	dcerpc_set_frag_length(&p->out_data.frag,
				p->out_data.frag.length + auth_blob.length);

	if (auth_blob.length) {

		if (!data_blob_append(p->mem_ctx, &p->out_data.frag,
					auth_blob.data, auth_blob.length)) {
			DEBUG(0, ("Append of auth info failed.\n"));
			goto err_exit;
		}
	}

	/*
	 * Setup the lengths for the initial reply.
	 */

	p->out_data.data_sent_length = 0;
	p->out_data.current_pdu_sent = 0;

	TALLOC_FREE(auth_blob.data);
	return True;

  err_exit:

	data_blob_free(&p->out_data.frag);
	TALLOC_FREE(auth_blob.data);
	return setup_bind_nak(p, pkt);
}