pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS

Difference between
modified post f94e417c8 by Anonymous on Fri 24th May 2024 14:13
original post b668b4 by Anonymous on Fri 24th May 2024 14:03
Download diff
Show old version | new version | both versions

    
11
22
/*
33
 * MIT License
44
 *
55
 * Copyright (c) 2024 Roland Mainz <roland.mainz@nrubsig.org>
66
 *
77
 * Permission is hereby granted, free of charge, to any person obtaining a copy
88
 * of this software and associated documentation files (the "Software"), to deal
99
 * in the Software without restriction, including without limitation the rights
1010
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1111
 * copies of the Software, and to permit persons to whom the Software is
1212
 * furnished to do so, subject to the following conditions:
1313
 *
1414
 * The above copyright notice and this permission notice shall be included in all
1515
 * copies or substantial portions of the Software.
1616
 *
1717
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1818
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1919
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2020
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2121
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2222
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2323
 * SOFTWARE.
2424
 */
2525
2626
/*
2727
 * winsg.c - run Win32 or Cygwin program with a different (primary) group
2828
 *
2929
 * Written by Roland Mainz <roland.mainz@nrubsig.org>
3030
 */
3131
32+
/*
3237
#include <windows.h>
3338
#include <stdio.h>
3439
#include <stdbool.h>
3540
#include <Lmcons.h>
3641
#include <process.h>
3742
3843
#if 0
3944
#define D(x) x
4045
#else
4146
#define D(x)
4247
#endif
4348
4449
/*
4550
 * Performance hack:
4651
 * GETTOKINFO_EXTRA_BUFFER - extra space for more data
4752
 * |GetTokenInformation()| for |TOKEN_USER| and |TOKEN_PRIMARY_GROUP|
4853
 * always fails in Win10 with |ERROR_INSUFFICIENT_BUFFER| if you
4954
 * just pass the |sizeof(TOKEN_*)| value. Instead of calling
5055
 * |GetTokenInformation()| with |NULL| arg to obtain the size to
5156
 * allocate we just provide 2048 bytes of extra space after the
5257
 * |TOKEN_*| size, and pray it is enough
5358
 */
5459
#define GETTOKINFO_EXTRA_BUFFER (2048)
5560
5661
bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
5762
{
5863
    DWORD tokdatalen;
5964
    PTOKEN_PRIMARY_GROUP ptpgroup;
6065
    PSID pgsid;
6166
    DWORD namesize = GNLEN+1;
6267
    char domainbuffer[UNLEN+1];
6368
    DWORD domainbuffer_size = sizeof(domainbuffer);
6469
    SID_NAME_USE name_use;
6570
6671
    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP)+GETTOKINFO_EXTRA_BUFFER;
6772
    ptpgroup = _alloca(tokdatalen);
6873
    if (!GetTokenInformation(tok, TokenPrimaryGroup, ptpgroup,
6974
        tokdatalen, &tokdatalen)) {
7075
        D((void)fprintf(stderr, "get_token_primarygroup_name: "
7176
            "GetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
7277
            "status=%d\n",
7378
            (void *)tok, (int)GetLastError()));
7479
        return false;
7580
    }
7681
7782
    pgsid = ptpgroup->PrimaryGroup;
7883
7984
    if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
8085
        domainbuffer, &domainbuffer_size, &name_use)) {
8186
        D((void)fprintf(stderr, "get_token_primarygroup_name: "
8287
            "LookupAccountSidA() failed, status=%d\n",
8388
            (int)GetLastError()));
8489
        return false;
8590
    }
8691
8792
    return true;
8893
}
8994
9095
bool is_group_in_token(HANDLE tok, PSID qsid)
9196
{
9297
    DWORD tokdatalen;
9398
    PTOKEN_GROUPS ptgroups;
9499
95100
    tokdatalen = sizeof(TOKEN_GROUPS)+GETTOKINFO_EXTRA_BUFFER;
96101
    ptgroups = _alloca(tokdatalen);
97102
    if (!GetTokenInformation(tok, TokenGroups, ptgroups,
98103
        tokdatalen, &tokdatalen)) {
99104
        D((void)fprintf(stderr, "is_group_in_token: "
100105
            "GetTokenInformation(tok=0x%p, TokenGroups) failed, "
101106
            "status=%d\n",
102107
            (void *)tok, (int)GetLastError()));
103108
        return false;
104109
    }
105110
106111
    int i;
107112
    D((void)fprintf(stderr, "is_group_in_token: got %d groups\n", (int)ptgroups->GroupCount));
108113
    for (i = 0 ; i < ptgroups->GroupCount ; i++) {
109114
        if (EqualSid(qsid, ptgroups->Groups[i].Sid) &&
110115
            (ptgroups->Groups[i].Attributes & SE_GROUP_ENABLED)) {
111116
            D((void)puts("#match"));
112117
            return true;
113118
        }
114119
    }
115120
116121
    D((void)puts("#no match"));
117122
118123
    return false;
119124
}
120125
121126
bool set_token_primarygroup_name(HANDLE tok, const char *new_groupname)
122127
{
123128
    DWORD tokdatalen;
124129
    TOKEN_PRIMARY_GROUP tpgroup;
125130
    char sidbuff[SECURITY_MAX_SID_SIZE+1];
126131
    PSID pgsid = (PSID)sidbuff;
127132
    DWORD pgsid_size = sizeof(sidbuff);
128133
    char domainbuffer[UNLEN+1];
129134
    DWORD domainbuffer_size = sizeof(domainbuffer);
130135
    SID_NAME_USE name_use;
131136
132137
    if (!LookupAccountNameA(NULL, new_groupname,
133138
        pgsid, &pgsid_size, domainbuffer, &domainbuffer_size, &name_use)) {
134139
        D((void)fprintf(stderr, "set_token_primarygroup_name: "
135140
            "LookupAccountNameA() failed.\n"));
136141
        return false;
137142
    }
138143
139144
    if (!is_group_in_token(tok, pgsid)) {
140145
        D((void)fprintf(stderr, "set_token_primarygroup_name: "
141146
            "group '%s' is not a member.\n", new_groupname));
142147
        return false;
143148
    }
144149
145150
    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP);
146151
    tpgroup.PrimaryGroup = pgsid;
147152
    if (!SetTokenInformation(tok, TokenPrimaryGroup,
148153
        &tpgroup, tokdatalen)) {
149154
        D((void)fprintf(stderr, "set_token_primarygroup_name: "
150155
            "SetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
151156
            "status=%d\n",
152157
            (void *)tok, (int)GetLastError()));
153158
        return false;
154159
    }
155160
156161
    return true;
157162
}
158163
159164
enum shelltype {
160165
    SHELLTYPE_NOT_SET = 0,
161166
    SHELLTYPE_NONE,
162167
    SHELLTYPE_CMD,
163168
    SHELLTYPE_SYSTEM
164169
};
165170
166171
int main(int ac, char *av[])
167172
{
168173
    enum shelltype st = SHELLTYPE_NOT_SET;
169174
    int cmd_arg_index = -1;
170175
    const char *newgrpname = NULL;
171176
    int subcmdret = EXIT_FAILURE;
172177
173178
    int i;
174179
175180
    for (i=1 ; i < ac ; i++) {
176181
        D((void)fprintf(stderr, "# i=%d, av[i]='%s'\n", i, av[i]));
177182
178183
        if (!strcmp(av[i], "-")) {
179184
            (void)fprintf(stderr, "%s: Run in new login not supported yet.\n", av[0]);
180185
            return 1;
181186
        }
182187
        else if (!strcmp(av[i], "-c")) {
183188
            st = SHELLTYPE_SYSTEM;
184189
            cmd_arg_index = i+1;
185190
            break;
186191
        }
187192
        else if (!strcmp(av[i], "/C")) {
188193
            st = SHELLTYPE_CMD;
189194
            cmd_arg_index = i+1;
190195
            break;
191196
        }
192197
        else if (!strcmp(av[i], "-g")) {
193198
            newgrpname = av[i+1];
194199
            i++;
195200
        }
196201
        else {
197202
            if ((i == 1) && (*av[i] != '-')) {
198203
                newgrpname = av[i];
199204
                continue;
200205
            }
201206
202207
            cmd_arg_index = i+1;
203208
            st = SHELLTYPE_NONE;
204209
            break;
205210
        }
206211
    }
207212
208213
    /*
209-
     * Handle newgrp(1)-like behaviour (run new shell/cmd.exe
214+
     * Handle newgrp(1)-like behaviour (run new shell (in our
210-
     * with requested group), e.g.
215+
     * case cmd.exe) with requested group), e.g. ...
211216
     * $ winsg -g cygwingrp1
212217
     * $ winsg cygwingrp1
213218
     */
214219
    if ((st == SHELLTYPE_NOT_SET) && (cmd_arg_index == -1)) {
215220
        st = SHELLTYPE_NONE;
216-
        cmd_arg_index = 2;
221+
        /* set |cmd_arg_index| to the end of |av|, which is |NULL| */
222+
        cmd_arg_index = i;
217223
    }
218224
219225
    if (!newgrpname) {
220226
        (void)fprintf(stderr, "%s: No group name given.\n", av[0]);
221227
        return 1;
222228
    }
223229
224230
    D((void)fprintf(stderr,
225231
        "# shelltype=%d, cmd_arg_index=%d, "
226232
        "av[cmd_arg_index]='%s', "
227233
        "new group name '%s'\n",
228234
        (int)st, cmd_arg_index, av[cmd_arg_index], newgrpname));
229235
230236
    HANDLE tok;
231237
232238
    if (!OpenProcessToken(GetCurrentProcess(),
233239
        TOKEN_QUERY|TOKEN_ADJUST_DEFAULT|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY,
234240
        &tok)) {
235241
        (void)fprintf(stderr, "%s: Cannot open token.\n", av[0]);
236242
        return 1;
237243
    }
238244
239245
    D(
240246
        char pgroupname[GNLEN+1];
241247
242248
        get_token_primarygroup_name(tok, pgroupname);
243249
        (void)printf("primary group name '%s'\n", pgroupname);
244250
    )
245251
246252
    if (!set_token_primarygroup_name(tok, newgrpname)) {
247253
        (void)fprintf(stderr,
248254
            "%s: Could not switch to new primary group '%s'.\n",
249255
            av[0], newgrpname);
250256
        return 1;
251257
    }
252258
253259
    D(
254260
        get_token_primarygroup_name(tok, pgroupname);
255261
        (void)printf("primary group name '%s'\n", pgroupname);
256262
    )
257263
258264
    (void)_flushall();
259265
260266
    switch(st) {
261267
#define CYGWIN_BASH_PATH "C:\\cygwin64\\bin\\bash.exe"
262268
#define WIN32_CMD_PATH "C:\\Windows\\system32\\cmd.exe"
263269
        case SHELLTYPE_SYSTEM:
264270
            if (av[cmd_arg_index] != NULL) {
265271
                size_t cmdbuff_size = strlen(CYGWIN_BASH_PATH)+
266272
                    16+
267273
                    strlen(av[cmd_arg_index]);
268274
                char *cmdbuff = alloca(cmdbuff_size);
269275
                (void)snprintf(cmdbuff, cmdbuff_size,
270276
                    "%s -c '%s'", CYGWIN_BASH_PATH,
271277
                    av[cmd_arg_index]);
272278
                subcmdret = system(cmdbuff);
273279
            }
274280
            else {
275281
                subcmdret = system(CYGWIN_BASH_PATH);
276282
            }
277283
            break;
278284
        case SHELLTYPE_CMD:
279285
            if (av[cmd_arg_index] != NULL) {
280286
                subcmdret = _spawnl(_P_WAIT,
281287
                    WIN32_CMD_PATH, WIN32_CMD_PATH,
282288
                    "/C", av[cmd_arg_index], NULL);
283289
            }
284290
            else {
285291
                subcmdret = _spawnl(_P_WAIT,
286292
                    WIN32_CMD_PATH, WIN32_CMD_PATH, NULL);
287293
            }
288294
            break;
289295
        case SHELLTYPE_NONE:
290296
            if (av[cmd_arg_index] != NULL) {
291297
                subcmdret = _spawnv(_P_WAIT,
292298
                    av[cmd_arg_index],
293299
                    (const char *const *)&av[cmd_arg_index]);
294300
            }
295301
            else {
296302
                subcmdret = _spawnl(_P_WAIT,
297303
                    WIN32_CMD_PATH, WIN32_CMD_PATH, NULL);
298304
            }
299305
            break;
300306
        default:
301307
            break;
302308
    }
303309
304310
    D((void)fprintf(stdout, "#mark winsg done, retval=%d\n", (int)subcmdret));
305311
    return 0;
306312
}
307313

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