pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


winsg.c - run Win32 or Cygwin program with a different group
Posted by Anonymous on Fri 24th May 2024 13:11
raw | new post
view followups (newest first): winsg.c - run Win32 or Cygwin program with a different group by Anonymous

  1.  
  2. /*
  3.  * MIT License
  4.  *
  5.  * Copyright (c) 2024 Roland Mainz <roland.mainz@nrubsig.org>
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  8.  * of this software and associated documentation files (the "Software"), to deal
  9.  * in the Software without restriction, including without limitation the rights
  10.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11.  * copies of the Software, and to permit persons to whom the Software is
  12.  * furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included in all
  15.  * copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23.  * SOFTWARE.
  24.  */
  25.  
  26. /*
  27.  * winsg.c - run Win32 or Cygwin program with a different group
  28.  *
  29.  * Written by Roland Mainz <roland.mainz@nrubsig.org>
  30.  */
  31.  
  32. #include <windows.h>
  33. #include <stdio.h>
  34. #include <stdbool.h>
  35. #include <Lmcons.h>
  36. #include <process.h>
  37.  
  38. /*
  39.  * Performance hack:
  40.  * GETTOKINFO_EXTRA_BUFFER - extra space for more data
  41.  * |GetTokenInformation()| for |TOKEN_USER| and |TOKEN_PRIMARY_GROUP|
  42.  * always fails in Win10 with |ERROR_INSUFFICIENT_BUFFER| if you
  43.  * just pass the |sizeof(TOKEN_*)| value. Instead of calling
  44.  * |GetTokenInformation()| with |NULL| arg to obtain the size to
  45.  * allocate we just provide 2048 bytes of extra space after the
  46.  * |TOKEN_*| size, and pray it is enough
  47.  */
  48. #define GETTOKINFO_EXTRA_BUFFER (2048)
  49.  
  50. bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
  51. {
  52.     DWORD tokdatalen;
  53.     PTOKEN_PRIMARY_GROUP ptpgroup;
  54.     PSID pgsid;
  55.     DWORD namesize = GNLEN+1;
  56.     char domainbuffer[UNLEN+1];
  57.     DWORD domainbuffer_size = sizeof(domainbuffer);
  58.     SID_NAME_USE name_use;
  59.  
  60.     tokdatalen = sizeof(TOKEN_PRIMARY_GROUP)+GETTOKINFO_EXTRA_BUFFER;
  61.     ptpgroup = _alloca(tokdatalen);
  62.     if (!GetTokenInformation(tok, TokenPrimaryGroup, ptpgroup,
  63.         tokdatalen, &tokdatalen)) {
  64.         (void)fprintf(stderr, "get_token_primarygroup_name: "
  65.             "GetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
  66.             "status=%d\n",
  67.             (void *)tok, (int)GetLastError());
  68.         return false;
  69.     }
  70.  
  71.     pgsid = ptpgroup->PrimaryGroup;
  72.  
  73.     if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
  74.         domainbuffer, &domainbuffer_size, &name_use)) {
  75.         (void)fprintf(stderr, "get_token_primarygroup_name: "
  76.             "LookupAccountSidA() failed, status=%d\n",
  77.             (int)GetLastError());
  78.         return false;
  79.     }
  80.  
  81.     return true;
  82. }
  83.  
  84. bool set_token_primarygroup_name(HANDLE tok, const char *new_groupname)
  85. {
  86.     DWORD tokdatalen;
  87.     TOKEN_PRIMARY_GROUP tpgroup;
  88.     char sidbuff[SECURITY_MAX_SID_SIZE+1];
  89.     PSID pgsid = (PSID)sidbuff;
  90.     DWORD pgsid_size = sizeof(sidbuff);
  91.     char domainbuffer[UNLEN+1];
  92.     DWORD domainbuffer_size = sizeof(domainbuffer);
  93.     SID_NAME_USE name_use;
  94.  
  95.     if (!LookupAccountNameA(NULL, new_groupname,
  96.         pgsid, &pgsid_size, domainbuffer, &domainbuffer_size, &name_use)) {
  97.         (void)fprintf(stderr, "set_token_primarygroup_name: "
  98.             "LookupAccountNameA() failed.\n");
  99.         return false;
  100.     }
  101.  
  102.     tokdatalen = sizeof(TOKEN_PRIMARY_GROUP);
  103.     tpgroup.PrimaryGroup = pgsid;
  104.     if (!SetTokenInformation(tok, TokenPrimaryGroup,
  105.         &tpgroup, tokdatalen)) {
  106.         (void)fprintf(stderr, "set_token_primarygroup_name: "
  107.             "SetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
  108.             "status=%d\n",
  109.             (void *)tok, (int)GetLastError());
  110.         return false;
  111.     }
  112.  
  113.     return true;
  114. }
  115.  
  116. enum shelltype {
  117.     SHELLTYPE_NOT_SET = 0,
  118.     SHELLTYPE_NONE,
  119.     SHELLTYPE_CMD,
  120.     SHELLTYPE_SYSTEM
  121. };
  122.  
  123. int main(int ac, char *av[])
  124. {
  125.     char pgroupname[GNLEN+1];
  126.     enum shelltype st = SHELLTYPE_NOT_SET;
  127.     int cmd_arg_index = -1;
  128.     const char *newgrpname = NULL;
  129.     int subcmdret = EXIT_FAILURE;
  130.  
  131.     int i;
  132.  
  133.     for (i=1 ; i < ac ; i++) {
  134.         (void)fprintf(stderr, "# i=%d, av[i]='%s'\n", i, av[i]);
  135.  
  136.         if (!strcmp(av[i], "-")) {
  137.             (void)fprintf(stderr, "%s: Run in new login not supported yet.\n", av[0]);
  138.             return 1;
  139.         }
  140.         else if (!strcmp(av[i], "-c")) {
  141.             st = SHELLTYPE_SYSTEM;
  142.             cmd_arg_index = i+1;
  143.             break;
  144.         }
  145.         else if (!strcmp(av[i], "/C")) {
  146.             st = SHELLTYPE_CMD;
  147.             cmd_arg_index = i+1;
  148.             break;
  149.         }
  150.         else if (!strcmp(av[i], "-g")) {
  151.             newgrpname = av[i+1];
  152.             i++;
  153.         }
  154.         else {
  155.             if ((i == 1) && (*av[i] != '-')) {
  156.                 newgrpname = av[i];
  157.                 continue;
  158.             }
  159.  
  160.             cmd_arg_index = i+1;
  161.             st = SHELLTYPE_NONE;
  162.             break;
  163.         }
  164.     }
  165.  
  166.     if ((st == SHELLTYPE_NOT_SET) && (cmd_arg_index == -1)) {
  167.         st = SHELLTYPE_NONE;
  168.         cmd_arg_index = 2;
  169.     }
  170.  
  171.     if (!newgrpname) {
  172.         (void)fprintf(stderr, "%s: No group name given.\n", av[0]);
  173.         return 1;
  174.     }
  175.  
  176.     (void)fprintf(stderr, "# shelltype=%d, cmd_arg_index=%d, av[cmd_arg_index]='%s', new group name '%s'\n",
  177.         (int)st, cmd_arg_index, av[cmd_arg_index], newgrpname);
  178.  
  179.     HANDLE tok;
  180.  
  181.     if (!OpenProcessToken(GetCurrentProcess(),
  182.         /*TOKEN_ALL_ACCESS*/TOKEN_QUERY|TOKEN_ADJUST_DEFAULT|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY,
  183.         &tok)) {
  184.         (void)fprintf(stderr, "OpenThreadToken failed.\n");
  185.         return 1;
  186.     }
  187.  
  188.     get_token_primarygroup_name(tok, pgroupname);
  189.     (void)printf("primary group name '%s'\n", pgroupname);
  190.  
  191.     set_token_primarygroup_name(tok, newgrpname);
  192.  
  193.     get_token_primarygroup_name(tok, pgroupname);
  194.     (void)printf("primary group name '%s'\n", pgroupname);
  195.  
  196.     (void)_flushall();
  197.  
  198.     switch(st) {
  199. #define CYGWIN_BASH_PATH "C:\\cygwin64\\bin\\bash.exe"
  200. #define WIN32_CMD_PATH "C:\\Windows\\system32\\cmd.exe"
  201.         case SHELLTYPE_SYSTEM:
  202.             if (av[cmd_arg_index] != NULL) {
  203.                 char cmdbuff[4096];
  204.                 snprintf(cmdbuff, sizeof(cmdbuff), "%s -c %s", "C:\\cygwin64\\bin\\bash.exe", av[cmd_arg_index]);
  205.                 subcmdret = system(cmdbuff);
  206.             }
  207.             else {
  208.                 subcmdret = system("C:\\cygwin64\\bin\\bash.exe");
  209.             }
  210.             break;
  211.         case SHELLTYPE_CMD:
  212.             if (av[cmd_arg_index] != NULL) {
  213.                 subcmdret = _spawnl(_P_WAIT, WIN32_CMD_PATH, WIN32_CMD_PATH, "/C", av[cmd_arg_index], NULL);
  214.             }
  215.             else {
  216.                 subcmdret = _spawnl(_P_WAIT, WIN32_CMD_PATH, WIN32_CMD_PATH, NULL);
  217.             }
  218.             break;
  219.         case SHELLTYPE_NONE:
  220.             if (av[cmd_arg_index] != NULL) {
  221.                 subcmdret = _spawnv(_P_WAIT, av[cmd_arg_index], (const char *const *)&av[cmd_arg_index]);
  222.             }
  223.             else {
  224.                 subcmdret = _spawnl(_P_WAIT, WIN32_CMD_PATH, WIN32_CMD_PATH, NULL);
  225.             }
  226.             break;
  227.         default:
  228.     }
  229.  
  230.     (void)fprintf(stdout, "#mark winsg done, retval=%d\n", (int)subcmdret);
  231.     return 0;
  232. }

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at