Ejemplo n.º 1
0
void check_dhcp_hosts(int fatal)
{
  /* If the same IP appears in more than one host config, then DISCOVER
     for one of the hosts will get the address, but REQUEST will be NAKed,
     since the address is reserved by the other one -> protocol loop. 
     Also check that FQDNs match the domain we are using. */
  
  struct dhcp_config *configs, *cp;
 
  for (configs = daemon->dhcp_conf; configs; configs = configs->next)
    {
      char *domain;

      if ((configs->flags & DHOPT_BANK) || fatal)
       {
	 for (cp = configs->next; cp; cp = cp->next)
	   if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
	     {
	       if (fatal)
		 die(_("duplicate IP address %s in dhcp-config directive."), 
		     inet_ntoa(cp->addr), EC_BADCONF);
	       else
		 my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."), 
			   inet_ntoa(cp->addr), daemon->dhcp_hosts_file);
	       configs->flags &= ~CONFIG_ADDR;
	     }
	 
	 /* split off domain part */
	 if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
	   configs->domain = domain;
       }
    }
}
Ejemplo n.º 2
0
void dhcp_init(void)
{
  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  struct sockaddr_in saddr;
  int oneopt = 1;
  struct dhcp_config *configs, *cp;

  if (fd == -1)
    die (_("cannot create DHCP socket : %s"), NULL, EC_BADNET);
  
  if (!fix_fd(fd) || 
#if defined(HAVE_LINUX_NETWORK)
      setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
#elif defined(IP_RECVIF)
      setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
#endif
      setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)  
    die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
  
  /* When bind-interfaces is set, there might be more than one dnmsasq
     instance binding port 67. That's OK if they serve different networks.
     Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD.
     OpenBSD <= 4.0 screws up IP_RECVIF when SO_REUSEPORT is set, but
     OpenBSD <= 3.9 doesn't have IP_RECVIF anyway, so we just have to elide
     this for OpenBSD 4.0, if you want more than one instance on oBSD4.0, tough. */

#ifndef OpenBSD4_0
  if (daemon->options & OPT_NOWILD)
    {
#ifdef SO_REUSEPORT
      int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
#else
      int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
#endif
      if (rc == -1)
	die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
    }
#endif
  
  memset(&saddr, 0, sizeof(saddr));
  saddr.sin_family = AF_INET;
  saddr.sin_port = htons(DHCP_SERVER_PORT);
  saddr.sin_addr.s_addr = INADDR_ANY;
#ifdef HAVE_SOCKADDR_SA_LEN
  saddr.sin_len = sizeof(struct sockaddr_in);
#endif

  if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
    die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET);

  daemon->dhcpfd = fd;

#ifndef HAVE_LINUX_NETWORK
  /* When we're not using capabilities, we need to do this here before
     we drop root. Also, set buffer size small, to avoid wasting
     kernel buffers */
  
  if (daemon->options & OPT_NO_PING)
    daemon->dhcp_icmp_fd = -1;
  else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 ||
	   setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 )
    die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET);
  
  /* Make BPF raw send socket */
  init_bpf();
#endif
  
  /* If the same IP appears in more than one host config, then DISCOVER
     for one of the hosts will get the address, but REQUEST will be NAKed,
     since the address is reserved by the other one -> protocol loop. 
     Also check that FQDNs match the domain we are using. */
  for (configs = daemon->dhcp_conf; configs; configs = configs->next)
    {
      char *domain;
      for (cp = configs->next; cp; cp = cp->next)
	if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr)
	  die(_("duplicate IP address %s in dhcp-config directive."), inet_ntoa(cp->addr), EC_BADCONF);
      
      if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname)))
	die(_("illegal domain %s in dhcp-config directive."), domain, EC_BADCONF);
    }
  
  daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet); 
  daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len);
}
Ejemplo n.º 3
0
WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
			   struct NetGetJoinableOUs *r)
{
#ifdef WITH_ADS
	NTSTATUS status;
	ADS_STATUS ads_status;
	ADS_STRUCT *ads = NULL;
	struct netr_DsRGetDCNameInfo *info = NULL;
	const char *dc = NULL;
	uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
			 DS_RETURN_DNS_NAME;

	status = dsgetdcname(ctx, NULL, r->in.domain,
			     NULL, NULL, flags, &info);
	if (!NT_STATUS_IS_OK(status)) {
		libnetapi_set_error_string(ctx, "%s",
			get_friendly_nt_error_msg(status));
		return ntstatus_to_werror(status);
	}

	dc = strip_hostname(info->dc_unc);

	ads = ads_init(info->domain_name, info->domain_name, dc);
	if (!ads) {
		return WERR_GENERAL_FAILURE;
	}

	SAFE_FREE(ads->auth.user_name);
	if (r->in.account) {
		ads->auth.user_name = SMB_STRDUP(r->in.account);
	} else if (ctx->username) {
		ads->auth.user_name = SMB_STRDUP(ctx->username);
	}

	SAFE_FREE(ads->auth.password);
	if (r->in.password) {
		ads->auth.password = SMB_STRDUP(r->in.password);
	} else if (ctx->password) {
		ads->auth.password = SMB_STRDUP(ctx->password);
	}

	ads_status = ads_connect_user_creds(ads);
	if (!ADS_ERR_OK(ads_status)) {
		ads_destroy(&ads);
		return WERR_DEFAULT_JOIN_REQUIRED;
	}

	ads_status = ads_get_joinable_ous(ads, ctx,
					  (char ***)r->out.ous,
					  (size_t *)r->out.ou_count);
	if (!ADS_ERR_OK(ads_status)) {
		ads_destroy(&ads);
		return WERR_DEFAULT_JOIN_REQUIRED;
	}

	ads_destroy(&ads);
	return WERR_OK;
#else
	return WERR_NOT_SUPPORTED;
#endif
}
Ejemplo n.º 4
0
WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
		       struct NetJoinDomain *r)
{
	struct libnet_JoinCtx *j = NULL;
	WERROR werr;

	if (!r->in.domain) {
		return WERR_INVALID_PARAM;
	}

	werr = libnet_init_JoinCtx(mem_ctx, &j);
	W_ERROR_NOT_OK_RETURN(werr);

	j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
	W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);

	if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
		NTSTATUS status;
		struct netr_DsRGetDCNameInfo *info = NULL;
		const char *dc = NULL;
		uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
				 DS_WRITABLE_REQUIRED |
				 DS_RETURN_DNS_NAME;
		status = dsgetdcname(mem_ctx, NULL, r->in.domain,
				     NULL, NULL, flags, &info);
		if (!NT_STATUS_IS_OK(status)) {
			libnetapi_set_error_string(mem_ctx,
				"%s", get_friendly_nt_error_msg(status));
			return ntstatus_to_werror(status);
		}

		dc = strip_hostname(info->dc_unc);
		j->in.dc_name = talloc_strdup(mem_ctx, dc);
		W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
	}

	if (r->in.account_ou) {
		j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
		W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
	}

	if (r->in.account) {
		j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
		W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
	}

	if (r->in.password) {
		j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
		W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
	}

	j->in.join_flags = r->in.join_flags;
	j->in.modify_config = true;
	j->in.debug = true;

	werr = libnet_Join(mem_ctx, j);
	if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
		libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
	}
	TALLOC_FREE(j);

	return werr;
}
Ejemplo n.º 5
0
WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
			 struct NetUnjoinDomain *r)
{
	struct libnet_UnjoinCtx *u = NULL;
	struct dom_sid domain_sid;
	const char *domain = NULL;
	WERROR werr;

	if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
		return WERR_SETUP_NOT_JOINED;
	}

	werr = libnet_init_UnjoinCtx(mem_ctx, &u);
	W_ERROR_NOT_OK_RETURN(werr);

	if (lp_realm()) {
		domain = lp_realm();
	} else {
		domain = lp_workgroup();
	}

	if (r->in.server_name) {
		u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
		W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
	} else {
		NTSTATUS status;
		struct netr_DsRGetDCNameInfo *info = NULL;
		const char *dc = NULL;
		uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
				 DS_WRITABLE_REQUIRED |
				 DS_RETURN_DNS_NAME;
		status = dsgetdcname(mem_ctx, NULL, domain,
				     NULL, NULL, flags, &info);
		if (!NT_STATUS_IS_OK(status)) {
			libnetapi_set_error_string(mem_ctx,
				"failed to find DC for domain %s: %s",
				domain,
				get_friendly_nt_error_msg(status));
			return ntstatus_to_werror(status);
		}

		dc = strip_hostname(info->dc_unc);
		u->in.dc_name = talloc_strdup(mem_ctx, dc);
		W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);

		u->in.domain_name = domain;
	}

	if (r->in.account) {
		u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
		W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
	}

	if (r->in.password) {
		u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
		W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
	}

	u->in.domain_name = domain;
	u->in.unjoin_flags = r->in.unjoin_flags;
	u->in.delete_machine_account = false;
	u->in.modify_config = true;
	u->in.debug = true;

	u->in.domain_sid = &domain_sid;

	werr = libnet_Unjoin(mem_ctx, u);
	if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
		libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
	}
	TALLOC_FREE(u);

	return werr;
}