public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: drop create_token and dependent functions
@ 2022-05-13 12:38 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2022-05-13 12:38 UTC (permalink / raw)
  To: cygwin-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=ca313dd8f4ceb7673c1c2fffb7da2c7bb291da30

commit ca313dd8f4ceb7673c1c2fffb7da2c7bb291da30
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Mon Mar 7 11:29:42 2022 +0100

    Cygwin: drop create_token and dependent functions
    
    Given we only called create_token on W7 WOW64 anyway, we can now
    drop this function and all other functions only called from there
    entirely.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/sec_auth.cc | 368 +---------------------------------------------
 winsup/cygwin/security.h  |   2 -
 winsup/cygwin/spawn.cc    |   8 +-
 winsup/cygwin/syscalls.cc |  23 +--
 4 files changed, 9 insertions(+), 392 deletions(-)

diff --git a/winsup/cygwin/sec_auth.cc b/winsup/cygwin/sec_auth.cc
index a7610c71f..a15778db0 100644
--- a/winsup/cygwin/sec_auth.cc
+++ b/winsup/cygwin/sec_auth.cc
@@ -379,41 +379,6 @@ sid_in_token_groups (PTOKEN_GROUPS grps, cygpsid sid)
   return false;
 }
 
-static void
-get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps)
-{
-  if (my_grps)
-    {
-      grp_list += well_known_local_sid;
-      grp_list += well_known_console_logon_sid;
-      if (sid_in_token_groups (my_grps, well_known_dialup_sid))
-	grp_list *= well_known_dialup_sid;
-      if (sid_in_token_groups (my_grps, well_known_network_sid))
-	grp_list *= well_known_network_sid;
-      if (sid_in_token_groups (my_grps, well_known_batch_sid))
-	grp_list *= well_known_batch_sid;
-      grp_list *= well_known_interactive_sid;
-#if 0
-      /* Don't add the SERVICE group when switching the user context.
-	 That's much too dangerous, since the service group adds the
-	 SE_IMPERSONATE_NAME privilege to the user.  After all, the
-	 process started with this token is not the service process
-	 anymore anyway. */
-      if (sid_in_token_groups (my_grps, well_known_service_sid))
-	grp_list *= well_known_service_sid;
-#endif
-      if (sid_in_token_groups (my_grps, well_known_this_org_sid))
-	grp_list *= well_known_this_org_sid;
-      grp_list *= well_known_users_sid;
-    }
-  else
-    {
-      grp_list += well_known_local_sid;
-      grp_list *= well_known_interactive_sid;
-      grp_list *= well_known_users_sid;
-    }
-}
-
 bool
 get_server_groups (cygsidlist &grp_list, PSID usersid,
 		   acct_disabled_chk_t check_account_disabled)
@@ -470,180 +435,6 @@ get_server_groups (cygsidlist &grp_list, PSID usersid,
   return true;
 }
 
-static bool
-get_initgroups_sidlist (cygsidlist &grp_list, PSID usersid, PSID pgrpsid,
-			PTOKEN_GROUPS my_grps)
-{
-  if (well_known_system_sid != usersid)
-    get_token_group_sidlist (grp_list, my_grps);
-  if (!get_server_groups (grp_list, usersid, CHK_DISABLED))
-    return false;
-
-  /* special_pgrp true if pgrpsid is not in normal groups */
-  grp_list += pgrpsid;
-  return true;
-}
-
-static bool
-get_setgroups_sidlist (cygsidlist &tmp_list, PSID usersid,
-		       PTOKEN_GROUPS my_grps, user_groups &groups)
-{
-  get_token_group_sidlist (tmp_list, my_grps);
-  if (!get_server_groups (tmp_list, usersid, CHK_DISABLED))
-    return false;
-  for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
-    tmp_list += groups.sgsids.sids[gidx];
-  tmp_list += groups.pgsid;
-  return true;
-}
-
-/* Fixed size TOKEN_PRIVILEGES list to reflect privileges given to the
-   SYSTEM account by default. */
-const struct
-{
-  DWORD PrivilegeCount;
-  LUID_AND_ATTRIBUTES Privileges[28];
-} sys_privs =
-{
-  28,
-  {
-    { { SE_CREATE_TOKEN_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_LOCK_MEMORY_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_INCREASE_QUOTA_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_TCB_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_SECURITY_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_TAKE_OWNERSHIP_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_LOAD_DRIVER_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_SYSTEM_PROFILE_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_SYSTEMTIME_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_INC_BASE_PRIORITY_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_CREATE_PAGEFILE_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_CREATE_PERMANENT_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_BACKUP_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_RESTORE_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_SHUTDOWN_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_DEBUG_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_AUDIT_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_CHANGE_NOTIFY_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_UNDOCK_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_MANAGE_VOLUME_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_IMPERSONATE_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_CREATE_GLOBAL_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_INCREASE_WORKING_SET_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_TIME_ZONE_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
-    { { SE_CREATE_SYMBOLIC_LINK_PRIVILEGE, 0 },
-	SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }
-  }
-};
-
-static PTOKEN_PRIVILEGES
-get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list,
-	       size_t &size, cygpsid *mandatory_integrity_sid)
-{
-  PLSA_UNICODE_STRING privstrs;
-  ULONG cnt;
-  PTOKEN_PRIVILEGES privs = NULL;
-
-  if (usersid == well_known_system_sid)
-    {
-      if (mandatory_integrity_sid)
-	*mandatory_integrity_sid = mandatory_system_integrity_sid;
-      return (PTOKEN_PRIVILEGES) &sys_privs;
-    }
-
-  if (mandatory_integrity_sid)
-    *mandatory_integrity_sid = mandatory_medium_integrity_sid;
-
-  for (int grp = -1; grp < grp_list.count (); ++grp)
-    {
-      if (grp == -1)
-	{
-	  if (LsaEnumerateAccountRights (lsa, usersid, &privstrs, &cnt)
-	      != STATUS_SUCCESS)
-	    continue;
-	}
-      else if (LsaEnumerateAccountRights (lsa, grp_list.sids[grp],
-					  &privstrs, &cnt) != STATUS_SUCCESS)
-	continue;
-      for (ULONG i = 0; i < cnt; ++i)
-	{
-	  LUID priv;
-	  PTOKEN_PRIVILEGES tmp;
-	  DWORD tmp_count;
-	  bool high_integrity;
-
-	  if (!privilege_luid (privstrs[i].Buffer, priv, high_integrity))
-	    continue;
-
-	  if (privs)
-	    {
-	      DWORD pcnt = privs->PrivilegeCount;
-	      LUID_AND_ATTRIBUTES *p = privs->Privileges;
-	      for (; pcnt > 0; --pcnt, ++p)
-		if (priv.HighPart == p->Luid.HighPart
-		    && priv.LowPart == p->Luid.LowPart)
-		  goto next_account_right;
-	    }
-
-	  tmp_count = privs ? privs->PrivilegeCount : 0;
-	  size = sizeof (DWORD)
-		 + (tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES);
-	  tmp = (PTOKEN_PRIVILEGES) realloc (privs, size);
-	  if (!tmp)
-	    {
-	      if (privs)
-		free (privs);
-	      LsaFreeMemory (privstrs);
-	      debug_printf ("realloc (privs) failed.");
-	      return NULL;
-	    }
-	  tmp->PrivilegeCount = tmp_count;
-	  privs = tmp;
-	  privs->Privileges[privs->PrivilegeCount].Luid = priv;
-	  privs->Privileges[privs->PrivilegeCount].Attributes =
-	    SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
-	  ++privs->PrivilegeCount;
-	  if (mandatory_integrity_sid && high_integrity)
-	    *mandatory_integrity_sid = mandatory_high_integrity_sid;
-
-	next_account_right:
-	  ;
-	}
-      LsaFreeMemory (privstrs);
-    }
-  return privs;
-}
-
 /* Accept a token if
    - the requested usersid matches the TokenUser and
    - if setgroups has been called:
@@ -654,9 +445,8 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list,
 	they match and verify only the primary groups.
 	The requested primary group must appear in the token.
 	The primary group in the token is a group associated with the usersid,
-	except if the token is internal and the group is in the token SD
-	(see create_token). In that latter case that group must match the
-	requested primary group.  */
+	except if the token is internal and the group is in the token SD.  In
+	that latter case that group must match the requested primary group.  */
 bool
 verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
 {
@@ -786,160 +576,6 @@ account_restriction (NTSTATUS status)
   return type;
 }
 
-HANDLE
-create_token (cygsid &usersid, user_groups &new_groups)
-{
-  NTSTATUS status;
-  LSA_HANDLE lsa = NULL;
-
-  cygsidlist tmp_gsids (cygsidlist_auto, 12);
-
-  SECURITY_QUALITY_OF_SERVICE sqos =
-    { sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE };
-  OBJECT_ATTRIBUTES oa = { sizeof oa, 0, 0, 0, 0, &sqos };
-  /* Up to Windows 7, when using an authentication LUID other than "Anonymous",
-     Windows whoami prints the wrong username, the one from the login session,
-     not the one from the actual user token of the process.  This is apparently
-     fixed in Windows 8.  However, starting with Windows 8, access rights of
-     the anonymous logon session is further restricted.  Therefore we create
-     the new user token with the authentication id of the local service
-     account.  Hopefully that's sufficient. */
-  const LUID auth_luid_7 = ANONYMOUS_LOGON_LUID;
-  const LUID auth_luid_8 = LOCALSERVICE_LUID;
-  LUID auth_luid = wincap.has_broken_whoami () ? auth_luid_7 : auth_luid_8;
-  LARGE_INTEGER exp = { QuadPart:INT64_MAX };
-
-  TOKEN_USER user;
-  PTOKEN_GROUPS new_tok_gsids = NULL;
-  PTOKEN_PRIVILEGES privs = NULL;
-  TOKEN_OWNER owner;
-  TOKEN_PRIMARY_GROUP pgrp;
-  TOKEN_DEFAULT_DACL dacl = {};
-  TOKEN_SOURCE source;
-  TOKEN_STATISTICS stats;
-  memcpy (source.SourceName, "Cygwin.1", 8);
-  source.SourceIdentifier.HighPart = 0;
-  source.SourceIdentifier.LowPart = 0x0101;
-
-  HANDLE token = NULL;
-  HANDLE primary_token = NULL;
-
-  tmp_pathbuf tp;
-  PTOKEN_GROUPS my_tok_gsids = NULL;
-  cygpsid mandatory_integrity_sid;
-  ULONG size;
-  size_t psize = 0;
-
-  /* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */
-  push_self_privilege (SE_CREATE_TOKEN_PRIVILEGE, true);
-
-  /* Open policy object. */
-  if (!(lsa = lsa_open_policy (NULL, POLICY_EXECUTE)))
-    goto out;
-
-  /* User, owner, primary group. */
-  user.User.Sid = usersid;
-  user.User.Attributes = 0;
-  owner.Owner = usersid;
-
-  /* Retrieve authentication id and group list from own process. */
-  if (hProcToken)
-    {
-      /* Switching user context to SYSTEM doesn't inherit the authentication
-	 id of the user account running current process. */
-      if (usersid == well_known_system_sid)
-	/* nothing to do */;
-      else
-	{
-	  status = NtQueryInformationToken (hProcToken, TokenStatistics,
-					    &stats, sizeof stats, &size);
-	  if (!NT_SUCCESS (status))
-	    debug_printf ("NtQueryInformationToken(hProcToken, "
-			  "TokenStatistics), %y", status);
-	}
-
-      /* Retrieving current processes group list to be able to inherit
-	 some important well known group sids. */
-      my_tok_gsids = (PTOKEN_GROUPS) tp.w_get ();
-      status = NtQueryInformationToken (hProcToken, TokenGroups, my_tok_gsids,
-					2 * NT_MAX_PATH, &size);
-      if (!NT_SUCCESS (status))
-	{
-	  debug_printf ("NtQueryInformationToken(hProcToken, TokenGroups), "
-			"%y", status);
-	  my_tok_gsids = NULL;
-	}
-    }
-
-  /* Create list of groups, the user is member in. */
-  if (new_groups.issetgroups ())
-    {
-      if (!get_setgroups_sidlist (tmp_gsids, usersid, my_tok_gsids, new_groups))
-	goto out;
-    }
-  else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid,
-				    my_tok_gsids))
-    goto out;
-
-  /* Primary group. */
-  pgrp.PrimaryGroup = new_groups.pgsid;
-
-  /* Create a TOKEN_GROUPS list from the above retrieved list of sids. */
-  new_tok_gsids = (PTOKEN_GROUPS)
-		  alloca (sizeof (DWORD) + (tmp_gsids.count () + 1)
-					   * sizeof (SID_AND_ATTRIBUTES));
-  new_tok_gsids->GroupCount = tmp_gsids.count ();
-  for (DWORD i = 0; i < new_tok_gsids->GroupCount; ++i)
-    {
-      new_tok_gsids->Groups[i].Sid = tmp_gsids.sids[i];
-      new_tok_gsids->Groups[i].Attributes = SE_GROUP_MANDATORY
-					    | SE_GROUP_ENABLED_BY_DEFAULT
-					    | SE_GROUP_ENABLED;
-    }
-
-  /* Retrieve list of privileges of that user.  Based on the usersid and
-     the returned privileges, get_priv_list sets the mandatory_integrity_sid
-     pointer to the correct MIC SID for UAC. */
-  if (!(privs = get_priv_list (lsa, usersid, tmp_gsids, psize,
-			       &mandatory_integrity_sid)))
-    goto out;
-
-  new_tok_gsids->Groups[new_tok_gsids->GroupCount].Attributes =
-    SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
-  new_tok_gsids->Groups[new_tok_gsids->GroupCount++].Sid
-    = mandatory_integrity_sid;
-
-  /* Let's be heroic... */
-  status = NtCreateToken (&token, TOKEN_ALL_ACCESS, &oa, TokenImpersonation,
-			  &auth_luid, &exp, &user, new_tok_gsids, privs, &owner,
-			  &pgrp, &dacl, &source);
-  if (status)
-    __seterrno_from_nt_status (status);
-  else
-    {
-      /* Convert to primary token. */
-      if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, &sec_none,
-			     SecurityImpersonation, TokenPrimary,
-			     &primary_token))
-	{
-	  __seterrno ();
-	  debug_printf ("DuplicateTokenEx %E");
-	  primary_token = NULL;
-	}
-    }
-
-out:
-  pop_self_privilege ();
-  if (token != INVALID_HANDLE_VALUE)
-    CloseHandle (token);
-  if (privs && privs != (PTOKEN_PRIVILEGES) &sys_privs)
-    free (privs);
-  lsa_close_policy (lsa);
-
-  debug_printf ("%p = create_token ()", primary_token);
-  return primary_token;
-}
-
 #define SFU_LSA_KEY_SUFFIX	L"_microsoft_sfu_utility"
 
 HANDLE
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 3e6688cd9..651f6d0e8 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -457,8 +457,6 @@ int setacl (HANDLE, path_conv &, int, struct acl *, bool &);
 
 /* Set impersonation or restricted token.  */
 void set_imp_token (HANDLE token, int type);
-/* Function creating a token by calling NtCreateToken. */
-HANDLE create_token (cygsid &usersid, user_groups &groups);
 /* LSA private key storage authentication, same as when using service logons. */
 HANDLE lsaprivkeyauth (struct passwd *pw);
 /* Kerberos or MsV1 S4U logon. */
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index c9e1fb6d2..98b588698 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -752,11 +752,9 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
 	      sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
 			     ::cygheap->user.sid ());
 	      /* We're creating a window station per user, not per logon
-		 session First of all we might not have a valid logon session
-		 for the user (logon by create_token), and second, it doesn't
-		 make sense in terms of security to create a new window
-		 station for every logon of the same user.  It just fills up
-		 the system with window stations for no good reason. */
+		 session.  It doesn't make sense in terms of security to
+		 create a new window station for every logon of the same user.
+		 It just fills up the system with window stations. */
 	      hwst = CreateWindowStationW (::cygheap->user.get_windows_id (sid),
 					   0, GENERIC_READ | GENERIC_WRITE, sa);
 	      if (!hwst)
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index b68d1f215..3a652c4f4 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -3607,8 +3607,7 @@ seteuid32 (uid_t uid)
   debug_printf ("Found token %p", new_token);
 
   /* If no impersonation token is available, try to authenticate using
-     LSA private data stored password, LSA authentication using our own
-     LSA module, or, as last chance, NtCreateToken. */
+     LSA private data stored password, or, if that fails, S4U logon. */
   if (new_token == NULL)
     {
       if (!(new_token = lsaprivkeyauth (pw_new)))
@@ -3621,23 +3620,9 @@ seteuid32 (uid_t uid)
 	  extract_nt_dom_user (pw_new, domain, user);
 	  if (!(new_token = s4uauth (true, domain, user, status)))
 	    {
-	      if (status != STATUS_INVALID_PARAMETER)
-		{
-		  debug_printf ("s4uauth failed, bail out");
-		  cygheap->user.reimpersonate ();
-		  return -1;
-		}
-	      /* If s4uauth fails with status code STATUS_INVALID_PARAMETER,
-		 we're running on a system not implementing MsV1_0S4ULogon
-		 (Windows 7 WOW64).  Fall back to create_token in this single
-		 case only. */
-	      debug_printf ("s4uauth failed, try create_token.");
-	      if (!(new_token = create_token (usersid, groups)))
-		{
-		  debug_printf ("create_token failed, bail out");
-		  cygheap->user.reimpersonate ();
-		  return -1;
-		}
+	      debug_printf ("s4uauth failed, bail out");
+	      cygheap->user.reimpersonate ();
+	      return -1;
 	    }
 	}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-13 12:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-13 12:38 [newlib-cygwin] Cygwin: drop create_token and dependent functions Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).