Exemplo n.º 1
0
void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token)
{
	struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
	
	/* Set the security context */

	DEBUG(3, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", 
		(unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx));

	debug_nt_user_token(DBGC_CLASS, 5, token);
	debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups);

	gain_root();

#ifdef HAVE_SETGROUPS
	sys_setgroups(ngroups, groups);
#endif

	ctx_p->ut.ngroups = ngroups;

	SAFE_FREE(ctx_p->ut.groups);
	if (token && (token == ctx_p->token)) {
		smb_panic("DUPLICATE_TOKEN");
	}

	TALLOC_FREE(ctx_p->token);
	
	if (ngroups) {
		ctx_p->ut.groups = (gid_t *)memdup(groups,
						   sizeof(gid_t) * ngroups);
		if (!ctx_p->ut.groups) {
			smb_panic("memdup failed");
		}
	} else {
		ctx_p->ut.groups = NULL;
	}

	if (token) {
		ctx_p->token = dup_nt_token(NULL, token);
		if (!ctx_p->token) {
			smb_panic("dup_nt_token failed");
		}
	} else {
		ctx_p->token = NULL;
	}

	become_id(uid, gid);

	ctx_p->ut.uid = uid;
	ctx_p->ut.gid = gid;

	/* Update current_user stuff */

	current_user.ut.uid = uid;
	current_user.ut.gid = gid;
	current_user.ut.ngroups = ngroups;
	current_user.ut.groups = groups;
	current_user.nt_user_token = ctx_p->token;
}
Exemplo n.º 2
0
void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, const struct security_token *token)
{
	struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];

	/* Set the security context */

	DEBUG(4, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", 
		(unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx));

	security_token_debug(DBGC_CLASS, 5, token);
	debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups);

	/* Change uid, gid and supplementary group list. */
	set_unix_security_ctx(uid, gid, ngroups, groups);

	ctx_p->ut.ngroups = ngroups;

	SAFE_FREE(ctx_p->ut.groups);
	if (token && (token == ctx_p->token)) {
		smb_panic("DUPLICATE_TOKEN");
	}

	TALLOC_FREE(ctx_p->token);

	if (ngroups) {
		ctx_p->ut.groups = (gid_t *)memdup(groups,
						   sizeof(gid_t) * ngroups);
		if (!ctx_p->ut.groups) {
			smb_panic("memdup failed");
		}
	} else {
		ctx_p->ut.groups = NULL;
	}

	if (token) {
		ctx_p->token = dup_nt_token(NULL, token);
		if (!ctx_p->token) {
			smb_panic("dup_nt_token failed");
		}
	} else {
		ctx_p->token = NULL;
	}

	ctx_p->ut.uid = uid;
	ctx_p->ut.gid = gid;

	/* Update current_user stuff */

	current_user.ut.uid = uid;
	current_user.ut.gid = gid;
	current_user.ut.ngroups = ngroups;
	current_user.ut.groups = groups;
	current_user.nt_user_token = ctx_p->token;
}
Exemplo n.º 3
0
NTSTATUS create_local_token(struct auth_serversupplied_info *server_info)
{
	struct security_token *t;
	NTSTATUS status;
	size_t i;
	struct dom_sid tmp_sid;
	struct wbcUnixId *ids;

	/*
	 * If winbind is not around, we can not make much use of the SIDs the
	 * domain controller provided us with. Likewise if the user name was
	 * mapped to some local unix user.
	 */

	if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
	    (server_info->nss_token)) {
		status = create_token_from_username(server_info,
						    server_info->unix_name,
						    server_info->guest,
						    &server_info->utok.uid,
						    &server_info->utok.gid,
						    &server_info->unix_name,
						    &server_info->security_token);

	} else {
		status = create_local_nt_token_from_info3(server_info,
							  server_info->guest,
							  server_info->info3,
							  &server_info->extra,
							  &server_info->security_token);
	}

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

	/* Convert the SIDs to gids. */

	server_info->utok.ngroups = 0;
	server_info->utok.groups = NULL;

	t = server_info->security_token;

	ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId,
			   t->num_sids);
	if (ids == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) {
		TALLOC_FREE(ids);
		return NT_STATUS_NO_MEMORY;
	}

	/* Start at index 1, where the groups start. */

	for (i=1; i<t->num_sids; i++) {

		if (ids[i].type != WBC_ID_TYPE_GID) {
			DEBUG(10, ("Could not convert SID %s to gid, "
				   "ignoring it\n",
				   sid_string_dbg(&t->sids[i])));
			continue;
		}
		if (!add_gid_to_array_unique(server_info, ids[i].id.gid,
					     &server_info->utok.groups,
					     &server_info->utok.ngroups)) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	/*
	 * Add the "Unix Group" SID for each gid to catch mapped groups
	 * and their Unix equivalent.  This is to solve the backwards
	 * compatibility problem of 'valid users = +ntadmin' where
	 * ntadmin has been paired with "Domain Admins" in the group
	 * mapping table.  Otherwise smb.conf would need to be changed
	 * to 'valid user = "******"'.  --jerry
	 *
	 * For consistency we also add the "Unix User" SID,
	 * so that the complete unix token is represented within
	 * the nt token.
	 */

	uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid);

	add_sid_to_array_unique(server_info->security_token, &tmp_sid,
				&server_info->security_token->sids,
				&server_info->security_token->num_sids);

	for ( i=0; i<server_info->utok.ngroups; i++ ) {
		gid_to_unix_groups_sid(server_info->utok.groups[i], &tmp_sid);
		add_sid_to_array_unique(server_info->security_token, &tmp_sid,
					&server_info->security_token->sids,
					&server_info->security_token->num_sids);
	}

	security_token_debug(DBGC_AUTH, 10, server_info->security_token);
	debug_unix_user_token(DBGC_AUTH, 10,
			      server_info->utok.uid,
			      server_info->utok.gid,
			      server_info->utok.ngroups,
			      server_info->utok.groups);

	status = log_nt_token(server_info->security_token);
	return status;
}
Exemplo n.º 4
0
NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
			    const struct auth_serversupplied_info *server_info,
			    DATA_BLOB *session_key,
			    const char *smb_username, /* for ->sanitized_username, for %U subs */
			    struct auth_session_info **session_info_out)
{
	struct security_token *t;
	NTSTATUS status;
	size_t i;
	struct dom_sid tmp_sid;
	struct auth_session_info *session_info;
	struct unixid *ids;
	fstring tmp;

	/* Ensure we can't possible take a code path leading to a
	 * null defref. */
	if (!server_info) {
		return NT_STATUS_LOGON_FAILURE;
	}

	session_info = talloc_zero(mem_ctx, struct auth_session_info);
	if (!session_info) {
		return NT_STATUS_NO_MEMORY;
	}

	session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
	if (!session_info->unix_token) {
		TALLOC_FREE(session_info);
		return NT_STATUS_NO_MEMORY;
	}

	session_info->unix_token->uid = server_info->utok.uid;
	session_info->unix_token->gid = server_info->utok.gid;

	session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
	if (!session_info->unix_info) {
		TALLOC_FREE(session_info);
		return NT_STATUS_NO_MEMORY;
	}

	session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
	if (!session_info->unix_info->unix_name) {
		TALLOC_FREE(session_info);
		return NT_STATUS_NO_MEMORY;
	}

	/* This is a potentially untrusted username for use in %U */
	alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
	session_info->unix_info->sanitized_username =
				talloc_strdup(session_info->unix_info, tmp);

	if (session_key) {
		data_blob_free(&session_info->session_key);
		session_info->session_key = data_blob_talloc(session_info,
								  session_key->data,
								  session_key->length);
		if (!session_info->session_key.data && session_key->length) {
			return NT_STATUS_NO_MEMORY;
		}
	} else {
		session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
							      server_info->session_key.length);
	}

	/* We need to populate session_info->info with the information found in server_info->info3 */
	status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
					    server_info->guest == false,
					    &session_info->info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
		TALLOC_FREE(session_info);
		return status;
	}

	if (server_info->security_token) {
		/* Just copy the token, it has already been finalised
		 * (nasty hack to support a cached guest/system session_info
		 */

		session_info->security_token = dup_nt_token(session_info, server_info->security_token);
		if (!session_info->security_token) {
			TALLOC_FREE(session_info);
			return NT_STATUS_NO_MEMORY;
		}

		session_info->unix_token->ngroups = server_info->utok.ngroups;
		if (server_info->utok.ngroups != 0) {
			session_info->unix_token->groups = (gid_t *)talloc_memdup(
				session_info->unix_token, server_info->utok.groups,
				sizeof(gid_t)*session_info->unix_token->ngroups);
		} else {
			session_info->unix_token->groups = NULL;
		}

		*session_info_out = session_info;
		return NT_STATUS_OK;
	}

	/*
	 * If winbind is not around, we can not make much use of the SIDs the
	 * domain controller provided us with. Likewise if the user name was
	 * mapped to some local unix user.
	 */

	if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
	    (server_info->nss_token)) {
		char *found_username = NULL;
		status = create_token_from_username(session_info,
						    server_info->unix_name,
						    server_info->guest,
						    &session_info->unix_token->uid,
						    &session_info->unix_token->gid,
						    &found_username,
						    &session_info->security_token);
		if (NT_STATUS_IS_OK(status)) {
			session_info->unix_info->unix_name = found_username;
		}
	} else {
		status = create_local_nt_token_from_info3(session_info,
							  server_info->guest,
							  server_info->info3,
							  &server_info->extra,
							  &session_info->security_token);
	}

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

	/* Convert the SIDs to gids. */

	session_info->unix_token->ngroups = 0;
	session_info->unix_token->groups = NULL;

	t = session_info->security_token;

	ids = talloc_array(talloc_tos(), struct unixid,
			   t->num_sids);
	if (ids == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
		TALLOC_FREE(ids);
		return NT_STATUS_NO_MEMORY;
	}

	for (i=0; i<t->num_sids; i++) {

		if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
			continue;
		}

		if (ids[i].type != ID_TYPE_GID &&
		    ids[i].type != ID_TYPE_BOTH) {
			DEBUG(10, ("Could not convert SID %s to gid, "
				   "ignoring it\n",
				   sid_string_dbg(&t->sids[i])));
			continue;
		}
		if (!add_gid_to_array_unique(session_info, ids[i].id,
					     &session_info->unix_token->groups,
					     &session_info->unix_token->ngroups)) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	/*
	 * Add the "Unix Group" SID for each gid to catch mapped groups
	 * and their Unix equivalent.  This is to solve the backwards
	 * compatibility problem of 'valid users = +ntadmin' where
	 * ntadmin has been paired with "Domain Admins" in the group
	 * mapping table.  Otherwise smb.conf would need to be changed
	 * to 'valid user = "******"'.  --jerry
	 *
	 * For consistency we also add the "Unix User" SID,
	 * so that the complete unix token is represented within
	 * the nt token.
	 */

	uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);

	add_sid_to_array_unique(session_info->security_token, &tmp_sid,
				&session_info->security_token->sids,
				&session_info->security_token->num_sids);

	for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
		gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
		add_sid_to_array_unique(session_info->security_token, &tmp_sid,
					&session_info->security_token->sids,
					&session_info->security_token->num_sids);
	}

	security_token_debug(DBGC_AUTH, 10, session_info->security_token);
	debug_unix_user_token(DBGC_AUTH, 10,
			      session_info->unix_token->uid,
			      session_info->unix_token->gid,
			      session_info->unix_token->ngroups,
			      session_info->unix_token->groups);

	status = log_nt_token(session_info->security_token);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	*session_info_out = session_info;
	return NT_STATUS_OK;
}