Exemple #1
0
static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
{
	int retval;
	bool winbind_env;

	DEBUG(10,("sys_getgrouplist: user [%s]\n", user));

	/* This is only ever called for Unix users, remote memberships are
	 * always determined by the info3 coming back from auth3 or the
	 * PAC. */
	winbind_env = winbind_env_set();
	(void)winbind_off();

#ifdef HAVE_GETGROUPLIST
	retval = getgrouplist(user, gid, groups, grpcnt);
#else
#ifdef HAVE_GETGRSET
	retval = getgrouplist_getgrset(user, gid, groups, grpcnt);
#else
	become_root();
	retval = getgrouplist_internals(user, gid, groups, grpcnt);
	unbecome_root();
#endif /* HAVE_GETGRSET */
#endif /* HAVE_GETGROUPLIST */

	/* allow winbindd lookups, but only if they were not already disabled */
	if (!winbind_env) {
		(void)winbind_on();
	}

	return retval;
}
Exemple #2
0
int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
{
	char *p;
	int retval;

	DEBUG(10,("sys_getgrouplist: user [%s]\n", user));
	
	/* see if we should disable winbindd lookups for local users */
	if ( (p = strchr(user, *lp_winbind_separator())) == NULL ) {
		if ( !winbind_off() )
			DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n",
				WINBINDD_DONT_ENV));
		else
			DEBUG(10,("sys_getgrouplist(): disabled winbindd for group lookup [user == %s]\n",
				user));
	}

#ifdef HAVE_GETGROUPLIST
	retval = getgrouplist(user, gid, groups, grpcnt);
#else
	become_root();
	retval = getgrouplist_internals(user, gid, groups, grpcnt);
	unbecome_root();
#endif

	/* allow winbindd lookups */
	winbind_on();
	
	return retval;
}
Exemple #3
0
NTSTATUS make_server_info_sam(struct auth_serversupplied_info **server_info,
			      struct samu *sampass)
{
	struct passwd *pwd;
	struct auth_serversupplied_info *result;
	const char *username = pdb_get_username(sampass);
	NTSTATUS status;

	if ( !(result = make_server_info(NULL)) ) {
		return NT_STATUS_NO_MEMORY;
	}

	if ( !(pwd = Get_Pwnam_alloc(result, username)) ) {
		DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
			  pdb_get_username(sampass)));
		TALLOC_FREE(result);
		return NT_STATUS_NO_SUCH_USER;
	}

	status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
				  &result->info3, &result->extra);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(result);
		return status;
	}

	result->unix_name = pwd->pw_name;
	/* Ensure that we keep pwd->pw_name, because we will free pwd below */
	talloc_steal(result, pwd->pw_name);
	result->utok.gid = pwd->pw_gid;
	result->utok.uid = pwd->pw_uid;

	TALLOC_FREE(pwd);

	if (IS_DC && is_our_machine_account(username)) {
		/*
		 * This is a hack of monstrous proportions.
		 * If we know it's winbindd talking to us,
		 * we know we must never recurse into it,
		 * so turn off contacting winbindd for this
		 * entire process. This will get fixed when
		 * winbindd doesn't need to talk to smbd on
		 * a PDC. JRA.
		 */

		(void)winbind_off();

		DEBUG(10, ("make_server_info_sam: our machine account %s "
			   "turning off winbindd requests.\n", username));
	}

	DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
		 pdb_get_username(sampass), result->unix_name));

	*server_info = result;

	return NT_STATUS_OK;
}
Exemple #4
0
/*
  startup a copy of smbd as a child daemon
*/
static void s3fs_task_init(struct task_server *task)
{
	struct tevent_req *subreq;
	const char *smbd_path;
	const char *smbd_cmd[2] = { NULL, NULL };

	task_server_set_title(task, "task[s3fs_parent]");

	smbd_path = talloc_asprintf(task, "%s/smbd", dyn_SBINDIR);
	smbd_cmd[0] = smbd_path;

	/* the child should be able to call through nss_winbind */
	(void)winbind_on();
	/* start it as a child process */
	subreq = samba_runcmd_send(task, task->event_ctx, timeval_zero(), 1, 0,
				smbd_cmd,
				"--option=server role check:inhibit=yes",
				"--foreground",
				debug_get_output_is_stdout()?"--log-stdout":NULL,
				NULL);
	/* the parent should not be able to call through nss_winbind */
	if (!winbind_off()) {
		DEBUG(0,("Failed to re-disable recursive winbindd calls after forking smbd\n"));
		task_server_terminate(task, "Failed to re-disable recursive winbindd calls", true);
		return;
	}
	if (subreq == NULL) {
		DEBUG(0, ("Failed to start smbd as child daemon\n"));
		task_server_terminate(task, "Failed to startup s3fs smb task", true);
		return;
	}

	tevent_req_set_callback(subreq, file_server_smbd_done, task);

	DEBUG(5,("Started file server child smbd\n"));
}
Exemple #5
0
static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
{
	int i;

	/* initialize the status to avoid suprise */
	for (i = 0; ids[i]; i++) {
		ids[i]->status = ID_UNKNOWN;
	}

	for (i = 0; ids[i]; i++) {
		struct passwd *pw;
		struct group *gr;
		const char *name;
		enum lsa_SidType type;
		bool ret;

		switch (ids[i]->xid.type) {
		case ID_TYPE_UID:
			pw = getpwuid((uid_t)ids[i]->xid.id);

			if (!pw) {
				ids[i]->status = ID_UNMAPPED;
				continue;
			}
			name = pw->pw_name;
			break;
		case ID_TYPE_GID:
			gr = getgrgid((gid_t)ids[i]->xid.id);

			if (!gr) {
				ids[i]->status = ID_UNMAPPED;
				continue;
			}
			name = gr->gr_name;
			break;
		default: /* ?? */
			ids[i]->status = ID_UNKNOWN;
			continue;
		}

		/* by default calls to winbindd are disabled
		   the following call will not recurse so this is safe */
		(void)winbind_on();
		/* Lookup name from PDC using lsa_lookup_names() */
		ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type);
		(void)winbind_off();

		if (!ret) {
			/* TODO: how do we know if the name is really not mapped,
			 * or something just failed ? */
			ids[i]->status = ID_UNMAPPED;
			continue;
		}

		switch (type) {
		case SID_NAME_USER:
			if (ids[i]->xid.type == ID_TYPE_UID) {
				ids[i]->status = ID_MAPPED;
			}
			break;

		case SID_NAME_DOM_GRP:
		case SID_NAME_ALIAS:
		case SID_NAME_WKN_GRP:
			if (ids[i]->xid.type == ID_TYPE_GID) {
				ids[i]->status = ID_MAPPED;
			}
			break;

		default:
			ids[i]->status = ID_UNKNOWN;
			break;
		}
	}
	return NT_STATUS_OK;
}
Exemple #6
0
static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
{
	int i;

	/* initialize the status to avoid suprise */
	for (i = 0; ids[i]; i++) {
		ids[i]->status = ID_UNKNOWN;
	}

	for (i = 0; ids[i]; i++) {
		struct group *gr;
		enum lsa_SidType type;
		char *name = NULL;
		bool ret;

		/* by default calls to winbindd are disabled
		   the following call will not recurse so this is safe */
		(void)winbind_on();
		ret = winbind_lookup_sid(talloc_tos(), ids[i]->sid, NULL,
					 (const char **)&name, &type);
		(void)winbind_off();

		if (!ret) {
			/* TODO: how do we know if the name is really not mapped,
			 * or something just failed ? */
			ids[i]->status = ID_UNMAPPED;
			continue;
		}

		switch (type) {
		case SID_NAME_USER: {
			struct passwd *pw;

			/* this will find also all lower case name and use username level */

			pw = Get_Pwnam_alloc(talloc_tos(), name);
			if (pw) {
				ids[i]->xid.id = pw->pw_uid;
				ids[i]->xid.type = ID_TYPE_UID;
				ids[i]->status = ID_MAPPED;
			}
			TALLOC_FREE(pw);
			break;
		}

		case SID_NAME_DOM_GRP:
		case SID_NAME_ALIAS:
		case SID_NAME_WKN_GRP:

			gr = getgrnam(name);
			if (gr) {
				ids[i]->xid.id = gr->gr_gid;
				ids[i]->xid.type = ID_TYPE_GID;
				ids[i]->status = ID_MAPPED;
			}
			break;

		default:
			ids[i]->status = ID_UNKNOWN;
			break;
		}
		TALLOC_FREE(name);
	}
	return NT_STATUS_OK;
}
Exemple #7
0
static NTSTATUS idmap_nss_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
{
	TALLOC_CTX *ctx;
	int i;

	if (! dom->initialized) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	ctx = talloc_new(dom);
	if ( ! ctx) {
		DEBUG(0, ("Out of memory!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	for (i = 0; ids[i]; i++) {
		struct passwd *pw;
		struct group *gr;
		const char *name;
		enum lsa_SidType type;
		BOOL ret;
		
		switch (ids[i]->xid.type) {
		case ID_TYPE_UID:
			pw = getpwuid((uid_t)ids[i]->xid.id);

			if (!pw) {
				ids[i]->status = ID_UNMAPPED;
				continue;
			}
			name = pw->pw_name;
			break;
		case ID_TYPE_GID:
			gr = getgrgid((gid_t)ids[i]->xid.id);

			if (!gr) {
				ids[i]->status = ID_UNMAPPED;
				continue;
			}
			name = gr->gr_name;
			break;
		default: /* ?? */
			ids[i]->status = ID_UNKNOWN;
			continue;
		}

		/* by default calls to winbindd are disabled
		   the following call will not recurse so this is safe */
		winbind_on();
		/* Lookup name from PDC using lsa_lookup_names() */
		ret = winbind_lookup_name(dom->name, name, ids[i]->sid, &type);
		winbind_off();

		if (!ret) {
			/* TODO: how do we know if the name is really not mapped,
			 * or something just failed ? */
			ids[i]->status = ID_UNMAPPED;
			continue;
		}

		switch (type) {
		case SID_NAME_USER:
			if (ids[i]->xid.type == ID_TYPE_UID) {
				ids[i]->status = ID_MAPPED;
			}
			break;

		case SID_NAME_DOM_GRP:
		case SID_NAME_ALIAS:
		case SID_NAME_WKN_GRP:
			if (ids[i]->xid.type == ID_TYPE_GID) {
				ids[i]->status = ID_MAPPED;
			}
			break;

		default:
			ids[i]->status = ID_UNKNOWN;
			break;
		}
	}


	talloc_free(ctx);
	return NT_STATUS_OK;
}
Exemple #8
0
static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
{
	TALLOC_CTX *ctx;
	int i;

	if (! dom->initialized) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	ctx = talloc_new(dom);
	if ( ! ctx) {
		DEBUG(0, ("Out of memory!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	for (i = 0; ids[i]; i++) {
		struct passwd *pw;
		struct group *gr;
		enum lsa_SidType type;
		const char *dom_name = NULL;
		const char *name = NULL;
		BOOL ret;

		/* by default calls to winbindd are disabled
		   the following call will not recurse so this is safe */
		winbind_on();
		ret = winbind_lookup_sid(ctx, ids[i]->sid, &dom_name, &name, &type);
		winbind_off();

		if (!ret) {
			/* TODO: how do we know if the name is really not mapped,
			 * or something just failed ? */
			ids[i]->status = ID_UNMAPPED;
			continue;
		}

		switch (type) {
		case SID_NAME_USER:

			/* this will find also all lower case name and use username level */
			
			pw = Get_Pwnam(name);
			if (pw) {
				ids[i]->xid.id = pw->pw_uid;
				ids[i]->xid.type = ID_TYPE_UID;
				ids[i]->status = ID_MAPPED;
			}
			break;

		case SID_NAME_DOM_GRP:
		case SID_NAME_ALIAS:
		case SID_NAME_WKN_GRP:

			gr = getgrnam(name);
			if (gr) {
				ids[i]->xid.id = gr->gr_gid;
				ids[i]->xid.type = ID_TYPE_GID;
				ids[i]->status = ID_MAPPED;
			}
			break;

		default:
			ids[i]->status = ID_UNKNOWN;
			break;
		}
	}

	talloc_free(ctx);
	return NT_STATUS_OK;
}
Exemple #9
0
/*
 main server.
*/
static int binary_smbd_main(const char *binary_name, int argc, const char *argv[])
{
	bool opt_daemon = false;
	bool opt_interactive = false;
	int opt;
	poptContext pc;
#define _MODULE_PROTO(init) extern NTSTATUS init(void);
	STATIC_service_MODULES_PROTO;
	init_module_fn static_init[] = { STATIC_service_MODULES };
	init_module_fn *shared_init;
	struct tevent_context *event_ctx;
	uint16_t stdin_event_flags;
	NTSTATUS status;
	const char *model = "standard";
	int max_runtime = 0;
	struct stat st;
	enum {
		OPT_DAEMON = 1000,
		OPT_INTERACTIVE,
		OPT_PROCESS_MODEL,
		OPT_SHOW_BUILD
	};
	struct poptOption long_options[] = {
		POPT_AUTOHELP
		{"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON,
		 "Become a daemon (default)", NULL },
		{"interactive",	'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE,
		 "Run interactive (not a daemon)", NULL},
		{"model", 'M', POPT_ARG_STRING,	NULL, OPT_PROCESS_MODEL, 
		 "Select process model", "MODEL"},
		{"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0, 
		 "set maximum runtime of the server process, till autotermination", "seconds"},
		{"show-build", 'b', POPT_ARG_NONE, NULL, OPT_SHOW_BUILD, "show build info", NULL },
		POPT_COMMON_SAMBA
		POPT_COMMON_VERSION
		{ NULL }
	};

	pc = poptGetContext(binary_name, argc, argv, long_options, 0);
	while((opt = poptGetNextOpt(pc)) != -1) {
		switch(opt) {
		case OPT_DAEMON:
			opt_daemon = true;
			break;
		case OPT_INTERACTIVE:
			opt_interactive = true;
			break;
		case OPT_PROCESS_MODEL:
			model = poptGetOptArg(pc);
			break;
		case OPT_SHOW_BUILD:
			show_build();
			break;
		default:
			fprintf(stderr, "\nInvalid option %s: %s\n\n",
				  poptBadOption(pc, 0), poptStrerror(opt));
			poptPrintUsage(pc, stderr, 0);
			return 1;
		}
	}

	if (opt_daemon && opt_interactive) {
		fprintf(stderr,"\nERROR: "
			  "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
		poptPrintUsage(pc, stderr, 0);
		return 1;
	} else if (!opt_interactive) {
		/* default is --daemon */
		opt_daemon = true;
	}

	poptFreeContext(pc);

	talloc_enable_null_tracking();

	setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE);
	setup_signals();

	/* we want total control over the permissions on created files,
	   so set our umask to 0 */
	umask(0);

	DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
	DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2016\n"));

	if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
		DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
		DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n",
			    (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t)));
		return 1;
	}

	if (opt_daemon) {
		DEBUG(3,("Becoming a daemon.\n"));
		become_daemon(true, false, false);
	}

	cleanup_tmp_files(cmdline_lp_ctx);

	if (!directory_exist(lpcfg_lock_directory(cmdline_lp_ctx))) {
		mkdir(lpcfg_lock_directory(cmdline_lp_ctx), 0755);
	}

	pidfile_create(lpcfg_pid_directory(cmdline_lp_ctx), binary_name);

	if (lpcfg_server_role(cmdline_lp_ctx) == ROLE_ACTIVE_DIRECTORY_DC) {
		if (!open_schannel_session_store(talloc_autofree_context(), cmdline_lp_ctx)) {
			exit_daemon("Samba cannot open schannel store for secured NETLOGON operations.", EACCES);
		}
	}

	/* make sure we won't go through nss_winbind */
	if (!winbind_off()) {
		exit_daemon("Samba failed to disable recusive winbindd calls.", EACCES);
	}

	gensec_init(); /* FIXME: */

	ntptr_init();	/* FIXME: maybe run this in the initialization function 
						of the spoolss RPC server instead? */

	ntvfs_init(cmdline_lp_ctx); 	/* FIXME: maybe run this in the initialization functions 
						of the SMB[,2] server instead? */

	process_model_init(cmdline_lp_ctx); 

	shared_init = load_samba_modules(NULL, "service");

	run_init_functions(static_init);
	run_init_functions(shared_init);

	talloc_free(shared_init);
	
	/* the event context is the top level structure in smbd. Everything else
	   should hang off that */
	event_ctx = s4_event_context_init(talloc_autofree_context());

	if (event_ctx == NULL) {
		exit_daemon("Initializing event context failed", EACCES);
	}

	if (opt_interactive) {
		/* terminate when stdin goes away */
		stdin_event_flags = TEVENT_FD_READ;
	} else {
		/* stay alive forever */
		stdin_event_flags = 0;
	}

	/* catch EOF on stdin */
#ifdef SIGTTIN
	signal(SIGTTIN, SIG_IGN);
#endif

	if (fstat(0, &st) != 0) {
		exit_daemon("Samba failed to set standard input handler", ENOTTY);
	}

	if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
		tevent_add_fd(event_ctx,
				event_ctx,
				0,
				stdin_event_flags,
				server_stdin_handler,
				discard_const(binary_name));
	}

	if (max_runtime) {
		DEBUG(0,("Called with maxruntime %d - current ts %llu\n",
		      max_runtime, (unsigned long long) time(NULL)));
		tevent_add_timer(event_ctx, event_ctx,
				 timeval_current_ofs(max_runtime, 0),
				 max_runtime_handler,
				 discard_const(binary_name));
	}

	if (lpcfg_server_role(cmdline_lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC
	    && !lpcfg_parm_bool(cmdline_lp_ctx, NULL, "server role check", "inhibit", false)
	    && !str_list_check_ci(lpcfg_server_services(cmdline_lp_ctx), "smb") 
	    && !str_list_check_ci(lpcfg_dcerpc_endpoint_servers(cmdline_lp_ctx), "remote")
	    && !str_list_check_ci(lpcfg_dcerpc_endpoint_servers(cmdline_lp_ctx), "mapiproxy")) {
		DEBUG(0, ("At this time the 'samba' binary should only be used for either:\n"));
		DEBUGADD(0, ("'server role = active directory domain controller' or to access the ntvfs file server with 'server services = +smb' or the rpc proxy with 'dcerpc endpoint servers = remote'\n"));
		DEBUGADD(0, ("You should start smbd/nmbd/winbindd instead for domain member and standalone file server tasks\n"));
		exit_daemon("Samba detected misconfigured 'server role' and exited. Check logs for details", EINVAL);
	};

	prime_ldb_databases(event_ctx);

	status = setup_parent_messaging(event_ctx, cmdline_lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("Samba failed to setup parent messaging", NT_STATUS_V(status));
	}

	DEBUG(0,("%s: using '%s' process model\n", binary_name, model));

	status = server_service_startup(event_ctx, cmdline_lp_ctx, model, 
					lpcfg_server_services(cmdline_lp_ctx));
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("Samba failed to start services", NT_STATUS_V(status));
	}

	if (opt_daemon) {
		daemon_ready("samba");
	}

	/* wait for events - this is where smbd sits for most of its
	   life */
	tevent_loop_wait(event_ctx);

	/* as everything hangs off this event context, freeing it
	   should initiate a clean shutdown of all services */
	talloc_free(event_ctx);

	return 0;
}