From: dac.override@gmail.com (Dominick Grift) Date: Wed, 28 Dec 2016 16:15:42 +0100 Subject: [refpolicy] [PATCH] Policy for gpg's dirmngr In-Reply-To: <2b2c0eda-e5a2-e95e-1c2e-cdb6bbf7232d@gmail.com> References: <20161228145816.25231-1-aranea@aixah.de> <2b2c0eda-e5a2-e95e-1c2e-cdb6bbf7232d@gmail.com> Message-ID: To: refpolicy@oss.tresys.com List-Id: refpolicy.oss.tresys.com On 12/28/2016 04:11 PM, Dominick Grift wrote: > On 12/28/2016 03:58 PM, Luis Ressel via refpolicy wrote: >> GnuPG 2.1 uses a separate dirmngr process for retrieving keys from a >> keyserver. This dirmngr is an integral part of GnuPG 2.1 and has some >> considerable differences from the old 'dirmngr' provided as an addon >> package for GnuPG 2.0. Using the same policies for both of those daemons >> would result in an unwieldy policy with too many permissions. >> >> The fc collision for /usr/bin/dirmngr shouldn't be a problem, as GnuPG >> 2.0 and 2.1 can't be installed in parallel; and to the best of my >> knowledge, the (no longer maintained) dirmngr addon for GnuPG 2.0 isn't >> in widespread use anyway. >> --- >> gpg.fc | 2 ++ >> gpg.if | 39 +++++++++++++++++++++++++++------ >> gpg.te | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 113 insertions(+), 7 deletions(-) >> >> diff --git a/gpg.fc b/gpg.fc >> index 3067dae..d96b347 100644 >> --- a/gpg.fc >> +++ b/gpg.fc >> @@ -1,8 +1,10 @@ >> HOME_DIR/\.gnupg(/.+)? gen_context(system_u:object_r:gpg_secret_t,s0) >> HOME_DIR/\.gnupg/log-socket -s gen_context(system_u:object_r:gpg_agent_tmp_t,s0) >> +HOME_DIR/\.gnupg/S\.dirmngr -s gen_context(system_u:object_r:gpg_dirmngr_tmp_t,s0) >> HOME_DIR/\.gnupg/S\.gpg-agent.* -s gen_context(system_u:object_r:gpg_agent_tmp_t,s0) >> HOME_DIR/\.gnupg/S\.scdaemon -s gen_context(system_u:object_r:gpg_agent_tmp_t,s0) >> >> +/usr/bin/dirmngr -- gen_context(system_u:object_r:gpg_dirmngr_exec_t,s0) >> /usr/bin/gpg(2)? -- gen_context(system_u:object_r:gpg_exec_t,s0) >> /usr/bin/gpgsm -- gen_context(system_u:object_r:gpg_exec_t,s0) >> /usr/bin/gpg-agent -- gen_context(system_u:object_r:gpg_agent_exec_t,s0) >> diff --git a/gpg.if b/gpg.if >> index efffff8..7612c57 100644 >> --- a/gpg.if >> +++ b/gpg.if >> @@ -17,32 +17,35 @@ >> # >> interface(`gpg_role',` >> gen_require(` >> - attribute_role gpg_roles, gpg_agent_roles, gpg_helper_roles, gpg_pinentry_roles; >> + attribute_role gpg_roles, gpg_agent_roles, gpg_dirmngr_roles, gpg_helper_roles, gpg_pinentry_roles; >> type gpg_t, gpg_exec_t, gpg_agent_t; >> type gpg_agent_exec_t, gpg_agent_tmp_t, gpg_helper_t; >> type gpg_pinentry_t, gpg_pinentry_tmp_t, gpg_secret_t; >> + type gpg_dirmngr_t, gpg_dirmngr_exec_t, gpg_dirmngr_tmp_t; >> ') >> >> roleattribute $1 gpg_roles; >> roleattribute $1 gpg_agent_roles; >> + roleattribute $1 gpg_dirmngr_roles; >> roleattribute $1 gpg_helper_roles; >> roleattribute $1 gpg_pinentry_roles; >> >> domtrans_pattern($2, gpg_exec_t, gpg_t) >> domtrans_pattern($2, gpg_agent_exec_t, gpg_agent_t) >> + domtrans_pattern($2, gpg_dirmngr_exec_t, gpg_dirmngr_t) >> >> allow $2 self:process setrlimit; >> - allow $2 { gpg_t gpg_agent_t gpg_helper_t gpg_pinentry_t }:process { ptrace signal_perms }; >> - ps_process_pattern($2, { gpg_t gpg_agent_t gpg_helper_t gpg_pinentry_t }) >> + allow $2 { gpg_t gpg_agent_t gpg_dirmngr_t gpg_helper_t gpg_pinentry_t }:process { ptrace signal_perms }; >> + ps_process_pattern($2, { gpg_t gpg_agent_t gpg_dirmngr_t gpg_helper_t gpg_pinentry_t }) >> >> allow gpg_pinentry_t $2:process signull; >> allow gpg_helper_t $2:fd use; >> - allow { gpg_t gpg_agent_t gpg_helper_t gpg_pinentry_t } $2:fifo_file { read write }; >> + allow { gpg_t gpg_agent_t gpg_dirmngr_t gpg_helper_t gpg_pinentry_t } $2:fifo_file { read write }; >> >> - allow $2 { gpg_agent_tmp_t gpg_secret_t }:dir { manage_dir_perms relabel_dir_perms }; >> - allow $2 { gpg_agent_tmp_t gpg_secret_t }:file { manage_file_perms relabel_file_perms }; >> + allow $2 { gpg_agent_tmp_t gpg_dirmngr_tmp_t gpg_secret_t }:dir { manage_dir_perms relabel_dir_perms }; >> + allow $2 { gpg_agent_tmp_t gpg_dirmngr_tmp_t gpg_secret_t }:file { manage_file_perms relabel_file_perms }; >> allow $2 gpg_secret_t:lnk_file { manage_lnk_file_perms relabel_lnk_file_perms }; >> - allow $2 { gpg_agent_tmp_t gpg_pinentry_tmp_t gpg_secret_t }:sock_file { manage_sock_file_perms relabel_sock_file_perms }; >> + allow $2 { gpg_agent_tmp_t gpg_dirmngr_tmp_t gpg_pinentry_tmp_t gpg_secret_t }:sock_file { manage_sock_file_perms relabel_sock_file_perms }; >> filetrans_pattern($2, gpg_secret_t, gpg_agent_tmp_t, sock_file, "log-socket") >> userdom_user_home_dir_filetrans($2, gpg_secret_t, dir, ".gnupg") >> >> @@ -216,6 +219,28 @@ interface(`gpg_stream_connect_agent',` >> >> ######################################## >> ## >> +## Connect to gpg dirmngr socket >> +## >> +## >> +## >> +## Domain allowed access. >> +## >> +## >> +# >> +interface(`gpg_stream_connect_dirmngr',` >> + gen_require(` >> + type gpg_dirmngr_t, gpg_dirmngr_tmp_t; >> + type gpg_secret_t; >> + ') >> + >> + stream_connect_pattern($1, gpg_dirmngr_tmp_t, gpg_dirmngr_tmp_t, gpg_dirmngr_t) >> + allow $1 gpg_secret_t:dir search_dir_perms; >> + userdom_search_user_runtime($1) >> + userdom_search_user_home_dirs($1) >> +') >> + >> +######################################## >> +## >> ## Send messages to and from gpg >> ## pinentry over DBUS. >> ## >> diff --git a/gpg.te b/gpg.te >> index 64e3c5c..5c2e526 100644 >> --- a/gpg.te >> +++ b/gpg.te >> @@ -19,6 +19,8 @@ roleattribute system_r gpg_roles; >> >> attribute_role gpg_agent_roles; >> >> +attribute_role gpg_dirmngr_roles; >> + >> attribute_role gpg_helper_roles; >> roleattribute system_r gpg_helper_roles; >> >> @@ -72,6 +74,18 @@ optional_policy(` >> pulseaudio_tmpfs_content(gpg_pinentry_tmpfs_t) >> ') >> >> +type gpg_dirmngr_t; >> +type gpg_dirmngr_exec_t; >> +typealias gpg_dirmngr_t alias { user_gpg_dirmngr_t staff_gpg_dirmngr_t sysadm_gpg_dirmngr_t }; >> +typealias gpg_dirmngr_t alias { auditadm_gpg_dirmngr_t secadm_gpg_dirmngr_t }; > > You do not have to typealias because I do not believe these types exist > >> +userdom_user_application_domain(gpg_dirmngr_t, gpg_dirmngr_exec_t) >> +role gpg_dirmngr_roles types gpg_dirmngr_t; >> + >> +type gpg_dirmngr_tmp_t; >> +typealias gpg_dirmngr_tmp_t alias { user_gpg_dirmngr_tmp_t staff_gpg_dirmngr_tmp_t sysadm_gpg_dirmngr_tmp_t }; >> +typealias gpg_dirmngr_tmp_t alias { auditadm_gpg_dirmngr_tmp_t secadm_gpg_dirmngr_tmp_t }; >> +userdom_user_tmp_file(gpg_dirmngr_tmp_t) >> + >> ######################################## >> # >> # Local policy >> @@ -94,8 +108,10 @@ manage_lnk_files_pattern(gpg_t, gpg_secret_t, gpg_secret_t) >> userdom_user_home_dir_filetrans(gpg_t, gpg_secret_t, dir) >> >> gpg_stream_connect_agent(gpg_t) >> +gpg_stream_connect_dirmngr(gpg_t) >> >> domtrans_pattern(gpg_t, gpg_agent_exec_t, gpg_agent_t) >> +domtrans_pattern(gpg_t, gpg_dirmngr_exec_t, gpg_dirmngr_t) >> domtrans_pattern(gpg_t, gpg_helper_exec_t, gpg_helper_t) >> >> kernel_read_sysctl(gpg_t) >> @@ -359,3 +375,66 @@ optional_policy(` >> optional_policy(` >> xserver_user_x_domain_template(gpg_pinentry, gpg_pinentry_t, gpg_pinentry_tmpfs_t) >> ') >> + >> +############################## >> +# >> +# Dirmngr local policy >> +# >> + >> +allow gpg_dirmngr_t self:unix_stream_socket { create_stream_socket_perms connectto }; >> + >> +manage_dirs_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_secret_t) >> +manage_files_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_secret_t) >> +manage_lnk_files_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_secret_t) >> +manage_sock_files_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_secret_t) >> + > > This would be something i would be trying to avoid. Especially with a > process that needs to be able to connect to the network. > > I think that this is probably not needed either. AFAIK, dirmngr only > needs to maintain ~/.gnupg/crls.d (besides its socket and reading its > ~/.gnupg/dirmngr.conf) > > Ideally only the gpg process itself would be able to ever touch gpg > secrets (files that is). > > Also ideally there should not be sockets with gpg_secret_t type in the > first place > This is what my ~/.gnupg looks like drwx------. 4 kcinimod kcinimod wheel.id:wheel.role:gpg.home_user_file:s0 4096 Dec 12 22:42 . drwx--x---+ 32 kcinimod kcinimod wheel.id:wheel.role:home_dir.file:s0 4096 Dec 27 23:00 .. drwx------. 2 kcinimod kcinimod wheel.id:wheel.role:dirmngr.home_user_file:s0 4096 Jul 12 18:05 crls.d -rw-------. 1 kcinimod kcinimod wheel.id:wheel.role:dirmngr.home_user_file:s0 2373 Jan 6 2016 dirmngr.conf -rw-rw-r--. 1 kcinimod kcinimod wheel.id:wheel.role:gpg_agent.home_user_file:s0 202 Jan 7 2016 gpg-agent.conf -rw-rw-r--. 1 kcinimod kcinimod wheel.id:wheel.role:gpg_agent.home_user_file:s0 1372398 Dec 28 15:56 gpg-agent.log -rw-------. 1 kcinimod kcinimod wheel.id:wheel.role:gpg.home_user_file:s0 6716 Jan 7 2016 gpg.conf drwx------. 2 kcinimod kcinimod wheel.id:wheel.role:gpg_agent.home_user_file:s0 4096 Jan 8 2016 private-keys-v1.d -rw-rw-r--. 1 kcinimod kcinimod wheel.id:wheel.role:gpg.home_user_file:s0 5180 Jan 6 2016 publickey.asc -rw-r--r--. 1 kcinimod kcinimod wheel.id:wheel.role:gpg.home_user_file:s0 73551 Dec 12 22:42 pubring.kbx -rw-r--r--. 1 kcinimod kcinimod wheel.id:wheel.role:gpg.home_user_file:s0 28973 Nov 14 11:01 pubring.kbx~ -rw-------. 1 kcinimod kcinimod wheel.id:wheel.role:gpg.home_user_file:s0 600 Dec 14 23:13 random_seed -rw-rw-r--. 1 kcinimod kcinimod wheel.id:wheel.role:scdaemon.home_user_file:s0 7 Dec 28 15:56 reader_0.status -rw-rw-r--. 1 kcinimod kcinimod wheel.id:wheel.role:scdaemon.home_user_file:s0 7 Dec 26 09:36 reader_-1.status -rw-rw-r--. 1 kcinimod kcinimod wheel.id:wheel.role:scdaemon.home_user_file:s0 68 Jan 7 2016 scdaemon.conf -rw-r-----. 1 kcinimod kcinimod wheel.id:wheel.role:gpg_agent.home_user_file:s0 676 Jan 8 2016 sshcontrol -rw-------. 1 kcinimod kcinimod wheel.id:wheel.role:gpg.home_user_file:s0 1320 Dec 12 22:42 trustdb.gpg And /run/user/1000/gnupg: drwx------. 2 kcinimod kcinimod wheel.id:wheel.role:gpg.tmpfs_user_file:s0 100 Dec 28 15:56 . drwx------. 10 kcinimod kcinimod sys.id:sys.role:tmpfs.fs:s0 300 Dec 28 16:13 .. srwx------. 1 kcinimod kcinimod wheel.id:wheel.role:gpg_agent.tmpfs_user_file:s0 0 Dec 28 15:56 S.gpg-agent srwx------. 1 kcinimod kcinimod wheel.id:wheel.role:gpg_agent.tmpfs_user_file:s0 0 Dec 28 15:56 S.gpg-agent.ssh srwx------. 1 kcinimod kcinimod wheel.id:wheel.role:scdaemon.tmpfs_user_file:s0 0 Dec 28 15:56 S.scdaemon >> +manage_dirs_pattern(gpg_dirmngr_t, gpg_dirmngr_tmp_t, gpg_dirmngr_tmp_t) >> +manage_files_pattern(gpg_dirmngr_t, gpg_dirmngr_tmp_t, gpg_dirmngr_tmp_t) >> +manage_sock_files_pattern(gpg_dirmngr_t, gpg_dirmngr_tmp_t, gpg_dirmngr_tmp_t) >> +files_tmp_filetrans(gpg_dirmngr_t, gpg_dirmngr_tmp_t, { file sock_file dir }) >> + >> +filetrans_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_dirmngr_tmp_t, sock_file, "S.dirmngr") >> + >> +domain_use_interactive_fds(gpg_dirmngr_t) >> + >> +userdom_use_user_terminals(gpg_dirmngr_t) >> +userdom_search_user_home_dirs(gpg_dirmngr_t) >> + >> +miscfiles_read_generic_certs(gpg_dirmngr_t) >> +miscfiles_read_localization(gpg_dirmngr_t) >> + >> +auth_use_nsswitch(gpg_dirmngr_t) >> + >> +corenet_all_recvfrom_unlabeled(gpg_dirmngr_t) >> +corenet_all_recvfrom_netlabel(gpg_dirmngr_t) >> +corenet_tcp_sendrecv_generic_if(gpg_dirmngr_t) >> +corenet_tcp_sendrecv_generic_node(gpg_dirmngr_t) >> + >> +# Key retrieval via HKP and LDAP (optionally tunnelled via Tor) >> +sysnet_use_ldap(gpg_dirmngr_t) >> +corenet_tcp_connect_pgpkeyserver_port(gpg_dirmngr_t) >> +corenet_tcp_sendrecv_pgpkeyserver_port(gpg_dirmngr_t) >> +corenet_sendrecv_pgpkeyserver_client_packets(gpg_dirmngr_t) >> +corenet_tcp_connect_http_port(gpg_dirmngr_t) >> +corenet_tcp_sendrecv_http_port(gpg_dirmngr_t) >> +corenet_sendrecv_http_client_packets(gpg_dirmngr_t) >> +corenet_tcp_connect_tor_port(gpg_dirmngr_t) >> +corenet_tcp_sendrecv_tor_port(gpg_dirmngr_t) >> +corenet_sendrecv_tor_client_packets(gpg_dirmngr_t) >> + >> +# Since version 2.1.17, gnupg uses a custom DNS implementation >> +sysnet_dns_name_resolve(gpg_dirmngr_t) > > sysnet_dns_name_resolve is already enclosed with auth_use_nsswitch() i > believe (probably sysnet_use_ldap is also enclosed with > auth_use_nsswitch() (not sure) > >> +corenet_udp_bind_generic_node(gpg_dirmngr_t) >> +corenet_udp_bind_all_unreserved_ports(gpg_dirmngr_t) >> + >> +tunable_policy(`use_nfs_home_dirs',` >> + fs_manage_nfs_dirs(gpg_dirmngr_t) >> + fs_manage_nfs_files(gpg_dirmngr_t) >> + fs_manage_nfs_symlinks(gpg_dirmngr_t) >> +') >> + >> +tunable_policy(`use_samba_home_dirs',` >> + fs_manage_cifs_dirs(gpg_dirmngr_t) >> + fs_manage_cifs_files(gpg_dirmngr_t) >> + fs_manage_cifs_symlinks(gpg_dirmngr_t) >> +') >> > > -- Key fingerprint = 5F4D 3CDB D3F8 3652 FBD8 02D5 3B6C 5F1D 2C7B 6B02 https://sks-keyservers.net/pks/lookup?op=get&search=0x3B6C5F1D2C7B6B02 Dominick Grift -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 648 bytes Desc: OpenPGP digital signature Url : http://oss.tresys.com/pipermail/refpolicy/attachments/20161228/112af7e8/attachment-0001.bin