Skip to contentSkip to conversation

Policy for gpg's dirmngr

PATCH New Luis Ressel 3 participants 11 messages Aug 9, 2015 – Aug 11, 2015

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 Policy for gpg's dirmngr

GnuPG 2.1 uses a separate dirmngr process for retrieving keys from a keyserver.

---
 gpg.fc |  1 +
 gpg.if | 16 +++++++++-------
 gpg.te | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 7 deletions(-)
gpg.fc +1 -0
index 888cd2c..d492dc5 100644
@@ -1,6 +1,7 @@
 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)
 
+/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)
gpg.if +9 -7
index b299418..13149ca 100644
@@ -17,31 +17,33 @@
 #
 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_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)
 
-	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")
 
gpg.te +50 -0

73 lines not on this page · raw message

Signature · 1 line
2.5.0
#1 lore raw

PATCH 2/2 gpg 2.1 places gpg-agent sockets in ~/.gnupg/

---
 gpg.if | 3 ++-
 gpg.te | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)
gpg.if +2 -1
index 13149ca..4141add 100644
@@ -205,10 +205,11 @@ interface(`gpg_rw_agent_pipes',`
 #
 interface(`gpg_stream_connect_agent',`
 	gen_require(`
-		type gpg_agent_t, gpg_agent_tmp_t;
+		type gpg_agent_t, gpg_agent_tmp_t, gpg_secret_t;
 	')
 
 	stream_connect_pattern($1, gpg_agent_tmp_t, gpg_agent_tmp_t, gpg_agent_t)
+	stream_connect_pattern($1, gpg_secret_t, gpg_agent_tmp_t, gpg_agent_t)
 ')
 
 ########################################
gpg.te +3 -0
index a40ac69..edf238a 100644
@@ -241,6 +241,9 @@ manage_sock_files_pattern(gpg_agent_t, gpg_agent_tmp_t, gpg_agent_tmp_t)
 files_tmp_filetrans(gpg_agent_t, gpg_agent_tmp_t, { file sock_file dir })
 
 filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "log-socket")
+filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.gpg-agent")
+filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.gpg-agent.ssh")
+filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.scdaemon")
 
 domtrans_pattern(gpg_agent_t, pinentry_exec_t, gpg_pinentry_t)
 
Signature · 1 line
2.5.0
#2 lore raw

PATCH 2/2 gpg 2.1 places gpg-agent sockets in ~/.gnupg/

Quoted 27 lines · Luis Ressel
---
 gpg.if | 3 ++-
 gpg.te | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)
gpg.if +2 -1
index 13149ca..4141add 100644
@@ -205,10 +205,11 @@ interface(`gpg_rw_agent_pipes',`
 #
 interface(`gpg_stream_connect_agent',`
 	gen_require(`
-		type gpg_agent_t, gpg_agent_tmp_t;
+		type gpg_agent_t, gpg_agent_tmp_t, gpg_secret_t;
 	')
 
 	stream_connect_pattern($1, gpg_agent_tmp_t, gpg_agent_tmp_t, gpg_agent_t)
+	stream_connect_pattern($1, gpg_secret_t, gpg_agent_tmp_t, gpg_agent_t)
 ')
 
 ########################################
gpg.te +0 -0
index a40ac69..edf238a 100644

gpg.te manage_sock_files_pattern(gpg_agent_t, gpg_agent_tmp_t, gpg_agent_tmp_t) · line 246

Quoted 6 lines
gpg.te +3 -0
@@ -241,6 +241,9 @@ manage_sock_files_pattern(gpg_agent_t, gpg_agent_tmp_t, gpg_agent_tmp_t)
 files_tmp_filetrans(gpg_agent_t, gpg_agent_tmp_t, { file sock_file dir })
 
 filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "log-socket")
+filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.gpg-agent")
+filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.gpg-agent.ssh")
+filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.scdaemon")

I would probably instead confine scdaemon ( i have confined scdaemon in my personal policy)

Quoted 10 lines
gpg.te +0 -0
 domtrans_pattern(gpg_agent_t, pinentry_exec_t, gpg_pinentry_t)
 
Signature · 6 lines
2.5.0

_______________________________________________
refpolicy mailing list
refpolicy at oss.tresys.com
http://oss.tresys.com/mailman/listinfo/refpolicy
Signature · 11 lines
02DFF788
4D30 903A 1CF3 B756 FB48  1514 3148 83A2 02DF F788
http://keys.gnupg.net/pks/lookup?op=vindex&search=0x314883A202DFF788
Dominick Grift
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 648 bytes
Desc: not available
Url : http://oss.tresys.com/pipermail/refpolicy/attachments/20150810/993d1cc1/attachment.bin 
#3 lore raw

PATCH 2/2 gpg 2.1 places gpg-agent sockets in ~/.gnupg/

Quoted 32 lines · On Mon, 10 Aug 2015 09:27:18 +0200 Dominick Grift <[email protected]>…
Quoted 31 lines · Luis Ressel
---
 gpg.if | 3 ++-
 gpg.te | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)
gpg.if +2 -1
index 13149ca..4141add 100644
@@ -205,10 +205,11 @@ interface(`gpg_rw_agent_pipes',`
 #
 interface(`gpg_stream_connect_agent',`
 	gen_require(`
-		type gpg_agent_t, gpg_agent_tmp_t;
+		type gpg_agent_t, gpg_agent_tmp_t, gpg_secret_t;
 	')
 
 	stream_connect_pattern($1, gpg_agent_tmp_t,
 gpg_agent_tmp_t, gpg_agent_t)
+	stream_connect_pattern($1, gpg_secret_t, gpg_agent_tmp_t,
 gpg_agent_t) ')
 

########################################

gpg.te +0 -0
index a40ac69..edf238a 100644
@@ -241,6 +241,9 @@ manage_sock_files_pattern(gpg_agent_t,
 gpg_agent_tmp_t, gpg_agent_tmp_t) files_tmp_filetrans(gpg_agent_t,
 gpg_agent_tmp_t, { file sock_file dir }) 
 filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t,
Quoted 8 lines
Quoted 5 lines
gpg.te +1 -0
 sock_file, "log-socket") +filetrans_pattern(gpg_agent_t,
 gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.gpg-agent")
+filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t,
 sock_file, "S.gpg-agent.ssh") +filetrans_pattern(gpg_agent_t,

gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.scdaemon")

I would probably instead confine scdaemon ( i have confined scdaemon in my personal policy)

I'll have a look into confining scdaemon. But for now, it's running as gpg_agent_t, so we should label its socket accordingly.

Signature · 1 line
Luis Ressel
#4 lore raw

PATCH 2/2 gpg 2.1 places gpg-agent sockets in ~/.gnupg/

Quoted 44 lines · Luis Ressel
Quoted 32 lines · On Mon, 10 Aug 2015 09:27:18 +0200 Dominick Grift <[email protected]>…
Quoted 31 lines · Luis Ressel
---
 gpg.if | 3 ++-
 gpg.te | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)
gpg.if +2 -1
index 13149ca..4141add 100644
@@ -205,10 +205,11 @@ interface(`gpg_rw_agent_pipes',`
 #
 interface(`gpg_stream_connect_agent',`
 	gen_require(`
-		type gpg_agent_t, gpg_agent_tmp_t;
+		type gpg_agent_t, gpg_agent_tmp_t, gpg_secret_t;
 	')
 
 	stream_connect_pattern($1, gpg_agent_tmp_t,
 gpg_agent_tmp_t, gpg_agent_t)
+	stream_connect_pattern($1, gpg_secret_t, gpg_agent_tmp_t,
 gpg_agent_t) ')
 

########################################

gpg.te +0 -0
index a40ac69..edf238a 100644
@@ -241,6 +241,9 @@ manage_sock_files_pattern(gpg_agent_t,
 gpg_agent_tmp_t, gpg_agent_tmp_t) files_tmp_filetrans(gpg_agent_t,
 gpg_agent_tmp_t, { file sock_file dir }) 
 filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t,
Quoted 8 lines
Quoted 5 lines
gpg.te +1 -0
 sock_file, "log-socket") +filetrans_pattern(gpg_agent_t,
 gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.gpg-agent")
+filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t,
 sock_file, "S.gpg-agent.ssh") +filetrans_pattern(gpg_agent_t,

gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.scdaemon")

I would probably instead confine scdaemon ( i have confined scdaemon in my personal policy)

Quoted 2 lines

I'll have a look into confining scdaemon. But for now, it's running as gpg_agent_t, so we should label its socket accordingly.

How about then just remove the names from the transitions that will make it so that if agent creates any sockfiles in ~/.gnupg theyll get automatically created with the agent type "do as i say and not as i do": we should be conservative with the use of name-based auto type transitions

also this above S.scdaemon sock file has no accompanying file context specification?

Quoted 7 lines
Signature · 6 lines
-- 
Luis Ressel
_______________________________________________
refpolicy mailing list
refpolicy at oss.tresys.com
http://oss.tresys.com/mailman/listinfo/refpolicy
Signature · 11 lines
02DFF788
4D30 903A 1CF3 B756 FB48  1514 3148 83A2 02DF F788
http://keys.gnupg.net/pks/lookup?op=vindex&search=0x314883A202DFF788
Dominick Grift
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 648 bytes
Desc: not available
Url : http://oss.tresys.com/pipermail/refpolicy/attachments/20150810/af75e852/attachment.bin 
#5 lore raw

PATCH 2/2 gpg 2.1 places gpg-agent sockets in ~/.gnupg/

Quoted 46 lines · On Mon, 10 Aug 2015 15:33:14 +0200 Dominick Grift <[email protected]>…
Quoted 45 lines · Luis Ressel
Quoted 41 lines · On Mon, 10 Aug 2015 09:27:18 +0200 Dominick Grift <[email protected]>…
Quoted 29 lines · Luis Ressel
---
 gpg.if | 3 ++-
 gpg.te | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)
gpg.if +2 -1
index 13149ca..4141add 100644
@@ -205,10 +205,11 @@ interface(`gpg_rw_agent_pipes',`
 #
 interface(`gpg_stream_connect_agent',`
 	gen_require(`
-		type gpg_agent_t, gpg_agent_tmp_t;
+		type gpg_agent_t, gpg_agent_tmp_t,
 gpg_secret_t; ')
 
 	stream_connect_pattern($1, gpg_agent_tmp_t,
 gpg_agent_tmp_t, gpg_agent_t)
+	stream_connect_pattern($1, gpg_secret_t,
 gpg_agent_tmp_t, gpg_agent_t) ')
 

########################################

gpg.te +0 -0
index a40ac69..edf238a 100644
@@ -241,6 +241,9 @@ manage_sock_files_pattern(gpg_agent_t,
 gpg_agent_tmp_t, gpg_agent_tmp_t)
Quoted 8 lines

files_tmp_filetrans(gpg_agent_t, gpg_agent_tmp_t, { file sock_file dir }) filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "log-socket") +filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.gpg-agent") +filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.gpg-agent.ssh") +filetrans_pattern(gpg_agent_t, gpg_secret_t, gpg_agent_tmp_t, sock_file, "S.scdaemon")

I would probably instead confine scdaemon ( i have confined scdaemon in my personal policy)

Quoted 9 lines
Quoted 2 lines

I'll have a look into confining scdaemon. But for now, it's running as gpg_agent_t, so we should label its socket accordingly.

How about then just remove the names from the transitions that will make it so that if agent creates any sockfiles in ~/.gnupg theyll get automatically created with the agent type "do as i say and not as i do": we should be conservative with the use of name-based auto type transitions

Yes, it'd probably be okay to mark all sock_files as gpg_agent_tmp_t.

Quoted 2 lines

also this above S.scdaemon sock file has no accompanying file context specification?

Good catch, I forgot this.

Signature · 1 line
Luis Ressel
#6 lore raw

PATCH 1/2 Policy for gpg's dirmngr

In reply to Luis Ressel
Quoted 2 lines · Luis Ressel

GnuPG 2.1 uses a separate dirmngr process for retrieving keys from a keyserver.

I have a policy for dirmngr as well. Comparing mine with yours. Below are some commants.

Quoted 42 lines
---
 gpg.fc |  1 +
 gpg.if | 16 +++++++++-------
 gpg.te | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 7 deletions(-)
gpg.fc +1 -0
index 888cd2c..d492dc5 100644
@@ -1,6 +1,7 @@
 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)
 
+/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)
gpg.if +3 -1
index b299418..13149ca 100644
@@ -17,31 +17,33 @@
 #
 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_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)

gpg.if line 41

Quoted 10 lines
gpg.if +3 -3
 
-	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 };

I do not believe the above is required. dirmngr can be run directly by the caller so it should already have permissions to rw inherited fifo files of the caller as per the domtrans_pattern()

You would need to allow the user domain to run dirmngr with a domain transition first though, but it makes sense because you can dir dirmngr as a server (see man dirmngr)

Quoted 30 lines
gpg.if +3 -3
-	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")
 
gpg.te +4 -0
index f878352..a40ac69 100644
@@ -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;

gpg.te optional_policy(` · line 88

Quoted 10 lines
gpg.te +10 -0
+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 };
+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)
+

It does not seem to actually maintain temporary files. Instead it maintains content in ~/.gnupg. So classifying that type userdom_user_tmp_file is inaccurate in my view

gpg.te manage_lnk_files_pattern(gpg_t, gpg_secret_t, gpg_secret_t) · line 114

Quoted 11 lines
gpg.te +2 -0
 ########################################
 #
 # 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)
+stream_connect_pattern(gpg_t, gpg_dirmngr_tmp_t, gpg_dirmngr_tmp_t, gpg_dirmngr_t) 
 
 domtrans_pattern(gpg_t, gpg_agent_exec_t, gpg_agent_t)
+domtrans_pattern(gpg_t, gpg_dirmngr_exec_t, gpg_dirmngr_t)

Users should probably also be allowed to run dirmngr with a domain transition

Quoted 7 lines
gpg.te +0 -0
 domtrans_pattern(gpg_t, gpg_helper_exec_t, gpg_helper_t)
 
 kernel_read_sysctl(gpg_t)
@@ -344,3 +360,37 @@ optional_policy(`
 optional_policy(`
 	xserver_user_x_domain_template(gpg_pinentry, gpg_pinentry_t, gpg_pinentry_tmpfs_t)
 ')

gpg.te optional_policy(` · line 372

Quoted 10 lines
gpg.te +10 -0
+
+##############################
+#
+# Dirmngr local policy
+#
+
+manage_dirs_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_secret_t)
+manage_sock_files_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)

I do not believe that dirmngr needs to be able to maintain gpg secrets. (I am pretty sure about that)

gpg.te optional_policy(` · line 377

Quoted 5 lines
gpg.te +5 -0
+
+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 })

I do not believe dirmngr maintains anything in /tmp or /var/tmp, everything is maintained in ~/.gnupg

gpg.te optional_policy(` · line 379

Quoted 2 lines
gpg.te +2 -0
+
+filetrans_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_dirmngr_tmp_t, sock_file, "S.dirmngr")

I believe it also maintains ~/.gnupg/crls\.d(/.*)?

gpg.te optional_policy(` · line 385

Quoted 6 lines
gpg.te +6 -0
+
+userdom_use_user_terminals(gpg_dirmngr_t)
+userdom_search_user_home_dirs(gpg_dirmngr_t)
+
+dev_read_rand(gpg_dirmngr_t)
+dev_read_urand(gpg_dirmngr_t)

I was not able to confirm the above two instead thoug it wants to read crypto sysctls here

gpg.te optional_policy(` · line 395

Quoted 10 lines
gpg.te +10 -0
+
+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)
+
+corenet_sendrecv_all_client_packets(gpg_dirmngr_t)
+corenet_tcp_connect_all_ports(gpg_dirmngr_t)

I think that this may be a bit too much. I suppose it needs to be able to hkp and http ports instead?

Quoted 8 lines
gpg.te +1 -0
+corenet_tcp_sendrecv_all_ports(gpg_dirmngr_t)
Signature · 6 lines
2.5.0

_______________________________________________
refpolicy mailing list
refpolicy at oss.tresys.com
http://oss.tresys.com/mailman/listinfo/refpolicy
Signature · 11 lines
02DFF788
4D30 903A 1CF3 B756 FB48  1514 3148 83A2 02DF F788
http://keys.gnupg.net/pks/lookup?op=vindex&search=0x314883A202DFF788
Dominick Grift
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 648 bytes
Desc: not available
Url : http://oss.tresys.com/pipermail/refpolicy/attachments/20150810/6c50bacf/attachment.bin 
#7 lore raw

PATCH 1/2 Policy for gpg's dirmngr

Quoted 62 lines · On Mon, 10 Aug 2015 09:25:27 +0200 Dominick Grift <[email protected]>…
Quoted 2 lines · Luis Ressel

GnuPG 2.1 uses a separate dirmngr process for retrieving keys from a keyserver.

I have a policy for dirmngr as well. Comparing mine with yours. Below are some commants.

Quoted 55 lines
---
 gpg.fc |  1 +
 gpg.if | 16 +++++++++-------
 gpg.te | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 7 deletions(-)
gpg.fc +0 -0
index 888cd2c..d492dc5 100644
@@ -1,6 +1,7 @@
 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)
+/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 b299418..13149ca 100644 --- a/gpg.if +++ b/gpg.if

gpg.fc +1 -1
@@ -17,31 +17,33 @@
 #
 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;

gpg.fc +2 -1
+		type gpg_dirmngr_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)
 
-	allow $2 { gpg_t gpg_agent_t gpg_helper_t

gpg_pinentry_t }:process { ptrace signal_perms };

gpg.fc +0 -1
-	ps_process_pattern($2, { gpg_t gpg_agent_t gpg_helper_t

gpg_pinentry_t })

gpg.fc +1 -0
+	allow $2 { gpg_t gpg_agent_t gpg_dirmngr_t gpg_helper_t

gpg_pinentry_t }:process { ptrace signal_perms };

gpg.fc +1 -0
+	ps_process_pattern($2, { gpg_t gpg_agent_t gpg_dirmngr_t

gpg_helper_t gpg_pinentry_t })

gpg.fc +0 -0
 	allow gpg_pinentry_t $2:process signull;
 	allow gpg_helper_t $2:fd use;
Quoted 9 lines
Quoted 4 lines
gpg.fc +0 -1
-	allow { gpg_t gpg_agent_t gpg_helper_t gpg_pinentry_t }

$2:fifo_file { read write };

gpg.fc +1 -0
+	allow { gpg_t gpg_agent_t gpg_dirmngr_t gpg_helper_t

gpg_pinentry_t } $2:fifo_file { read write };

I do not believe the above is required. dirmngr can be run directly by the caller so it should already have permissions to rw inherited fifo files of the caller as per the domtrans_pattern()

In fact, the fifo permissions don't seem to be neccessary.

Quoted 4 lines

You would need to allow the user domain to run dirmngr with a domain transition first though, but it makes sense because you can dir dirmngr as a server (see man dirmngr)

I missed this. I'll add a domtrans.

Quoted 44 lines
Quoted 44 lines
gpg.fc +0 -1
-	allow $2 { gpg_agent_tmp_t gpg_secret_t }:dir

{ manage_dir_perms relabel_dir_perms };

gpg.fc +0 -1
-	allow $2 { gpg_agent_tmp_t gpg_secret_t }:file

{ manage_file_perms relabel_file_perms };

gpg.fc +1 -0
+	allow $2 { gpg_agent_tmp_t gpg_dirmngr_tmp_t

gpg_secret_t }:dir { manage_dir_perms relabel_dir_perms };

gpg.fc +1 -0
+	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 };

gpg.fc +0 -1
-	allow $2 { gpg_agent_tmp_t gpg_pinentry_tmp_t

gpg_secret_t }:sock_file { manage_sock_file_perms relabel_sock_file_perms };

gpg.fc +1 -0
+	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") diff --git a/gpg.te b/gpg.te index f878352..a40ac69 100644 --- a/gpg.te
+++ b/gpg.te

gpg.fc +5 -0
@@ -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 };

gpg.fc +2 -0
+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

Quoted 9 lines
Quoted 4 lines

{ 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) +

It does not seem to actually maintain temporary files. Instead it maintains content in ~/.gnupg. So classifying that type userdom_user_tmp_file is inaccurate in my view

Yes, I only needed gpg_dirmngr_tmp_t for the socket file, it's not used for anything in /tmp. I'll change the declaration. Should I also change the name to something other than _tmp_t?

Quoted 28 lines

gpg.fc manage_lnk_files_pattern(gpg_t, gpg_secret_t, · line 114

Quoted 11 lines

########################################
#
# Local policy

gpg.fc +2 -0
@@ -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)
+stream_connect_pattern(gpg_t, gpg_dirmngr_tmp_t,
 gpg_dirmngr_tmp_t, gpg_dirmngr_t) 
 domtrans_pattern(gpg_t, gpg_agent_exec_t, gpg_agent_t)
+domtrans_pattern(gpg_t, gpg_dirmngr_exec_t, gpg_dirmngr_t)

Users should probably also be allowed to run dirmngr with a domain transition

Quoted 13 lines
gpg.fc +6 -0
 domtrans_pattern(gpg_t, gpg_helper_exec_t, gpg_helper_t)
 
 kernel_read_sysctl(gpg_t)
@@ -344,3 +360,37 @@ optional_policy(`
 optional_policy(`
 	xserver_user_x_domain_template(gpg_pinentry,
 gpg_pinentry_t, gpg_pinentry_tmpfs_t) ')
+
+##############################
+#
+# Dirmngr local policy
+#
+
Quoted 9 lines
Quoted 5 lines
gpg.fc +2 -0
+manage_dirs_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_secret_t)
+manage_sock_files_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)

I do not believe that dirmngr needs to be able to maintain gpg secrets. (I am pretty sure about that)

It does not need access to the secret files, just the config files and .gnupg/{dirmngr-cache,crls}.d/, which are currently labeled gpg_secret_t (also, the .gnupg/ directory itself has this type). I'll improve this.

Quoted 17 lines
Quoted 7 lines
gpg.fc +2 -0
+
+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 })

I do not believe dirmngr maintains anything in /tmp or /var/tmp, everything is maintained in ~/.gnupg

Quoted 3 lines
gpg.fc +2 -0
+
+filetrans_pattern(gpg_dirmngr_t, gpg_secret_t, gpg_dirmngr_tmp_t,

sock_file, "S.dirmngr")

I believe it also maintains ~/.gnupg/crls\.d(/.*)?

Quoted 10 lines

gpg.fc

Quoted 6 lines
gpg.fc +6 -0
+
+userdom_use_user_terminals(gpg_dirmngr_t)
+userdom_search_user_home_dirs(gpg_dirmngr_t)
+
+dev_read_rand(gpg_dirmngr_t)
+dev_read_urand(gpg_dirmngr_t)

I was not able to confirm the above two instead thoug it wants to read crypto sysctls here

On my system, dirmngr fails to start without those.

avc: denied { read } for pid=2126 comm=636F6E6E2066643D30 name="random" dev="devtmpfs" ino=1032 scontext=staff_u:staff_r:gpg_dirmngr_t tcontext=system_u:object_r:random_device_t tclass=chr_file permissive=0

Quoted 5 lines
Quoted 5 lines
gpg.fc +5 -0
+
+auth_use_nsswitch(gpg_dirmngr_t)
+
+corenet_all_recvfrom_unlabeled(gpg_dirmngr_t)
+corenet_all_recvfrom_netlabel(gpg_dirmngr_t)
Quoted 8 lines

gpg.fc

Quoted 5 lines
gpg.fc +5 -0
+corenet_tcp_sendrecv_generic_if(gpg_dirmngr_t)
+corenet_tcp_sendrecv_generic_node(gpg_dirmngr_t)
+
+corenet_sendrecv_all_client_packets(gpg_dirmngr_t)
+corenet_tcp_connect_all_ports(gpg_dirmngr_t)

I think that this may be a bit too much. I suppose it needs to be able to hkp and http ports instead?

The network permissions are in fact a bit wide, it only needs access to hkp, http and ldap. However, the same could be said about gpg_t and gpg_agent_t (I copied the permissions from their policies).

Signature · 1 line
Luis Ressel
#8 lore raw

PATCH 1/2 Policy for gpg's dirmngr

On Mon, Aug 10, 2015 at 03:42:34PM +0200, Luis Ressel wrote:

<snip>

Quoted 9 lines
Quoted 5 lines

It does not seem to actually maintain temporary files. Instead it maintains content in ~/.gnupg. So classifying that type userdom_user_tmp_file is inaccurate in my view

Yes, I only needed gpg_dirmngr_tmp_t for the socket file, it's not used for anything in /tmp. I'll change the declaration. Should I also change the name to something other than _tmp_t?

I would probably change the name of the type but i don' t find the name as important. What i do find more important is that this type is not actually associated with user tmp files but instead with user home files.

Quoted 9 lines
Quoted 4 lines

I do not believe that dirmngr needs to be able to maintain gpg secrets. (I am pretty sure about that)

It does not need access to the secret files, just the config files and .gnupg/{dirmngr-cache,crls}.d/, which are currently labeled gpg_secret_t (also, the .gnupg/ directory itself has this type). I'll improve this.

I wasnt aware of ~/.gnupg/dirmngr-cache.d .. but yes that and crls.d would need to be associated with the dirmngr type and not the gpg secret type in my view

Yes it needs to traverse ~/.gnupg obviously and add/del ~/.gnupg directory entries but ideally it should not need any access to any file in ~/.gnupg other than its own (we dont want it to be able to access the keys for example)

Quoted 5 lines
Quoted 4 lines

I was not able to confirm the above two instead thoug it wants to read crypto sysctls here

Quoted 7 lines

On my system, dirmngr fails to start without those.

avc: denied { read } for pid=2126 comm=636F6E6E2066643D30 name="random" dev="devtmpfs" ino=1032 scontext=staff_u:staff_r:gpg_dirmngr_t tcontext=system_u:object_r:random_device_t tclass=chr_file permissive=0

Assuming 636F6E6E2066643D30 translates to "dirmngr", then i guess it is needed. I havent encountered this on my implementation.

Quoted 8 lines
Quoted 3 lines

I think that this may be a bit too much. I suppose it needs to be able to hkp and http ports instead?

The network permissions are in fact a bit wide, it only needs access to hkp, http and ldap. However, the same could be said about gpg_t and gpg_agent_t (I copied the permissions from their policies).

The existing gpg policy is not optimal and i wouldnt take that as an example. In fact I would revisit the whole gpg suite because gpg agent doesnt need access to gpg secrets either. The main goal of this policy, in my view, is to ensure integrity of the keys.

Quoted 6 lines
Signature · 5 lines
Luis Ressel
_______________________________________________
refpolicy mailing list
refpolicy at oss.tresys.com
http://oss.tresys.com/mailman/listinfo/refpolicy
Signature · 11 lines
02DFF788
4D30 903A 1CF3 B756 FB48  1514 3148 83A2 02DF F788
http://keys.gnupg.net/pks/lookup?op=vindex&search=0x314883A202DFF788
Dominick Grift
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 648 bytes
Desc: not available
Url : http://oss.tresys.com/pipermail/refpolicy/attachments/20150810/2e8baf24/attachment-0001.bin 
#9 lore raw

PATCH 1/2 Policy for gpg's dirmngr

Hello,

Quoted 1 line · Dominick Grift

On Mon, Aug 10, 2015 at 03:42:34PM +0200, Luis Ressel wrote:

<snip>

Quoted 10 lines
Quoted 8 lines

On my system, dirmngr fails to start without those.

avc: denied { read } for pid=2126 comm=636F6E6E2066643D30 name="random" dev="devtmpfs" ino=1032 scontext=staff_u:staff_r:gpg_dirmngr_t tcontext=system_u:object_r:random_device_t tclass=chr_file permissive=0

Assuming 636F6E6E2066643D30 translates to "dirmngr", then i guess it is needed. I havent encountered this on my implementation.

To decode this string, several ways exist [1], for example in Python:

    python -c 'import binascii;

print(binascii.unhexlify("636F6E6E2066643D30"))'

This gives "conn fd=0", which is not directly "dirmngr". But in fact dirmngr seems to spawn a thread with this name [2] so this process is really dirmngr. Moreover in dirmngr/ks-engine-hkp.c in gnupg code, function select_random_host seems to need a random number generator to choose an host, which could explain the access to /dev/random (I have not checked deeply the code to understand how this function gets called).

--
Nicolas Iooss

[1]
http://blog.siphos.be/2014/03/decoding-the-hex-coded-path-information-in-avc-denials/
[2]
https://github.com/unofficial-mirrors/gnupg/blob/gnupg-2.1.3/dirmngr/dirmngr.c#L2048-L2059

#10 lore raw

PATCH 1/2 Policy for gpg's dirmngr

Quoted 14 lines · Nicolas Iooss

Hello,

Quoted 1 line · Dominick Grift

On Mon, Aug 10, 2015 at 03:42:34PM +0200, Luis Ressel wrote:

<snip>

Quoted 9 lines
Quoted 8 lines

On my system, dirmngr fails to start without those.

avc: denied { read } for pid=2126 comm=636F6E6E2066643D30 name="random" dev="devtmpfs" ino=1032 scontext=staff_u:staff_r:gpg_dirmngr_t tcontext=system_u:object_r:random_device_t tclass=chr_file permissive=0

Quoted 6 lines
Quoted 1 line

Assuming 636F6E6E2066643D30 translates to "dirmngr", then i guess it is needed. I havent encountered this on my implementation.

To decode this string, several ways exist [1], for example in Python:

    python -c 'import binascii;

print(binascii.unhexlify("636F6E6E2066643D30"))'

Thanks, yes. reading the avc denial with ausearch -i will also interpret it.

Quoted 21 lines

This gives "conn fd=0", which is not directly "dirmngr". But in fact dirmngr seems to spawn a thread with this name [2] so this process is really dirmngr. Moreover in dirmngr/ks-engine-hkp.c in gnupg code, function select_random_host seems to need a random number generator to choose an host, which could explain the access to /dev/random (I have not checked deeply the code to understand how this function gets called).

--
Nicolas Iooss

[1]
http://blog.siphos.be/2014/03/decoding-the-hex-coded-path-information-in-avc-denials/
[2]
https://github.com/unofficial-mirrors/gnupg/blob/gnupg-2.1.3/dirmngr/dirmngr.c#L2048-L2059

_______________________________________________
refpolicy mailing list
refpolicy at oss.tresys.com
http://oss.tresys.com/mailman/listinfo/refpolicy

Signature · 11 lines
02DFF788
4D30 903A 1CF3 B756 FB48  1514 3148 83A2 02DF F788
http://keys.gnupg.net/pks/lookup?op=vindex&search=0x314883A202DFF788
Dominick Grift
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 648 bytes
Desc: not available
Url : http://oss.tresys.com/pipermail/refpolicy/attachments/20150811/4023282c/attachment.bin