polkit-authorization-constraint.c 33.1 KB
Newer Older
1
2
3
4
5
6
7
8
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
/***************************************************************************
 *
 * polkit-authorization-constraint.c : Conditions that must be
 * satisfied in order for an authorization to apply
 *
 * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
 *
9
10
11
12
13
14
15
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
16
 *
17
18
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
19
 *
20
21
22
23
24
25
26
27
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 *
 **************************************************************************/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <errno.h>
43
#include <limits.h>
44
45
46
47

#include "polkit-debug.h"
#include "polkit-authorization-constraint.h"
#include "polkit-utils.h"
48
#include "polkit-private.h"
49
#include "polkit-test.h"
50
#include "polkit-private.h"
51
 
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
 * SECTION:polkit-authorization-constraint
 * @title: Authorization Constraints
 * @short_description: Conditions that must be satisfied in
 * order for an authorization to apply
 *
 * This class is used to represent conditions that must be satisfied
 * in order for an authorization to apply
 *
 * Since: 0.7
 **/

/**
 * PolKitAuthorizationConstraint:
 *
 * Instances of this class are used to represent conditions that must
 * be satisfied in order for an authorization to apply.
 *
 * Since: 0.7
 **/
struct _PolKitAuthorizationConstraint
{
        int refcount;
75
        PolKitAuthorizationConstraintType type;
76
77
78
79
80
81
82
83

        union {
                struct {
                        char *path;
                } exe;
                struct {
                        char *context;
                } selinux_context;
Jim Li's avatar
Jim Li committed
84
        } data;
85
86
87
};

static PolKitAuthorizationConstraint _local_constraint = {-1, 
88
                                                          POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_LOCAL};
89
90

static PolKitAuthorizationConstraint _active_constraint = {-1, 
91
                                                          POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_ACTIVE};
92

93
94
static PolKitAuthorizationConstraint *
_polkit_authorization_constraint_new (void)
95
96
{
        PolKitAuthorizationConstraint *authc;
97
        authc = kit_new0 (PolKitAuthorizationConstraint, 1);
98
99
        if (authc == NULL)
                goto oom;
100
        authc->refcount = 1;
101
oom:
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
        return authc;
}

/**
 * polkit_authorization_constraint_ref:
 * @authc: the object
 * 
 * Increase reference count.
 * 
 * Returns: the object
 *
 * Since: 0.7
 **/
PolKitAuthorizationConstraint *
polkit_authorization_constraint_ref (PolKitAuthorizationConstraint *authc)
{
118
        kit_return_val_if_fail (authc != NULL, authc);
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
        if (authc->refcount == -1)
                return authc;
        authc->refcount++;
        return authc;
}

/**
 * polkit_authorization_constraint_unref:
 * @authc: the authorization_constraint object
 * 
 * Decreases the reference count of the object. If it becomes zero,
 * the object is freed. Before freeing, reference counts on embedded
 * objects are decresed by one.
 *
 * Since: 0.7
 **/
void
polkit_authorization_constraint_unref (PolKitAuthorizationConstraint *authc)
{
138
        kit_return_if_fail (authc != NULL);
139
140
141
142
143
144
        if (authc->refcount == -1)
                return;
        authc->refcount--;
        if (authc->refcount > 0) 
                return;

145
146
147
148
149
150
        switch (authc->type) {
        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_LOCAL:
        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_ACTIVE:
                break;

        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_EXE:
Jim Li's avatar
Jim Li committed
151
                kit_free (authc->data.exe.path);
152
153
154
                break;

        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_SELINUX_CONTEXT:
Jim Li's avatar
Jim Li committed
155
                kit_free (authc->data.selinux_context.context);
156
157
158
                break;
        }

159
        kit_free (authc);
160
161
162
163
164
165
166
167
168
169
170
171
172
}

/**
 * polkit_authorization_constraint_debug:
 * @authc: the object
 * 
 * Print debug details
 *
 * Since: 0.7
 **/
void
polkit_authorization_constraint_debug (PolKitAuthorizationConstraint *authc)
{
173
        kit_return_if_fail (authc != NULL);
174
        polkit_debug ("PolKitAuthorizationConstraint: refcount=%d type=%d", authc->refcount, authc->type);
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
}

/**
 * polkit_authorization_constraint_validate:
 * @authc: the object
 * 
 * Validate the object
 * 
 * Returns: #TRUE iff the object is valid.
 *
 * Since: 0.7
 **/
polkit_bool_t
polkit_authorization_constraint_validate (PolKitAuthorizationConstraint *authc)
{
190
        kit_return_val_if_fail (authc != NULL, FALSE);
191
192
193
194
195
196
197
198
199
200

        return TRUE;
}

/**
 * polkit_authorization_constraint_check_session:
 * @authc: the object
 * @session: the session
 *
 * Determine if the given session satisfies the conditions imposed by
201
 * the given constraint.
202
203
204
205
206
207
208
209
210
211
212
213
214
215
 *
 * Returns: #TRUE if, and only if, the given session satisfies the
 * conditions imposed by the given constraint.
 *
 * Since: 0.7
 */
polkit_bool_t
polkit_authorization_constraint_check_session (PolKitAuthorizationConstraint *authc,
                                               PolKitSession                 *session)
{
        polkit_bool_t ret;
        polkit_bool_t is_active;
        polkit_bool_t is_local;

216
217
        kit_return_val_if_fail (authc != NULL, FALSE);
        kit_return_val_if_fail (session != NULL, FALSE);
218
219
220

        ret = FALSE;

221
222
        polkit_session_get_ck_is_local (session, &is_local);
        polkit_session_get_ck_is_active (session, &is_active);
223

224
        if (authc->type == POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_LOCAL)  {
225
226
227
228
                if (!is_local)
                        goto out;
        }

229
        if (authc->type == POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_ACTIVE)  {
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
                if (!is_active)
                        goto out;
        }

        ret = TRUE;
out:
        return ret;
}

/**
 * polkit_authorization_constraint_check_caller:
 * @authc: the object
 * @caller: the caller
 *
 * Determine if the given caller satisfies the conditions imposed by
 * the given constraint
 *
 * Returns: #TRUE if, and only if, the given caller satisfies the
 * conditions imposed by the given constraint.
 *
 * Since: 0.7
 */
polkit_bool_t 
polkit_authorization_constraint_check_caller (PolKitAuthorizationConstraint *authc,
                                              PolKitCaller                  *caller)
{
256
257
258
259
        int n;
        pid_t pid;
        char *selinux_context;
        char buf[PATH_MAX];
260
261
262
        polkit_bool_t ret;
        PolKitSession *session;

263
264
        kit_return_val_if_fail (authc != NULL, FALSE);
        kit_return_val_if_fail (caller != NULL, FALSE);
265
266
267
268

        ret = FALSE;

        /* caller may not be in a session */
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289

        switch (authc->type) {
        /* explicit fallthrough */
        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_LOCAL:
        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_ACTIVE:
                if (polkit_caller_get_ck_session (caller, &session) && session != NULL) {
                        ret = polkit_authorization_constraint_check_session (authc, session);
                }
                break;

        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_EXE:
                if (polkit_caller_get_pid (caller, &pid)) {

                        /* we may be running unprivileged.. so optionally use the helper. Requires the calling
                         * process (this one) to have the org.freedesktop.policykit.read authorization.
                         *
                         * An example of this is HAL (running as user 'haldaemon').
                         */
                        n = polkit_sysdeps_get_exe_for_pid_with_helper (pid, buf, sizeof (buf));

                        if (n != -1 && n < (int) sizeof (buf)) {
Jim Li's avatar
Jim Li committed
290
                                if (strcmp (authc->data.exe.path, buf) == 0) {
291
292
293
294
295
296
297
298
299
                                        ret = TRUE;
                                }
                        }
                }

                break;

        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_SELINUX_CONTEXT:
                if (polkit_caller_get_selinux_context (caller, &selinux_context) && selinux_context != NULL) {
Jim Li's avatar
Jim Li committed
300
                        if (strcmp (authc->data.selinux_context.context, selinux_context) == 0) {
301
302
303
304
305
306
307
                                ret = TRUE;
                        }
                } else {
                        /* if SELinux context is not set then SELinux is not enabled (or the
                         * caller made a mistake and didn't set it); thus, the authorization can
                         * never apply 
                         */
308
309
                        ret = TRUE;
                }
310
                break;
311
312
313
314
315
316
        }

        return ret;
}

/**
317
 * polkit_authorization_constraint_type:
318
319
320
321
322
323
 * @authc: the object
 *
 * Describe the constraint; this is only useful when inspecting an
 * authorization to present information to the user (e.g. as
 * polkit-auth(1) does).
 *
324
 * Returns: type from #PolKitAuthorizationConstraintType
325
326
327
 *
 * Since: 0.7
 */
328
329
PolKitAuthorizationConstraintType
polkit_authorization_constraint_type (PolKitAuthorizationConstraint *authc)
330
{
331
        kit_return_val_if_fail (authc != NULL, FALSE);
332
        return authc->type;
333
334
}

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/**
 * polkit_authorization_constraint_get_exe:
 * @authc: the object
 *
 * Get the exe path for the constraint.
 *
 * Returns: The exe path or #NULL if type isn't
 * #POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_EXE. Caller shall not
 * free this string.
 * 
 * Since: 0.8
 */
const char *
polkit_authorization_constraint_get_exe (PolKitAuthorizationConstraint *authc)
{
        kit_return_val_if_fail (authc != NULL, NULL);
        kit_return_val_if_fail (authc->type == POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_EXE, NULL);

Jim Li's avatar
Jim Li committed
353
        return authc->data.exe.path;
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
}

/**
 * polkit_authorization_constraint_get_selinux_context:
 * @authc: the object
 *
 * Get the SELinux context for the constraint.
 *
 * Returns: The selinux context or #NULL if type isn't
 * #POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_SELINUX_CONTEXT. Caller
 * shall not free this string.
 * 
 * Since: 0.8
 */
const char *
polkit_authorization_constraint_get_selinux_context (PolKitAuthorizationConstraint *authc)
{
        kit_return_val_if_fail (authc != NULL, NULL);
        kit_return_val_if_fail (authc->type == POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_SELINUX_CONTEXT, NULL);

Jim Li's avatar
Jim Li committed
374
        return authc->data.selinux_context.context;
375
376
}

377
378
379
380
381
382
/**
 * polkit_authorization_constraint_get_require_local:
 *
 * Get a #PolKitAuthorizationConstraint object that represents the
 * constraint that the session or caller must be local.
 *
383
 * Returns: the constraint
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
 *
 * Since: 0.7
 */
PolKitAuthorizationConstraint *
polkit_authorization_constraint_get_require_local (void)
{
        return &_local_constraint;
}

/**
 * polkit_authorization_constraint_get_require_active:
 *
 * Get a #PolKitAuthorizationConstraint object that represents the
 * constraint that the session or caller must be active.
 *
399
 * Returns: the constraint
400
401
402
403
404
405
406
407
408
 *
 * Since: 0.7
 */
PolKitAuthorizationConstraint *
polkit_authorization_constraint_get_require_active (void)
{
        return &_active_constraint;
}

409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
/**
 * polkit_authorization_constraint_get_require_exe:
 * @path: path to program
 *
 * Get a #PolKitAuthorizationConstraint object that represents the
 * constraint that the caller must be a specific program
 *
 * Returns: the constraint or #NULL on OOM
 *
 * Since: 0.8
 */
PolKitAuthorizationConstraint *
polkit_authorization_constraint_get_require_exe (const char *path)
{
        PolKitAuthorizationConstraint *authc;

        kit_return_val_if_fail (path != NULL, NULL);

        authc = _polkit_authorization_constraint_new ();
        if (authc == NULL)
                goto out;
        authc->type = POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_EXE;
Jim Li's avatar
Jim Li committed
431
432
        authc->data.exe.path = kit_strdup (path);
        if (authc->data.exe.path == NULL) {
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
                polkit_authorization_constraint_unref (authc);
                authc = NULL;
        }

out:
        return authc;
}

/**
 * polkit_authorization_constraint_get_require_selinux_context:
 * @context: SELinux context
 *
 * Get a #PolKitAuthorizationConstraint object that represents the
 * constraint that the caller must be in a specific SELinux context.
 *
 * Returns: the constraint or #NULL on OOM
 *
 * Since: 0.8
 */
PolKitAuthorizationConstraint *
polkit_authorization_constraint_get_require_selinux_context (const char *context)
{
        PolKitAuthorizationConstraint *authc;

        kit_return_val_if_fail (context != NULL, NULL);

        authc = _polkit_authorization_constraint_new ();
        if (authc == NULL)
                goto out;
        authc->type = POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_SELINUX_CONTEXT;
Jim Li's avatar
Jim Li committed
463
464
        authc->data.selinux_context.context = kit_strdup (context);
        if (authc->data.selinux_context.context == NULL) {
465
466
467
468
469
470
471
472
                polkit_authorization_constraint_unref (authc);
                authc = NULL;
        }

out:
        return authc;
}

473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
/**
 * polkit_authorization_constraint_to_string:
 * @authc: the object
 * @out_buf: buffer to store the string representation in
 * @buf_size: size of buffer
 *
 * Get a textual representation of the constraint; this is only useful
 * for serializing; it's a machine, not human, readable string.
 *
 * Returns: Number of characters written (not including trailing
 * '\0'). If the output was truncated due to the buffer being too
 * small, buf_size will be returned. Thus, a return value of buf_size
 * or more indicates that the output was truncated (see snprintf(3))
 * or an error occured.
 *
 * Since: 0.7
 */
size_t
polkit_authorization_constraint_to_string (PolKitAuthorizationConstraint *authc, char *out_buf, size_t buf_size)
{
493
        kit_return_val_if_fail (authc != NULL, buf_size);
494

495
496
        switch (authc->type) {
        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_LOCAL:
497
498
                return snprintf (out_buf, buf_size, "local");

499
        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_ACTIVE:
500
                return snprintf (out_buf, buf_size, "active");
501
502

        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_EXE:
Jim Li's avatar
Jim Li committed
503
                return snprintf (out_buf, buf_size, "exe:%s", authc->data.exe.path);
504
505
                
        case POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_SELINUX_CONTEXT:
Jim Li's avatar
Jim Li committed
506
                return snprintf (out_buf, buf_size, "selinux_context:%s", authc->data.selinux_context.context);
507
        }
508
509

        return 0;
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
}

/**
 * polkit_authorization_constraint_from_string:
 * @str: textual representation of constraint
 *
 * Construct a constraint from a textual representation as returned by
 * polkit_authorization_constraint_to_string().
 *
 * Returns: the constraint or #NULL if the string coulnd't be parsed.
 */
PolKitAuthorizationConstraint *
polkit_authorization_constraint_from_string (const char *str)
{
        PolKitAuthorizationConstraint *ret;

526
        kit_return_val_if_fail (str != NULL, NULL);
527
528
529

        ret = NULL;

530
        if (strcmp (str, "local") == 0) {
531
532
533
534
535
                ret = polkit_authorization_constraint_get_require_local ();
                goto out;
        } else if (strcmp (str, "active") == 0) {
                ret = polkit_authorization_constraint_get_require_active ();
                goto out;
536
        } else if (strncmp (str, "exe:", 4) == 0 && strlen (str) > 4) {
537
538
                ret = polkit_authorization_constraint_get_require_exe (str + 4);
                goto out;
539
        } else if (strncmp (str, "selinux_context:", 16) == 0 && strlen (str) > 16) {
540
541
                ret = polkit_authorization_constraint_get_require_selinux_context (str + 16);
                goto out;
542
543
544
545
546
547
548
549
550
        }

out:
        return ret;
}

/**
 * polkit_authorization_constraint_get_from_caller:
 * @caller: caller
551
552
 * @out_array: return location for constraints
 * @array_size: size of the passed array
553
 *
554
555
556
 * Given a caller, return the set of most restrictive constraints
 * possible. For example, if the caller is local and active, a set
 * constraints requiring this will be returned.
557
558
 *
 * This function is typically used when the caller obtains an
559
 * authorization through authentication; the goal is to put
560
561
562
 * constraints on the authorization such that it's only valid when the
 * caller is in the context as where she obtained it.
 *
563
564
565
 * The caller must unref all the created objects using
 * polkit_authorization_constraint_unref().
 *
566
567
568
569
570
571
572
573
574
 * Returns: If OOM -1 is returned. This function do not create more
 * than @array_size constraints (including the trailing %NULL). If the
 * output was truncated due to this limit then the return value is the
 * number of objects (not including the trailing %NULL) which would
 * have been written to the final array if enough space had been
 * available. Thus, a return value of @array_size or more means that
 * the output was truncated.
 *
 * Since: 0.7
575
 */
576
int
577
578
579
polkit_authorization_constraint_get_from_caller (PolKitCaller *caller, 
                                                 PolKitAuthorizationConstraint **out_array, 
                                                 size_t array_size)
580
{
581
582
583
        pid_t pid;
        char *selinux_context;
        int ret;
584
585
586
        polkit_bool_t is_local;
        polkit_bool_t is_active;
        PolKitSession *session;
587
588
        char path[PATH_MAX];
        int n;
589

590
591
592
593
594
        kit_return_val_if_fail (caller != NULL, 0);
        kit_return_val_if_fail (out_array != NULL, 0);

        ret = 0;

595
        if (!polkit_caller_get_ck_session (caller, &session) || session == NULL) {
596
597
                goto out;
        }
598
        
599
600
        polkit_session_get_ck_is_local (session, &is_local);
        polkit_session_get_ck_is_active (session, &is_active);
601
602

        if (is_local) {
603
                if (ret < (int) array_size)
604
605
606
607
608
                        out_array[ret] = polkit_authorization_constraint_get_require_local ();
                ret++;
        } 

        if (is_active) {
609
                if (ret < (int) array_size)
610
611
                        out_array[ret] = polkit_authorization_constraint_get_require_active ();
                ret++;
612
613
        }

614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
        /* constrain to callers program */
        if (polkit_caller_get_pid (caller, &pid)) {
                /* So the program to receive a constraint may besetuid root... so we may need some
                 * help to get the exepath.. Therefore use _with_helper().
                 *
                 * This works because this function is normally only called from polkit-grant-helper which
                 * is setgid polkituser.. this means that _with_helper will succeed.
                 *
                 * An example of this is pulseaudio...
                 */
                n = polkit_sysdeps_get_exe_for_pid_with_helper (pid, path, sizeof (path));
                if (n != -1 && n < (int) sizeof (path)) {
                        PolKitAuthorizationConstraint *c;

                        c = polkit_authorization_constraint_get_require_exe (path);
                        if (c == NULL)
                                goto oom;

                        if (ret < (int) array_size)
                                out_array[ret] = c;

                        ret++;
                }
        }

        /* constrain to callers SELinux context */
        if (polkit_caller_get_selinux_context (caller, &selinux_context) && selinux_context != NULL) {
                PolKitAuthorizationConstraint *c;

                c = polkit_authorization_constraint_get_require_selinux_context (selinux_context);
                if (c == NULL)
                        goto oom;

                if (ret < (int) array_size)
                        out_array[ret] = c;
                
                ret++;
        }

653
out:
654
        if (ret < (int) array_size)
655
656
                out_array[ret] = NULL;

657
        return ret;
658
659
660
661
662
663

oom:
        for (n = 0; n < ret; n++) {
                polkit_authorization_constraint_unref (out_array[n]);
        }
        return -1;
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
}

/**
 * polkit_authorization_constraint_equal:
 * @a: first constraint
 * @b: first constraint
 *
 * Determines if two constraints are equal
 *
 * Returns: #TRUE only if the given constraints are equal
 *
 * Since: 0.7
 */
polkit_bool_t
polkit_authorization_constraint_equal (PolKitAuthorizationConstraint *a, PolKitAuthorizationConstraint *b)
{
680
681
        polkit_bool_t ret;

682
683
        kit_return_val_if_fail (a != NULL, FALSE);
        kit_return_val_if_fail (b != NULL, FALSE);
684

685
686
687
688
689
690
        ret = FALSE;

        if (a->type != b->type)
                goto out;

        if (a->type == POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_EXE) {
Jim Li's avatar
Jim Li committed
691
                if (strcmp (a->data.exe.path, b->data.exe.path) != 0)
692
693
                        goto out;
        } else if (a->type == POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_SELINUX_CONTEXT) {
Jim Li's avatar
Jim Li committed
694
                if (strcmp (a->data.selinux_context.context, b->data.selinux_context.context) != 0)
695
696
697
698
699
700
701
                        goto out;
        }

        ret = TRUE;

out:
        return ret;
702
}
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719

#ifdef POLKIT_BUILD_TESTS

static polkit_bool_t
_tst1 (PolKitSession *s, PolKitAuthorizationConstraint *ac, polkit_bool_t *out_result)
{
        polkit_bool_t oom;
        PolKitCaller *c;

        oom = TRUE;

        if (s == NULL)
                goto out;

        *out_result = polkit_authorization_constraint_check_session (ac, s);

        if ((c = polkit_caller_new ()) != NULL) {
720
721
                /* we know that the ac's passed always will be REQUIRE_ACTIVE or REQUIRE_LOCAL */
                kit_assert (polkit_authorization_constraint_check_caller (ac, c) == FALSE);
722

723
724
                kit_assert (polkit_caller_set_ck_session (c, s));
                kit_assert (*out_result == polkit_authorization_constraint_check_caller (ac, c));
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
                polkit_caller_unref (c);
        }

        oom = FALSE;

out:
        return oom;
}

static void
_tst2 (PolKitAuthorizationConstraint *ac)
{
        char buf[256];
        PolKitAuthorizationConstraint *ac2;

        /* not enough space */
741
        kit_assert (polkit_authorization_constraint_to_string (ac, buf, 2) >= 2);
742

743
        kit_assert (polkit_authorization_constraint_to_string (ac, buf, sizeof (buf)) < sizeof (buf));
744
        if ((ac2 = polkit_authorization_constraint_from_string (buf)) != NULL) {
745
                kit_assert (polkit_authorization_constraint_equal (ac, ac2) == TRUE);
746
747
748
749
                polkit_authorization_constraint_unref (ac2);
        }
}

750
#if 0
751
752
753
754
755
756
757
758
759
760
761
762
763
764
static polkit_bool_t
_tst3 (PolKitSession *s, PolKitAuthorizationConstraint *compare_to, polkit_bool_t *ret)
{
        PolKitAuthorizationConstraint *ac;
        polkit_bool_t is_oom;
        PolKitCaller *c;

        is_oom = TRUE;

        if (s == NULL)
                goto out;

        if ((c = polkit_caller_new ()) != NULL) {
                ac = polkit_authorization_constraint_get_from_caller (c);
765
                kit_assert (polkit_authorization_constraint_equal (ac, polkit_authorization_constraint_get_null ()));
766
767


768
                kit_assert (polkit_caller_set_ck_session (c, s));
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783

                ac = polkit_authorization_constraint_get_from_caller (c);

                *ret = polkit_authorization_constraint_equal (ac, compare_to);

                polkit_caller_unref (c);
                polkit_authorization_constraint_unref (ac);

                is_oom = FALSE;
        }


out:
        return is_oom;
}
784
#endif
785
786
787
788
789

static polkit_bool_t
_run_test (void)
{
        PolKitAuthorizationConstraint *ac;
790
        PolKitAuthorizationConstraint *ac2;
791
        PolKitAuthorizationConstraintType type;
792
793
794
795
796
        PolKitSession *s_active;
        PolKitSession *s_inactive;
        PolKitSession *s_active_remote;
        PolKitSession *s_inactive_remote;
        polkit_bool_t ret;
797
        char buf[256];
798
799
800
801
802
803

        if ((s_active = polkit_session_new ()) != NULL) {
                if (!polkit_session_set_ck_objref (s_active, "/session1")) {
                        polkit_session_unref (s_active);
                        s_active = NULL;
                } else {
804
805
                        kit_assert (polkit_session_set_ck_is_local (s_active, TRUE));
                        kit_assert (polkit_session_set_ck_is_active (s_active, TRUE));
806
807
808
809
810
811
812
813
                }
        }

        if ((s_inactive = polkit_session_new ()) != NULL) {
                if (!polkit_session_set_ck_objref (s_inactive, "/session2")) {
                        polkit_session_unref (s_inactive);
                        s_inactive = NULL;
                } else {
814
815
                        kit_assert (polkit_session_set_ck_is_local (s_inactive, TRUE));
                        kit_assert (polkit_session_set_ck_is_active (s_inactive, FALSE));
816
817
818
819
820
821
822
823
824
                }
        }

        if ((s_active_remote = polkit_session_new ()) != NULL) {
                if (!polkit_session_set_ck_objref (s_active_remote, "/session3") ||
                    !polkit_session_set_ck_remote_host (s_active_remote, "remotehost.com")) {
                        polkit_session_unref (s_active_remote);
                        s_active_remote = NULL;
                } else {
825
826
                        kit_assert (polkit_session_set_ck_is_local (s_active_remote, FALSE));
                        kit_assert (polkit_session_set_ck_is_active (s_active_remote, TRUE));
827
828
829
830
831
832
833
834
835
                }
        }

        if ((s_inactive_remote = polkit_session_new ()) != NULL) {
                if (!polkit_session_set_ck_objref (s_inactive_remote, "/session4") ||
                    !polkit_session_set_ck_remote_host (s_inactive_remote, "remotehost.com")) {
                        polkit_session_unref (s_inactive_remote);
                        s_inactive_remote = NULL;
                } else {
836
837
                        kit_assert (polkit_session_set_ck_is_local (s_inactive_remote, FALSE));
                        kit_assert (polkit_session_set_ck_is_active (s_inactive_remote, FALSE));
838
839
840
841
                }
        }

        /* local constraint */
842
        kit_assert ((ac = polkit_authorization_constraint_get_require_local ()) != NULL);
843
844
        type = polkit_authorization_constraint_type (ac);
        kit_assert (type == POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_LOCAL);
845
846
847
848
        kit_assert (_tst1 (s_active, ac, &ret) || ret == TRUE);
        kit_assert (_tst1 (s_inactive, ac, &ret) || ret == TRUE);
        kit_assert (_tst1 (s_active_remote, ac, &ret) || ret == FALSE);
        kit_assert (_tst1 (s_inactive_remote, ac, &ret) || ret == FALSE);
849
850
851
        _tst2 (ac);

        /* active constraint */
852
        kit_assert ((ac = polkit_authorization_constraint_get_require_active ()) != NULL);
853
854
        type = polkit_authorization_constraint_type (ac);
        kit_assert (type == POLKIT_AUTHORIZATION_CONSTRAINT_TYPE_REQUIRE_ACTIVE);
855
856
857
858
        kit_assert (_tst1 (s_active, ac, &ret) || ret == TRUE);
        kit_assert (_tst1 (s_inactive, ac, &ret) || ret == FALSE);
        kit_assert (_tst1 (s_active_remote, ac, &ret) || ret == TRUE);
        kit_assert (_tst1 (s_inactive_remote, ac, &ret) || ret == FALSE);
859
860
861
        _tst2 (ac);


862
#if 0
863
864
865
        /* TODO: redo these tests; they are supposed to to verify that 
         *       polkit_authorization_constraint_get_from_caller() works()
         */
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
        for (n = 0; n < 4; n++) {
                PolKitSession *s;
                polkit_bool_t expected[4];

                switch (n) {
                case 0:
                        s = s_active;
                        expected[0] = TRUE;
                        expected[1] = FALSE;
                        expected[2] = FALSE;
                        expected[3] = FALSE;
                        break;
                case 1:
                        s = s_inactive;
                        expected[0] = FALSE;
                        expected[1] = TRUE;
                        expected[2] = FALSE;
                        expected[3] = FALSE;
                        break;
                case 2:
                        s = s_active_remote;
                        expected[0] = FALSE;
                        expected[1] = FALSE;
                        expected[2] = TRUE;
                        expected[3] = FALSE;
                        break;
                case 3:
                        s = s_inactive_remote;
                        expected[0] = FALSE;
                        expected[1] = FALSE;
                        expected[2] = FALSE;
                        expected[3] = TRUE;
                        break;
                }

901
902
903
904
                kit_assert (_tst3 (s, polkit_authorization_constraint_get_require_local_active (), &ret) || ret == expected[0]);
                kit_assert (_tst3 (s, polkit_authorization_constraint_get_require_local (), &ret) || ret == expected[1]);
                kit_assert (_tst3 (s, polkit_authorization_constraint_get_require_active (), &ret) || ret == expected[2]);
                kit_assert (_tst3 (s, polkit_authorization_constraint_get_null (), &ret) || ret == expected[3]);
905
        }
906
#endif
907

908
        if ((ac = _polkit_authorization_constraint_new ()) != NULL) {
909
910
911
912
913
914
                polkit_authorization_constraint_validate (ac);
                polkit_authorization_constraint_debug (ac);
                polkit_authorization_constraint_ref (ac);
                polkit_authorization_constraint_unref (ac);
                polkit_authorization_constraint_unref (ac);
        }
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976

        char our_exe[256];
        int n;
        n = polkit_sysdeps_get_exe_for_pid (getpid (), our_exe, sizeof (our_exe));
        kit_assert (n != -1);
        kit_assert (n < (int) sizeof (our_exe));

        if ((ac = polkit_authorization_constraint_get_require_exe (our_exe)) != NULL) {
                const char *s;
                PolKitCaller *c;

                kit_assert ((s = polkit_authorization_constraint_get_exe (ac)) != NULL && strcmp (s, our_exe) == 0);
                kit_assert (polkit_authorization_constraint_to_string (ac, buf, sizeof (buf)) < sizeof (buf));
                if ((ac2 = polkit_authorization_constraint_from_string (buf)) != NULL) {
                        kit_assert (polkit_authorization_constraint_equal (ac, ac2));
                        polkit_authorization_constraint_unref (ac2);
                }

                if ((c = polkit_caller_new ()) != NULL) {
                        kit_assert (polkit_caller_set_pid (c, getpid ()));
                        kit_assert (polkit_authorization_constraint_check_caller (ac, c));
                        kit_assert (polkit_caller_set_pid (c, getppid ()));
                        kit_assert (! polkit_authorization_constraint_check_caller (ac, c));
                        polkit_caller_unref (c);
                }
                

                polkit_authorization_constraint_unref (ac);
        }

        if ((ac = polkit_authorization_constraint_get_require_selinux_context ("httpd_exec_t")) != NULL) {
                const char *s;
                PolKitCaller *c;

                kit_assert ((s = polkit_authorization_constraint_get_selinux_context (ac)) != NULL && 
                            strcmp (s, "httpd_exec_t") == 0);
                kit_assert (polkit_authorization_constraint_to_string (ac, buf, sizeof (buf)) < sizeof (buf));
                if ((ac2 = polkit_authorization_constraint_from_string (buf)) != NULL) {
                        kit_assert (polkit_authorization_constraint_equal (ac, ac2));
                        polkit_authorization_constraint_unref (ac2);
                }

                if ((c = polkit_caller_new ()) != NULL) {
                        kit_assert (polkit_caller_set_pid (c, getpid ()));

                        if (polkit_caller_set_selinux_context (c, "httpd_exec_t")) {
                                kit_assert (polkit_authorization_constraint_check_caller (ac, c));
                        } else {
                                kit_assert (errno == ENOMEM);
                        }

                        if (polkit_caller_set_selinux_context (c, "hald_exec_t")) {
                                kit_assert (! polkit_authorization_constraint_check_caller (ac, c));
                        } else {
                                kit_assert (errno == ENOMEM);
                        }

                        polkit_caller_unref (c);
                }

                polkit_authorization_constraint_unref (ac);
        }
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
        
        if (s_active != NULL)
                polkit_session_unref (s_active);

        if (s_inactive != NULL)
                polkit_session_unref (s_inactive);

        if (s_active_remote != NULL)
                polkit_session_unref (s_active_remote);

        if (s_inactive_remote != NULL)
                polkit_session_unref (s_inactive_remote);

        return TRUE;
}


994
KitTest _test_authorization_constraint = {
995
996
997
998
999
1000
1001
        "polkit_authorization_constraint",
        NULL,
        NULL,
        _run_test
};

#endif /* POLKIT_BUILD_TESTS */