summaryrefslogtreecommitdiffstats
path: root/private/ntos/npfs/secursup.c
blob: c6869a55b92d58e33af9b780d780defe4f15dac3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    SecurSup.c

Abstract:

    This module implements the Named Pipe Security support routines

Author:

    Gary Kimura     [GaryKi]    06-May-1991

Revision History:

--*/

#include "NpProcs.h"

//
//  The debug trace level
//

#define Dbg                              (DEBUG_TRACE_SECURSUP)

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, NpCopyClientContext)
#pragma alloc_text(PAGE, NpImpersonateClientContext)
#pragma alloc_text(PAGE, NpInitializeSecurity)
#pragma alloc_text(PAGE, NpSetDataEntryClientContext)
#pragma alloc_text(PAGE, NpUninitializeSecurity)
#endif


NTSTATUS
NpInitializeSecurity (
    IN PCCB Ccb,
    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
    IN PETHREAD UserThread
    )

/*++

Routine Description:

    This routine initializes the security (impersonation) fields
    in the ccb.  It is called when the client end gets opened.

Arguments:

    Ccb - Supplies the ccb being initialized

    SecurityQos - Supplies the clients quality of service parameter

    UserThread - Supplise the client's user thread

Return Value:

    NTSTATUS - Returns the result of the operation

--*/

{
    NTSTATUS Status;

    PAGED_CODE();

    DebugTrace(+1, Dbg, "NpInitializeSecurity, Ccb = %08lx\n", Ccb);

    //
    //  Either copy the security qos parameter, if it is not null or
    //  create a dummy qos
    //

    if (SecurityQos != NULL) {

        RtlCopyMemory( &Ccb->SecurityQos,
                       SecurityQos,
                       sizeof(SECURITY_QUALITY_OF_SERVICE) );

    } else {

        Ccb->SecurityQos.Length              = sizeof(SECURITY_QUALITY_OF_SERVICE);
        Ccb->SecurityQos.ImpersonationLevel  = SecurityImpersonation;
        Ccb->SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
        Ccb->SecurityQos.EffectiveOnly       = TRUE;
    }

    //
    //  Because we might be asked to reinitialize the ccb we need
    //  to first check if the security client context is not null and if so then
    //  free its pool
    //

    if (Ccb->SecurityClientContext != NULL) {

        SeDeleteClientSecurity( Ccb->SecurityClientContext );
        ExFreePool( Ccb->SecurityClientContext );
    }

    //
    //  If the tracking mode is static then we need to capture the
    //  client context now otherwise we set the client context field
    //  to null
    //

    if (Ccb->SecurityQos.ContextTrackingMode == SECURITY_STATIC_TRACKING) {

        //
        //  Allocate a client context record, and then initialize it
        //

        Ccb->SecurityClientContext = FsRtlAllocatePool( PagedPool,
                                                        sizeof(SECURITY_CLIENT_CONTEXT) );

        DebugTrace(0, Dbg, "Static tracking, ClientContext = %08lx\n", Ccb->SecurityClientContext);

        if (!NT_SUCCESS(Status = SeCreateClientSecurity( UserThread,
                                                         &Ccb->SecurityQos,
                                                         FALSE,
                                                         Ccb->SecurityClientContext ))) {

            DebugTrace(0, Dbg, "Not successful at creating client security, %08lx\n", Status);

            ExFreePool( Ccb->SecurityClientContext );
            Ccb->SecurityClientContext = NULL;
        }

    } else {

        DebugTrace(0, Dbg, "Dynamic tracking\n", 0);

        Ccb->SecurityClientContext = NULL;
        Status = STATUS_SUCCESS;
    }

    DebugTrace(-1, Dbg, "NpInitializeSecurity -> %08lx\n", Status);

    return Status;
}


VOID
NpUninitializeSecurity (
    IN PCCB Ccb
    )

/*++

Routine Description:

    This routine deletes the client context referenced by the ccb

Arguments:

    Ccb - Supplies the ccb being uninitialized

Return Value:

    None

--*/

{
    PAGED_CODE();

    DebugTrace(+1, Dbg, "NpUninitializeSecurity, Ccb = %08lx\n", Ccb);

    //
    //  We only have work to do if the client context field is not null
    //  and then we need to delete the client context, and free the memory.
    //

    if (Ccb->SecurityClientContext != NULL) {

        DebugTrace(0, Dbg, "Delete client context, %08lx\n", Ccb->SecurityClientContext);

        SeDeleteClientSecurity( Ccb->SecurityClientContext );

        ExFreePool( Ccb->SecurityClientContext );
        Ccb->SecurityClientContext = NULL;
    }

    DebugTrace(-1, Dbg, "NpUninitializeSecurity -> VOID\n", 0);

    return;
}


NTSTATUS
NpSetDataEntryClientContext (
    IN NAMED_PIPE_END NamedPipeEnd,
    IN PCCB Ccb,
    IN PDATA_ENTRY DataEntry,
    IN PETHREAD UserThread
    )

/*++

Routine Description:

    This routine captures a new client context and stores it in the indicated
    data entry, but only if the tracking mode is dynamic and only for the
    client end of the named pipe.

Arguments:

    NamedPipeEnd - Indicates the client or server end of the named pipe.
        Only the client end does anything.

    Ccb - Supplies the ccb for this instance of the named pipe.

    DataEntry - Supplies the data entry to use to store the client context

    UserThread - Supplies the thread of the client

Return Value:

    NTSTATUS - Returns our success code.

--*/

{
    NTSTATUS Status;

    PAGED_CODE();

    DebugTrace(+1, Dbg, "NpSetDataEntryClientContext, Ccb = %08lx\n", Ccb);

    //
    //  Only do the work if this is the client end and tracking is dynamic
    //

    if ((NamedPipeEnd == FILE_PIPE_CLIENT_END) &&
        (Ccb->SecurityQos.ContextTrackingMode == SECURITY_DYNAMIC_TRACKING)) {

        //
        //  Allocate a client context record, and then initialize it
        //

        DataEntry->SecurityClientContext = FsRtlAllocatePool( NonPagedPoolMustSucceed,
                                                              sizeof(SECURITY_CLIENT_CONTEXT) );

        DebugTrace(0, Dbg, "Client End, Dynamic Tracking, ClientContext = %08lx\n", DataEntry->SecurityClientContext);

        if (!NT_SUCCESS(Status = SeCreateClientSecurity( UserThread,
                                                         &Ccb->SecurityQos,
                                                         FALSE,
                                                         DataEntry->SecurityClientContext ))) {

            DebugTrace(0, Dbg, "Not successful at creating client security, %08lx\n", Status);

            ExFreePool( DataEntry->SecurityClientContext );
            DataEntry->SecurityClientContext = NULL;
        }

    } else {

        DebugTrace(0, Dbg, "Static Tracking or Not Client End\n", 0);

        DataEntry->SecurityClientContext = NULL;
        Status = STATUS_SUCCESS;
    }

    DebugTrace(-1, Dbg, "NpSetDataEntryClientContext -> %08lx\n", Status);

    return Status;
}


VOID
NpCopyClientContext (
    IN PCCB Ccb,
    IN PDATA_ENTRY DataEntry
    )

/*++

Routine Description:

    This routine copies the client context stored in the data entry into
    the ccb, but only for dynamic tracking.

Arguments:

    Ccb - Supplies the ccb to update.

    DataEntry - Supplies the DataEntry to copy from.

Return Value:

--*/

{
    PAGED_CODE();

    DebugTrace(+1, Dbg, "NpCopyClientContext, Ccb = %08lx\n", Ccb);

    //
    //  Only do the copy if the data entries client context field is not null
    //  which means that we are doing dynamic tracking.  Note we will
    //  not be called with a server write data entry that has a non null
    //  client context.
    //

    if (DataEntry->SecurityClientContext != NULL) {

        DebugTrace(0, Dbg, "have something to copy %08lx\n", DataEntry->SecurityClientContext);

        //
        //  First check if we need to delete and deallocate the client
        //  context in the nonpaged ccb
        //

        if (Ccb->SecurityClientContext != NULL) {

            DebugTrace(0, Dbg, "Remove current client context %08lx\n", Ccb->SecurityClientContext);

            SeDeleteClientSecurity( Ccb->SecurityClientContext );

            ExFreePool( Ccb->SecurityClientContext );
        }

        //
        //  Now copy over the reference to the client context, and zero
        //  out the reference in the data entry.
        //

        Ccb->SecurityClientContext = DataEntry->SecurityClientContext;
        DataEntry->SecurityClientContext = NULL;
    }

    DebugTrace(-1, Dbg, "NpCopyClientContext -> VOID\n", 0 );

    return;
}


NTSTATUS
NpImpersonateClientContext (
    IN PCCB Ccb
    )

/*++

Routine Description:

    This routine impersonates the current client context stored in the
    ccb

Arguments:

    Ccb - Supplies the ccb for the named pipe

Return Value:

    NTSTATUS - returns our status code.

--*/

{
    NTSTATUS Status;

    PAGED_CODE();

    DebugTrace(+1, Dbg, "NpImpersonateClientContext, Ccb = %08lx\n", Ccb);

    if (Ccb->SecurityClientContext == NULL) {

        DebugTrace(0, Dbg, "Cannot impersonate\n", 0);

        Status = STATUS_CANNOT_IMPERSONATE;

    } else {

        SeImpersonateClient( Ccb->SecurityClientContext, NULL );

        Status = STATUS_SUCCESS;
    }

    DebugTrace(-1, Dbg, "NpImpersonateClientContext -> %08lx\n", Status);

    return Status;
}