pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS

Difference between
modified post 3da241c by Anonymous on Fri 24th May 2024 16:30
original post 46221e by Anonymous on Fri 24th May 2024 15:53
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
3232
/*
3333
 * Compile with:
3434
 * $ clang -target x86_64-pc-windows-gnu -Wall -DUNICODE=1 -D_UNICODE=1 -g winsg.c -o winsg.exe #
3535
 */
3636
3737
#include <windows.h>
3838
#include <stdio.h>
3939
#include <stdbool.h>
4040
#include <assert.h>
4141
#include <Lmcons.h>
4242
#include <process.h>
4343
4444
#if 0
4545
#define D(x) x
4646
#else
4747
#define D(x)
4848
#endif
4949
5050
#ifdef _WIN64
5151
#define CYGWIN_BASH_PATH "C:\\cygwin64\\bin\\bash.exe"
5252
#else
5353
#define CYGWIN_BASH_PATH "C:\\cygwin\\bin\\bash.exe"
5454
#endif /* _WIN64 */
5555
#define WIN32_CMDEXE_PATH "C:\\Windows\\system32\\cmd.exe"
5656
5757
/*
5858
 * Performance hack:
5959
 * GETTOKINFO_EXTRA_BUFFER - extra space for more data
6060
 * |GetTokenInformation()| for |TOKEN_USER| and |TOKEN_PRIMARY_GROUP|
6161
 * always fails in Win10 with |ERROR_INSUFFICIENT_BUFFER| if you
6262
 * just pass the |sizeof(TOKEN_*)| value. Instead of calling
6363
 * |GetTokenInformation()| with |NULL| arg to obtain the size to
6464
 * allocate we just provide 2048 bytes of extra space after the
6565
 * |TOKEN_*| size, and pray it is enough
6666
 */
6767
#define GETTOKINFO_EXTRA_BUFFER (2048)
6868
6969
D(
7070
static
7171
bool get_token_primarygroup_name(HANDLE tok, char *out_buffer)
7272
{
7373
    DWORD tokdatalen;
7474
    PTOKEN_PRIMARY_GROUP ptpgroup;
7575
    PSID pgsid;
7676
    DWORD namesize = GNLEN+1;
7777
    char domainbuffer[UNLEN+1];
7878
    DWORD domainbuffer_size = sizeof(domainbuffer);
7979
    SID_NAME_USE name_use;
8080
8181
    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP)+GETTOKINFO_EXTRA_BUFFER;
8282
    ptpgroup = _alloca(tokdatalen);
8383
    if (!GetTokenInformation(tok, TokenPrimaryGroup, ptpgroup,
8484
        tokdatalen, &tokdatalen)) {
8585
        D((void)fprintf(stderr, "get_token_primarygroup_name: "
8686
            "GetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
8787
            "status=%d.\n",
8888
            (void *)tok, (int)GetLastError()));
8989
        return false;
9090
    }
9191
9292
    pgsid = ptpgroup->PrimaryGroup;
9393
9494
    if (!LookupAccountSidA(NULL, pgsid, out_buffer, &namesize,
9595
        domainbuffer, &domainbuffer_size, &name_use)) {
9696
        D((void)fprintf(stderr, "get_token_primarygroup_name: "
9797
            "LookupAccountSidA() failed, status=%d.\n",
9898
            (int)GetLastError()));
9999
        return false;
100100
    }
101101
102102
    return true;
103103
}
104104
)
105105
106106
static
107107
bool is_group_in_token(HANDLE tok, PSID qsid)
108108
{
109109
    DWORD tokdatalen;
110110
    PTOKEN_GROUPS ptgroups;
111111
112112
    tokdatalen = sizeof(TOKEN_GROUPS)+GETTOKINFO_EXTRA_BUFFER;
113113
    ptgroups = _alloca(tokdatalen);
114114
    if (!GetTokenInformation(tok, TokenGroups, ptgroups,
115115
        tokdatalen, &tokdatalen)) {
116116
        D((void)fprintf(stderr, "is_group_in_token: "
117117
            "GetTokenInformation(tok=0x%p, TokenGroups) failed, "
118118
            "status=%d.\n",
119119
            (void *)tok, (int)GetLastError()));
120120
        return false;
121121
    }
122122
123123
    int i;
124124
    D(
125125
        (void)fprintf(stderr, "is_group_in_token: got %d groups\n",
126126
            (int)ptgroups->GroupCount)
127127
    );
128128
    for (i = 0 ; i < ptgroups->GroupCount ; i++) {
129129
        if (EqualSid(qsid, ptgroups->Groups[i].Sid) &&
130130
            (ptgroups->Groups[i].Attributes & SE_GROUP_ENABLED)) {
131131
            D((void)puts("is_group_in_token: #match"));
132132
            return true;
133133
        }
134134
    }
135135
136136
    D((void)puts("is_group_in_token: #no match"));
137137
138138
    return false;
139139
}
140140
141141
static
142142
bool get_group_sid(const char *groupname, PSID pgsid, PDWORD pgsid_size)
143143
{
144144
    char domainbuffer[UNLEN+1];
145145
    DWORD domainbuffer_size = sizeof(domainbuffer);
146146
    SID_NAME_USE name_use;
147147
148148
    if (!LookupAccountNameA(NULL, groupname,
149149
        pgsid, pgsid_size, domainbuffer, &domainbuffer_size, &name_use)) {
150150
        D((void)fprintf(stderr, "get_group_sid: "
151151
            "LookupAccountNameA() failed.\n"));
152152
        return false;
153153
    }
154154
155155
    return true;
156156
}
157157
158158
static
159159
bool set_token_primarygroup_sid(HANDLE tok, PSID pgsid)
160160
{
161161
    DWORD tokdatalen;
162162
    TOKEN_PRIMARY_GROUP tpgroup;
163163
164164
    tokdatalen = sizeof(TOKEN_PRIMARY_GROUP);
165165
    tpgroup.PrimaryGroup = pgsid;
166166
    if (!SetTokenInformation(tok, TokenPrimaryGroup,
167167
        &tpgroup, tokdatalen)) {
168168
        D((void)fprintf(stderr, "set_token_primarygroup_sid: "
169169
            "SetTokenInformation(tok=0x%p, TokenPrimaryGroup) failed, "
170170
            "status=%d\n",
171171
            (void *)tok, (int)GetLastError()));
172172
        return false;
173173
    }
174174
175175
    return true;
176176
}
177177
178178
static
179179
char *stpcpy (char *s1, const char *s2)
180180
{
181181
    size_t l = strlen(s2);
182182
    return memcpy(s1, s2, l+1) + l;
183183
}
184184
185185
static
186186
void win32cmd_quotearg(char *s1, const char *s2)
187187
{
188188
    int c;
189189
    *s1++ = '"';
190190
    while ((c = *s2) != '\0') {
191191
        switch(c) {
192192
            case '"':
193193
                *s1++='\\';
194194
                *s1 = c;
195195
                break;
196196
            default:
197197
                *s1 = c;
198198
                break;
199199
        }
200200
        s1++;
201201
        s2++;
202202
    }
203203
    *s1++ = '"';
204204
    *s1 = '\0';
205205
}
206206
207207
208208
enum shelltype {
209209
    SHELLTYPE_NOT_SET = 0,
210210
    SHELLTYPE_NONE,
211211
    SHELLTYPE_CMD,
212212
    SHELLTYPE_SYSTEM
213213
};
214214
215215
int main(int ac, char *av[])
216216
{
217217
    enum shelltype st = SHELLTYPE_NOT_SET;
218218
    int cmd_arg_index = -1;
219219
    const char *newgrpname = NULL;
220+
    HANDLE tok = INVALID_HANDLE_VALUE;
220221
    int subcmdret = EXIT_FAILURE;
222+
    int retval = 1;
222223
    int i;
223224
224225
    for (i=1 ; i < ac ; i++) {
225226
        D((void)fprintf(stderr, "# i=%d, av[i]='%s'\n", i, av[i]));
226227
227228
        if (!strcmp(av[i], "-")) {
228229
            (void)fprintf(stderr, "%s: "
229230
                "Run in new login not supported yet.\n", av[0]);
230-
            return 1;
231+
            retval = 1;
232+
            goto done;
231233
        }
232234
        else if (!strcmp(av[i], "-c")) {
233235
            /* -c can take zero or one argument */
234236
            if ((ac-i) > 2) {
235237
                (void)fprintf(stderr, "%s: "
236238
                    "Too many arguments for -c.\n", av[0]);
237-
                return 1;
239+
                retval = 1;
240+
                goto done;
238241
            }
239242
240243
            st = SHELLTYPE_SYSTEM;
241244
            cmd_arg_index = i+1;
242245
            break;
243246
        }
244247
        else if (!strcmp(av[i], "/C")) {
245248
            /* /C can take zero or one argument */
246249
            if ((ac-i) > 2) {
247250
                (void)fprintf(stderr, "%s: "
248251
                    "Too many arguments for /C.\n", av[0]);
249-
                return 1;
252+
                retval = 1;
253+
                goto done;
250254
            }
251255
252256
            st = SHELLTYPE_CMD;
253257
            cmd_arg_index = i+1;
254258
            break;
255259
        }
256260
        else if (!strcmp(av[i], "-g")) {
257261
            newgrpname = av[i+1];
258262
            i++;
259263
        }
260264
        else if ((av[i][0] == '-') || (av[i][0] == '/')) {
261265
            (void)fprintf(stderr, "%s: "
262266
                "Unsupported option '%s'.\n", av[0], av[i]);
263-
            return 1;
267+
            retval = 1;
268+
            goto done;
264269
        }
265270
        else {
266271
            if ((i == 1) && (*av[i] != '-')) {
267272
                newgrpname = av[i];
268273
                continue;
269274
            }
270275
271276
            cmd_arg_index = i+1;
272277
            st = SHELLTYPE_NONE;
273278
            break;
274279
        }
275280
    }
276281
277282
    /*
278283
     * Handle newgrp(1)-like behaviour (run new shell (in our
279284
     * case cmd.exe) with requested group), e.g. ...
280285
     * $ winsg -g cygwingrp1
281286
     * $ winsg cygwingrp1
282287
     */
283288
    if ((st == SHELLTYPE_NOT_SET) && (cmd_arg_index == -1)) {
284289
        st = SHELLTYPE_NONE;
285290
        /* set |cmd_arg_index| to the end of |av|, which is |NULL| */
286291
        cmd_arg_index = i;
287292
    }
288293
289294
    if (!newgrpname) {
290295
        (void)fprintf(stderr, "%s: No group name given.\n", av[0]);
291-
        return 1;
296+
        retval = 1;
297+
        goto done;
292298
    }
293299
294300
    D((void)fprintf(stderr,
295301
        "# shelltype=%d, cmd_arg_index=%d, "
296302
        "av[cmd_arg_index]='%s', "
297303
        "new group name '%s'\n",
298304
        (int)st, cmd_arg_index, av[cmd_arg_index], newgrpname));
299305
301-
306+
    if (!OpenProcessToken(GetCurrentProcess(),

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