~ubuntu-core-dev/apparmor/master

« back to all changes in this revision

Viewing changes to utils/aa-mergeprof

  • Committer: Jamie Strandboge
  • Date: 2016-01-05 19:14:44 UTC
  • Revision ID: jamie@ubuntu.com-20160105191444-4cxbegq4ru62ri2n
Tags: 2.10-0ubuntu10
* debian/patches/lp1529074.patch: for systems using networkd, add read on
  /run/systemd/resolve/resolv.conf (LP: #1529074)
* No change rebuild for perl 5.22
* debian/patches/fix-abstraction-for-python3.5.patch: adjust python
  abstraction for python 3.5
* debian/apparmor.init,apparmor.upstart: clear only the system cache if
  apparmor version has changed on snappy flavors since snappy will handle
  the app's cache itself
* debian/lib/apparmor/functions:
  - compile /var/lib/snappy/apparmor/profiles policy
  - add compare_previous_version()
  - refactor clear_cache()
  - compare_and_save_debsums() checks if $PROFILES_VAR exists
* debian/libapparmor-dev.manpages: add 5 missing libapparmor manpages
  (LP: #1491147, LP: #1384431)
* Rebuild against python3.5.
* debian/patches/parser-fix-cache-file-mtime-regression.patch: Fix a bug
  that resulted in the mtime of generate policy cache files to be set
  incorrectly. The mtime of cache files should be the newest mtime detected
  on the profile and abstraction files used to generate the policy cache
  file. However, the bug caused the mtime of the policy cache file to either
  not be updated or to be updated to an incorrect time. (LP: #1484178)
* debian/patches/parser-verify-cache-file-mtime.patch: Add tests to verify
  that the policy cache file's mtime is being set correctly and that cache
  handling is correct when the profile or abstraction files are newer than
  the policy cache file.
* debian/patches/parser-run-caching-tests-without-apparmorfs.patch,
  debian/patches/parser-do-cleanup-when-test-was-skipped.patch: Enable the
  caching tests to run on the buildds even though apparmorfs isn't mounted.
* debian/patches/aa-status-dont_require_python3-apparmor.patch:
  make aa-status(8) work even when python3-apparmor is not installed,
  otherwise dh_apparmor postinst snippets can fail (LP: #1480492)
* debian/control: make apparmor-utils depend on the same package
  version of python3-apparmor
* Update to apparmor 2.10
  - libapparmor added functions to ease loading profile cache files to
    help support systemd on-demand load of policy (LP: #1385414)
  - apparmor parser: fixed policy generation to allow matching
    embedded NULs in abstract unix socket names (LP: #1413410)
  - aa-status: don't traceback when not permitted to read current
    set of apparmor policy (LP: #1466768)
  - aa-logprof: don't crash on policies that have an #include of a
    directory (LP: #1471425)
  - aa-logprof: fix crash when network rejections occur when file
    operations are performed on network sockets (LP: #1466812)
* dropped reproducible-pdf.patch, incorporated upstream
* debian/patches/tests-fix_sysctl_test.patch: fix sysctl test failure
  with 4.1 kernel and newer.
* debian/control: add alternate dependency on linux-initramfs-tool
  (LP: #1109029)
* debian/libapparmor1.symbols: update symbols file for added symbols
  in libapparmor
* No-change rebuild for python3.5 transition
* Update to apparmor 2.9.2
  - Fix minitools to work with multiple profiles at once (LP: #1378095)
  - Parse mounts that have non-ascii UTF-8 chars (LP: #1310598)
  - Update dovecot profiles (LP: #1296667)
  - Allow ubuntu-helpers to build texlive fonts (LP: #1010909)
* dropped patches incorporated upstream:
  add-mir-abstraction-lp1422521.patch, systemd-dev-log-lp1413232.patch
  parser-fix_modifier_compilation_+_tests.patch,
  tests-fix_systemd_breakage_in_pivot_root-lp1436109.patch,
  GDM_X_authority-lp1432126.patch, and
  debian/patches/easyprof-framework-policy.patch
* Partial merge with debian apparmor package:
  - debian/rules: enable the bindnow hardening flag during build.
  - debian/upstream/signing-key.asc: add new upstream public
    signing key
  - debian/watch: fix watch file, add gpg signature checking
  - install libapparmor.so dev symlink under /usr not /lib
  - debian/patches/reproducible-pdf.patch: make techdoc.pdf
    reproducible even in face of timezone variations.
  - debian/control: sync fields
  - debian/debhelper/postrm-apparmor: remove
    /etc/apparmor.d/{disable,} on package purge
  - debian/libapache2-mod-apparmor.postrm: on package purge, delete
    /etc/apparmor.d/{,disable} if empty
  - debian/libapparmor1.symbols: Use Build-Depends-Package in the
    symbols file.
  - debian/copyright: sync
* Make debian/lib/apparmor/profile-load executable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
import os
18
18
 
19
19
import apparmor.aa
 
20
from apparmor.aa import available_buttons, combine_name, delete_duplicates, is_known_rule, match_includes
20
21
import apparmor.aamode
 
22
from apparmor.common import AppArmorException
 
23
from apparmor.regex import re_match_include
21
24
import apparmor.severity
22
25
import apparmor.cleanprofile as cleanprofile
23
26
import apparmor.ui as aaui
24
27
 
 
28
# setup exception handling
 
29
from apparmor.fail import enable_aa_exception_handler
 
30
enable_aa_exception_handler()
 
31
 
25
32
# setup module translations
26
33
from apparmor.translations import init_translation
27
34
_ = init_translation()
43
50
if profiledir:
44
51
    apparmor.aa.profile_dir = apparmor.aa.get_full_path(profiledir)
45
52
    if not os.path.isdir(apparmor.aa.profile_dir):
46
 
        raise apparmor.AppArmorException(_("%s is not a directory.") %profiledir)
 
53
        raise AppArmorException(_("%s is not a directory.") %profiledir)
47
54
 
48
55
def reset_aa():
49
56
    apparmor.aa.aa = apparmor.aa.hasher()
229
236
                            return o
230
237
                            pass#self.user.aa[profile][hat][allow][path][mode] = (old_mode | new_mode) - (new_mode & conflict_x)
231
238
                        else:
232
 
                            raise apparmor.aa.AppArmorException(_('Unknown selection'))
 
239
                            raise AppArmorException(_('Unknown selection'))
233
240
                        done = True
234
241
 
235
242
    def ask_the_questions(self, other, profile):
 
243
        aa = self.user.aa  # keep references so that the code in this function can use the short name
 
244
        changed = apparmor.aa.changed  # (and be more in sync with aa.py ask_the_questions())
 
245
 
236
246
        if other == 'other':
237
247
            other = self.other
238
248
        else:
262
272
                done = True
263
273
            elif ans == 'CMD_ALLOW':
264
274
                selection = options[selected]
265
 
                inc = apparmor.aa.re_match_include(selection)
 
275
                inc = re_match_include(selection)
266
276
                self.user.filelist[self.user.filename]['include'][inc] = True
267
277
                options.pop(selected)
268
278
                aaui.UI_Info(_('Adding %s to the file.') % selection)
279
289
 
280
290
            options = []
281
291
            for inc in other.aa[profile][hat]['include'].keys():
282
 
                if not inc in self.user.aa[profile][hat]['include'].keys():
 
292
                if not inc in aa[profile][hat]['include'].keys():
283
293
                    options.append('#include <%s>' %inc)
284
294
 
285
295
            default_option = 1
297
307
                    done = True
298
308
                elif ans == 'CMD_ALLOW':
299
309
                    selection = options[selected]
300
 
                    inc = apparmor.aa.re_match_include(selection)
301
 
                    deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc)
302
 
                    self.user.aa[profile][hat]['include'][inc] = True
 
310
                    inc = re_match_include(selection)
 
311
                    deleted = apparmor.aa.delete_duplicates(aa[profile][hat], inc)
 
312
                    aa[profile][hat]['include'][inc] = True
303
313
                    options.pop(selected)
304
314
                    aaui.UI_Info(_('Adding %s to the file.') % selection)
305
315
                    if deleted:
307
317
                elif ans == 'CMD_FINISHED':
308
318
                    return
309
319
 
310
 
            #Add the capabilities
311
 
            for allow in ['allow', 'deny']:
312
 
                if other.aa[profile][hat].get(allow, False):
313
 
                    continue
314
 
                for capability in sorted(other.aa[profile][hat][allow]['capability'].keys()):
315
 
                    severity = sev_db.rank('CAP_%s' % capability)
316
 
                    default_option = 1
317
 
                    options = []
318
 
                    newincludes = apparmor.aa.match_cap_includes(self.user.aa[profile][hat], capability)
319
 
                    q = aaui.PromptQuestion()
320
 
                    if newincludes:
321
 
                        options += list(map(lambda inc: '#include <%s>' %inc, sorted(set(newincludes))))
322
 
 
323
 
                    if options:
324
 
                        options.append('capability %s' % capability)
325
 
                        q.options = options
326
 
                        q.selected = default_option - 1
327
 
 
328
 
                    q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat)]
329
 
                    q.headers += [_('Capability'), capability]
330
 
                    q.headers += [_('Severity'), severity]
331
 
 
332
 
                    audit_toggle = 0
333
 
 
334
 
                    q.functions = ['CMD_ALLOW', 'CMD_DENY', 'CMD_IGNORE_ENTRY', 'CMD_ABORT', 'CMD_FINISHED']
335
 
 
336
 
                    q.default = 'CMD_ALLOW'
337
 
 
338
 
                    done = False
339
 
                    while not done:
340
 
                        ans, selected = q.promptUser()
341
 
                        # Ignore the log entry
342
 
                        if ans == 'CMD_IGNORE_ENTRY':
343
 
                            done = True
344
 
                            break
345
 
 
346
 
                        elif ans == 'CMD_FINISHED':
347
 
                            return
348
 
 
349
 
                        if ans == 'CMD_ALLOW':
350
 
                            selection = ''
351
 
                            if options:
352
 
                                selection = options[selected]
353
 
                            match = apparmor.aa.re_match_include(selection)
354
 
                            if match:
355
 
                                deleted = False
356
 
                                inc = match
357
 
                                deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc)
358
 
                                self.user.aa[profile][hat]['include'][inc] = True
359
 
 
360
 
                                aaui.UI_Info(_('Adding %s to profile.') % selection)
361
 
                                if deleted:
362
 
                                    aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
363
 
 
364
 
                            self.user.aa[profile][hat]['allow']['capability'][capability]['set'] = True
365
 
                            self.user.aa[profile][hat]['allow']['capability'][capability]['audit'] = other.aa[profile][hat]['allow']['capability'][capability]['audit']
366
 
 
367
 
                            apparmor.aa.changed[profile] = True
368
 
 
369
 
                            aaui.UI_Info(_('Adding capability %s to profile.'), capability)
370
 
                            done = True
371
 
 
372
 
                        elif ans == 'CMD_DENY':
373
 
                            self.user.aa[profile][hat]['deny']['capability'][capability]['set'] = True
374
 
                            apparmor.aa.changed[profile] = True
375
 
 
376
 
                            aaui.UI_Info(_('Denying capability %s to profile.') % capability)
377
 
                            done = True
378
 
                        else:
379
 
                            done = False
380
 
 
381
320
            # Process all the path entries.
382
321
            for allow in ['allow', 'deny']:
383
322
                for path in sorted(other.aa[profile][hat][allow]['path'].keys()):
384
323
                    #print(path, other.aa[profile][hat][allow]['path'][path])
385
324
                    mode = other.aa[profile][hat][allow]['path'][path]['mode']
386
325
 
387
 
                    if self.user.aa[profile][hat][allow]['path'].get(path, False):
388
 
                        mode = self.conflict_mode(profile, hat, allow, path, 'mode', other.aa[profile][hat][allow]['path'][path]['mode'], self.user.aa[profile][hat][allow]['path'][path]['mode'])
389
 
                        self.conflict_mode(profile, hat, allow, path, 'audit', other.aa[profile][hat][allow]['path'][path]['audit'], self.user.aa[profile][hat][allow]['path'][path]['audit'])
390
 
                        apparmor.aa.changed[profile] = True
 
326
                    if aa[profile][hat][allow]['path'].get(path, False):
 
327
                        mode = self.conflict_mode(profile, hat, allow, path, 'mode', other.aa[profile][hat][allow]['path'][path]['mode'], aa[profile][hat][allow]['path'][path]['mode'])
 
328
                        self.conflict_mode(profile, hat, allow, path, 'audit', other.aa[profile][hat][allow]['path'][path]['audit'], aa[profile][hat][allow]['path'][path]['audit'])
 
329
                        changed[profile] = True
391
330
                        continue
392
331
                    # Lookup modes from profile
393
332
                    allow_mode = set()
395
334
                    deny_mode = set()
396
335
                    deny_audit = set()
397
336
 
398
 
                    fmode, famode, fm = apparmor.aa.rematchfrag(self.user.aa[profile][hat], 'allow', path)
 
337
                    fmode, famode, fm = apparmor.aa.rematchfrag(aa[profile][hat], 'allow', path)
399
338
                    if fmode:
400
339
                        allow_mode |= fmode
401
340
                    if famode:
402
341
                        allow_audit |= famode
403
342
 
404
 
                    cm, cam, m = apparmor.aa.rematchfrag(self.user.aa[profile][hat], 'deny', path)
 
343
                    cm, cam, m = apparmor.aa.rematchfrag(aa[profile][hat], 'deny', path)
405
344
                    if cm:
406
345
                        deny_mode |= cm
407
346
                    if cam:
408
347
                        deny_audit |= cam
409
348
 
410
 
                    imode, iamode, im = apparmor.aa.match_prof_incs_to_path(self.user.aa[profile][hat], 'allow', path)
 
349
                    imode, iamode, im = apparmor.aa.match_prof_incs_to_path(aa[profile][hat], 'allow', path)
411
350
                    if imode:
412
351
                        allow_mode |= imode
413
352
                    if iamode:
414
353
                        allow_audit |= iamode
415
354
 
416
 
                    cm, cam, m = apparmor.aa.match_prof_incs_to_path(self.user.aa[profile][hat], 'deny', path)
 
355
                    cm, cam, m = apparmor.aa.match_prof_incs_to_path(aa[profile][hat], 'deny', path)
417
356
                    if cm:
418
357
                        deny_mode |= cm
419
358
                    if cam:
434
373
                        if not allow_mode & apparmor.aamode.AA_MAY_EXEC:
435
374
                            mode |= apparmor.aa.str_to_mode('ix')
436
375
 
437
 
                    # m is not implied by ix
438
 
 
439
 
                    ### If we get an mmap request, check if we already have it in allow_mode
440
 
                    ##if mode & AA_EXEC_MMAP:
441
 
                    ##    # ix implies m, so we don't need to add m if ix is present
442
 
                    ##    if contains(allow_mode, 'ix'):
443
 
                    ##        mode = mode - AA_EXEC_MMAP
444
 
 
445
376
                    if not mode:
446
377
                        continue
447
378
 
462
393
                        for incname in apparmor.aa.include.keys():
463
394
                            include_valid = False
464
395
                            # If already present skip
465
 
                            if self.user.aa[profile][hat][incname]:
 
396
                            if aa[profile][hat][incname]:
466
397
                                continue
467
398
                            if incname.startswith(apparmor.aa.profile_dir):
468
399
                                incname = incname.replace(apparmor.aa.profile_dir+'/', '', 1)
512
443
                            owner_toggle = apparmor.aa.cfg['settings']['default_owner_prompt']
513
444
                        done = False
514
445
                        while not done:
515
 
                            q =  aaui.PromptQuestion()
 
446
                            q = aaui.PromptQuestion()
516
447
                            q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat),
517
448
                                            _('Path'), path]
518
449
 
598
529
                            elif ans == 'CMD_ALLOW':
599
530
                                path = options[selected]
600
531
                                done = True
601
 
                                match = apparmor.aa.re_match_include(path)
 
532
                                match = re_match_include(path)
602
533
                                if match:
603
534
                                    inc = match
604
 
                                    deleted = 0
605
 
                                    deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc)
606
 
                                    self.user.aa[profile][hat]['include'][inc] =  True
607
 
                                    apparmor.aa.changed[profile] =  True
 
535
                                    deleted = apparmor.aa.delete_duplicates(aa[profile][hat], inc)
 
536
                                    aa[profile][hat]['include'][inc] = True
 
537
                                    changed[profile] = True
608
538
                                    aaui.UI_Info(_('Adding %s to profile.') % path)
609
539
                                    if deleted:
610
540
                                        aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
611
541
 
612
542
                                else:
613
 
                                    if self.user.aa[profile][hat]['allow']['path'][path].get('mode', False):
614
 
                                        mode |= self.user.aa[profile][hat]['allow']['path'][path]['mode']
 
543
                                    if aa[profile][hat]['allow']['path'][path].get('mode', False):
 
544
                                        mode |= aa[profile][hat]['allow']['path'][path]['mode']
615
545
                                    deleted = []
616
 
                                    for entry in self.user.aa[profile][hat]['allow']['path'].keys():
 
546
                                    for entry in aa[profile][hat]['allow']['path'].keys():
617
547
                                        if path == entry:
618
548
                                            continue
619
549
 
620
550
                                        if apparmor.aa.matchregexp(path, entry):
621
 
                                            if apparmor.aa.mode_contains(mode, self.user.aa[profile][hat]['allow']['path'][entry]['mode']):
 
551
                                            if apparmor.aa.mode_contains(mode, aa[profile][hat]['allow']['path'][entry]['mode']):
622
552
                                                deleted.append(entry)
623
553
                                    for entry in deleted:
624
 
                                        self.user.aa[profile][hat]['allow']['path'].pop(entry)
 
554
                                        aa[profile][hat]['allow']['path'].pop(entry)
625
555
                                    deleted = len(deleted)
626
556
 
627
557
                                    if owner_toggle == 0:
633
563
                                    elif owner_toggle == 3:
634
564
                                        mode = apparmor.aa.owner_flatten_mode(mode)
635
565
 
636
 
                                    if not self.user.aa[profile][hat]['allow'].get(path, False):
637
 
                                        self.user.aa[profile][hat]['allow']['path'][path]['mode'] = self.user.aa[profile][hat]['allow']['path'][path].get('mode', set()) | mode
 
566
                                    if not aa[profile][hat]['allow'].get(path, False):
 
567
                                        aa[profile][hat]['allow']['path'][path]['mode'] = aa[profile][hat]['allow']['path'][path].get('mode', set()) | mode
638
568
 
639
569
 
640
570
                                    tmpmode = set()
641
571
                                    if audit_toggle == 1:
642
 
                                        tmpmode = mode- allow_mode
 
572
                                        tmpmode = mode - allow_mode
643
573
                                    elif audit_toggle == 2:
644
574
                                        tmpmode = mode
645
575
 
646
 
                                    self.user.aa[profile][hat]['allow']['path'][path]['audit'] = self.user.aa[profile][hat]['allow']['path'][path].get('audit', set()) | tmpmode
 
576
                                    aa[profile][hat]['allow']['path'][path]['audit'] = aa[profile][hat]['allow']['path'][path].get('audit', set()) | tmpmode
647
577
 
648
 
                                    apparmor.aa.changed[profile] = True
 
578
                                    changed[profile] = True
649
579
 
650
580
                                    aaui.UI_Info(_('Adding %(path)s %(mode)s to profile') % { 'path': path, 'mode': apparmor.aa.mode_to_str_user(mode) })
651
581
                                    if deleted:
654
584
                            elif ans == 'CMD_DENY':
655
585
                                path = options[selected].strip()
656
586
                                # Add new entry?
657
 
                                self.user.aa[profile][hat]['deny']['path'][path]['mode'] = self.user.aa[profile][hat]['deny']['path'][path].get('mode', set()) | (mode - allow_mode)
658
 
 
659
 
                                self.user.aa[profile][hat]['deny']['path'][path]['audit'] = self.user.aa[profile][hat]['deny']['path'][path].get('audit', set())
660
 
 
661
 
                                apparmor.aa.changed[profile] = True
 
587
                                aa[profile][hat]['deny']['path'][path]['mode'] = aa[profile][hat]['deny']['path'][path].get('mode', set()) | (mode - allow_mode)
 
588
 
 
589
                                aa[profile][hat]['deny']['path'][path]['audit'] = aa[profile][hat]['deny']['path'][path].get('audit', set())
 
590
 
 
591
                                changed[profile] = True
662
592
 
663
593
                                done = True
664
594
 
665
595
                            elif ans == 'CMD_NEW':
666
596
                                arg = options[selected]
667
 
                                if not apparmor.aa.re_match_include(arg):
 
597
                                if not re_match_include(arg):
668
598
                                    ans = aaui.UI_GetString(_('Enter new path: '), arg)
669
599
#                                         if ans:
670
600
#                                             if not matchliteral(ans, path):
678
608
 
679
609
                            elif ans == 'CMD_GLOB':
680
610
                                newpath = options[selected].strip()
681
 
                                if not apparmor.aa.re_match_include(newpath):
 
611
                                if not re_match_include(newpath):
682
612
                                    newpath = apparmor.aa.glob_path(newpath)
683
613
 
684
614
                                    if newpath not in options:
689
619
 
690
620
                            elif ans == 'CMD_GLOBEXT':
691
621
                                newpath = options[selected].strip()
692
 
                                if not apparmor.aa.re_match_include(newpath):
 
622
                                if not re_match_include(newpath):
693
623
                                    newpath = apparmor.aa.glob_path_withext(newpath)
694
624
 
695
625
                                    if newpath not in options:
701
631
                            elif re.search('\d', ans):
702
632
                                default_option = ans
703
633
 
704
 
            #
705
 
            for allow in ['allow', 'deny']:
706
 
                for family in sorted(other.aa[profile][hat][allow]['netdomain']['rule'].keys()):
707
 
                    # severity handling for net toggles goes here
 
634
            for ruletype in ['capability', 'network', 'change_profile']:
 
635
                if other.aa[profile][hat].get(ruletype, False): # needed until we have proper profile initialization
 
636
                    for rule_obj in other.aa[profile][hat][ruletype].rules:
708
637
 
709
 
                    for sock_type in sorted(other.aa[profile][hat][allow]['netdomain']['rule'][family].keys()):
710
 
                        #if apparmor.aa.profile_known_network(self.user.aa[profile][hat], family, sock_type):
711
 
                        #    continue
712
 
                        # disabled for now because it crashes, for details and impact see
713
 
                        # https://bugs.launchpad.net/apparmor/+bug/1382241
 
638
                        if is_known_rule(aa[profile][hat], ruletype, rule_obj):
 
639
                            continue
714
640
 
715
641
                        default_option = 1
716
642
                        options = []
717
 
                        newincludes = apparmor.aa.match_net_includes(self.user.aa[profile][hat], family, sock_type)
 
643
                        newincludes = match_includes(aa[profile][hat], ruletype, rule_obj)
718
644
                        q = aaui.PromptQuestion()
719
645
                        if newincludes:
720
 
                            options += list(map(lambda s: '#include <%s>'%s, sorted(set(newincludes))))
721
 
                        if True:#options:
722
 
                            options.append('network %s %s' % (family, sock_type))
723
 
                            q.options = options
724
 
                            q.selected = default_option - 1
725
 
 
726
 
                        q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat)]
727
 
                        q.headers += [_('Network Family'), family]
728
 
                        q.headers += [_('Socket Type'), sock_type]
729
 
 
730
 
                        audit_toggle = 0
731
 
                        q.functions = ['CMD_ALLOW', 'CMD_DENY', 'CMD_IGNORE_ENTRY', 'CMD_AUDIT_NEW',
732
 
                                          'CMD_ABORT', 'CMD_FINISHED']
733
 
 
734
 
                        q.default = 'CMD_ALLOW'
 
646
                            options += list(map(lambda inc: '#include <%s>' % inc, sorted(set(newincludes))))
 
647
 
 
648
                        options.append(rule_obj.get_clean())
 
649
                        q.options = options
 
650
                        q.selected = default_option - 1
735
651
 
736
652
                        done = False
737
653
                        while not done:
 
654
                            q.headers = [_('Profile'), combine_name(profile, hat)]
 
655
                            q.headers += rule_obj.logprof_header()
 
656
 
 
657
                            # Load variables into sev_db? Not needed/used for capabilities and network rules.
 
658
                            severity = rule_obj.severity(sev_db)
 
659
                            if severity != sev_db.NOT_IMPLEMENTED:
 
660
                                q.headers += [_('Severity'), severity]
 
661
 
 
662
                            q.functions = available_buttons(rule_obj)
 
663
                            q.default = q.functions[0]
 
664
 
738
665
                            ans, selected = q.promptUser()
739
666
                            if ans == 'CMD_IGNORE_ENTRY':
740
667
                                done = True
743
670
                            elif ans == 'CMD_FINISHED':
744
671
                                return
745
672
 
746
 
                            if ans.startswith('CMD_AUDIT'):
747
 
                                audit_toggle = not audit_toggle
748
 
                                audit = ''
749
 
                                if audit_toggle:
750
 
                                    audit = 'audit'
751
 
                                    q.functions = ['CMD_ALLOW', 'CMD_DENY', 'CMD_AUDIT_OFF',
752
 
                                                      'CMD_ABORT', 'CMD_FINISHED']
 
673
                            elif ans.startswith('CMD_AUDIT'):
 
674
                                if ans == 'CMD_AUDIT_NEW':
 
675
                                    rule_obj.audit = True
 
676
                                    rule_obj.raw_rule = None
753
677
                                else:
754
 
                                    q.functions = ['CMD_ALLOW', 'CMD_DENY', 'CMD_AUDIT_NEW',
755
 
                                                      'CMD_ABORT', 'CMD_FINISHED']
756
 
                                q.headers = [_('Profile'), apparmor.aa.combine_name(profile, hat)]
757
 
                                q.headers += [_('Network Family'), audit + family]
758
 
                                q.headers += [_('Socket Type'), sock_type]
 
678
                                    rule_obj.audit = False
 
679
                                    rule_obj.raw_rule = None
 
680
 
 
681
                                options[len(options) - 1] = rule_obj.get_clean()
 
682
                                q.options = options
759
683
 
760
684
                            elif ans == 'CMD_ALLOW':
761
 
                                #print(options, selected)
 
685
                                done = True
 
686
                                changed[profile] = True
 
687
 
762
688
                                selection = options[selected]
763
 
                                done = True
764
 
                                if apparmor.aa.re_match_include(selection): #re.search('#include\s+<.+>$', selection):
765
 
                                    inc =  apparmor.aa.re_match_include(selection) #re.search('#include\s+<(.+)>$', selection).groups()[0]
766
 
                                    deleted =  0
767
 
                                    deleted = apparmor.aa.delete_duplicates(self.user.aa[profile][hat], inc)
768
 
 
769
 
                                    self.user.aa[profile][hat]['include'][inc] = True
770
 
 
771
 
                                    apparmor.aa.changed[profile] = True
772
 
 
773
 
                                    aaui.UI_Info(_('Adding %s to profile') % selection)
 
689
 
 
690
                                inc = re_match_include(selection)
 
691
                                if inc:
 
692
                                    deleted = delete_duplicates(aa[profile][hat], inc)
 
693
 
 
694
                                    aa[profile][hat]['include'][inc] = True
 
695
 
 
696
                                    aaui.UI_Info(_('Adding %s to profile.') % selection)
774
697
                                    if deleted:
775
698
                                        aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted)
776
699
 
777
700
                                else:
778
 
                                    self.user.aa[profile][hat]['allow']['netdomain']['audit'][family][sock_type] = audit_toggle
779
 
                                    self.user.aa[profile][hat]['allow']['netdomain']['rule'][family][sock_type] = True
780
 
 
781
 
                                    apparmor.aa.changed[profile] = True
782
 
 
783
 
                                    aaui.UI_Info(_('Adding network access %(family)s %(type)s to profile.') % { 'family': family, 'type': sock_type })
 
701
                                    aa[profile][hat][ruletype].add(rule_obj)
 
702
 
 
703
                                    aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean())
784
704
 
785
705
                            elif ans == 'CMD_DENY':
786
706
                                done = True
787
 
                                self.user.aa[profile][hat]['deny']['netdomain']['rule'][family][sock_type] = True
788
 
                                apparmor.aa.changed[profile] = True
789
 
                                aaui.UI_Info(_('Denying network access %(family)s %(type)s to profile') % { 'family': family, 'type': sock_type })
 
707
                                changed[profile] = True
 
708
 
 
709
                                rule_obj.deny = True
 
710
                                rule_obj.raw_rule = None  # reset raw rule after manually modifying rule_obj
 
711
                                aa[profile][hat][ruletype].add(rule_obj)
 
712
                                aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean())
790
713
 
791
714
                            else:
792
715
                                done = False