rpms/pam/devel pam-1.0.0-selinux-env-params.patch, NONE, 1.1 pam.spec, 1.178, 1.179

Tomáš Mráz (tmraz) fedora-extras-commits at redhat.com
Mon May 19 16:55:57 UTC 2008


Author: tmraz

Update of /cvs/pkgs/rpms/pam/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv3637

Modified Files:
	pam.spec 
Added Files:
	pam-1.0.0-selinux-env-params.patch 
Log Message:
* Mon May 19 2008 Tomas Mraz <tmraz at redhat.com> 1.0.1-3
- pam_selinux: add env_params option which will be used by OpenSSH


pam-1.0.0-selinux-env-params.patch:

--- NEW FILE pam-1.0.0-selinux-env-params.patch ---
Index: modules/pam_selinux/pam_selinux.8.xml
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/modules/pam_selinux/pam_selinux.8.xml,v
retrieving revision 1.2
diff -u -p -r1.2 pam_selinux.8.xml
--- modules/pam_selinux/pam_selinux.8.xml	15 Jun 2007 10:17:22 -0000	1.2
+++ modules/pam_selinux/pam_selinux.8.xml	19 May 2008 15:44:08 -0000
@@ -37,6 +37,9 @@
 	select_context
       </arg>
       <arg choice="opt">
+	env_params
+      </arg>
+      <arg choice="opt">
 	use_current_range
       </arg>
     </cmdsynopsis>
@@ -137,12 +140,30 @@
       </varlistentry>
       <varlistentry>
         <term>
+          <option>env_params</option>
+        </term>
+        <listitem>
+          <para>
+            Attempt to obtain a custom security context role from PAM environment.
+            If MLS is on obtain also sensitivity level. This option and the
+            select_context option are mutually exclusive. The respective PAM
+            environment variables are <emphasis>SELINUX_ROLE_REQUESTED</emphasis>,
+            <emphasis>SELINUX_LEVEL_REQUESTED</emphasis>, and
+            <emphasis>SELINUX_USE_CURRENT_RANGE</emphasis>. The first two variables
+            are self describing and the last one if set to 1 makes the PAM module behave as
+            if the use_current_range was specified on the command line of the module.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
           <option>use_current_range</option>
         </term>
         <listitem>
           <para>
-            Use the sensitivity range of the process for the user context.
-            This option and the select_context option are mutually exclusive.
+            Use the sensitivity level of the current process for the user context
+            instead of the default level. Also supresses asking of the
+            sensitivity level from the user or obtaining it from PAM environment.
           </para>
         </listitem>
       </varlistentry>
Index: modules/pam_selinux/pam_selinux.c
===================================================================
RCS file: /cvsroot/pam/Linux-PAM/modules/pam_selinux/pam_selinux.c,v
retrieving revision 1.16
diff -u -p -r1.16 pam_selinux.c
--- modules/pam_selinux/pam_selinux.c	22 Apr 2008 19:21:37 -0000	1.16
+++ modules/pam_selinux/pam_selinux.c	19 May 2008 15:44:08 -0000
@@ -2,8 +2,9 @@
  * A module for Linux-PAM that will set the default security context after login
  * via PAM.
  *
- * Copyright (c) 2003 Red Hat, Inc.
+ * Copyright (c) 2003-2008 Red Hat, Inc.
  * Written by Dan Walsh <dwalsh at redhat.com>
+ * Additional improvements by Tomas Mraz <tmraz at redhat.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -138,15 +139,22 @@ send_text (pam_handle_t *pamh, const cha
  */
 static int
 query_response (pam_handle_t *pamh, const char *text, const char *def,
-		char **responses, int debug)
+		char **response, int debug)
 {
   int rc;
   if (def) 
-    rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, responses, "%s [%s] ", text, def);
+    rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s [%s] ", text, def);
   else
-    rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, responses, "%s ", text);
-  if (debug)
-    pam_syslog(pamh, LOG_NOTICE, "%s %s", text, responses[0]);
+    rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s ", text);
+
+  if (*response == NULL) {
+    rc = PAM_CONV_ERR;
+  }
+  
+  if (rc != PAM_SUCCESS) {
+    pam_syslog(pamh, LOG_WARNING, "No response to query: %s", text);
+  } else  if (debug)
+    pam_syslog(pamh, LOG_NOTICE, "%s %s", text, *response);
   return rc;
 }
 
@@ -157,13 +165,15 @@ manual_context (pam_handle_t *pamh, cons
   context_t new_context;
   int mls_enabled = is_selinux_mls_enabled();
   char *type=NULL;
-  char *responses=NULL;
+  char *response=NULL;
 
   while (1) {
-    query_response(pamh,
-		   _("Would you like to enter a security context? [N] "), NULL, 
-		   &responses,debug);
-    if ((responses[0] == 'y') || (responses[0] == 'Y'))
+    if (query_response(pamh,
+		   _("Would you like to enter a security context? [N] "), NULL,
+		   &response, debug) != PAM_SUCCESS)
+	return NULL;
+
+    if ((response[0] == 'y') || (response[0] == 'Y'))
       {
 	if (mls_enabled)
 	  new_context = context_new ("user:role:type:level");
@@ -176,26 +186,29 @@ manual_context (pam_handle_t *pamh, cons
 	if (context_user_set (new_context, user))
               goto fail_set;
 
-	_pam_drop(responses);
+	_pam_drop(response);
 	/* Allow the user to enter each field of the context individually */
-	query_response(pamh,_("role:"), NULL, &responses,debug);
-	if (responses[0] != '\0') {
-	   if (context_role_set (new_context, responses)) 
+	if (query_response(pamh, _("role:"), NULL, &response, debug) == PAM_SUCCESS &&
+	    response[0] != '\0') {
+	   if (context_role_set (new_context, response)) 
               goto fail_set;
-	   if (get_default_type(responses, &type)) 
+	   if (get_default_type(response, &type)) 
               goto fail_set;
 	   if (context_type_set (new_context, type)) 
               goto fail_set;
 	}
-	_pam_drop(responses);
+	_pam_drop(response);
+
 	if (mls_enabled)
 	  {
-	    query_response(pamh,_("level:"), NULL, &responses,debug);
-	    if (responses[0] != '\0') {
-	      if (context_range_set (new_context, responses))
+	    if (query_response(pamh, _("level:"), NULL, &response, debug) == PAM_SUCCESS &&
+		response[0] != '\0') {
+	      if (context_range_set (new_context, response))
 		goto fail_set;
 	    }
+	    _pam_drop(response);
 	  }
+
 	/* Get the string value of the context and see if it is valid. */
 	if (!security_check_context(context_str(new_context))) {
 	  newcon = strdup(context_str(new_context));
@@ -204,16 +217,17 @@ manual_context (pam_handle_t *pamh, cons
 	}
 	else
 	  send_text(pamh,_("Not a valid security context"),debug);
-	context_free (new_context);
+
+        context_free (new_context);
       }
     else {
-      _pam_drop(responses);
+      _pam_drop(response);
       return NULL;
     }
   } /* end while */
  fail_set:
   free(type);
-  _pam_drop(responses);
+  _pam_drop(response);
   context_free (new_context);
   return NULL;
 }
@@ -239,69 +253,91 @@ static int mls_range_allowed(pam_handle_
 }
 
 static security_context_t
-config_context (pam_handle_t *pamh, security_context_t puser_context, int debug)
+config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_current_range, int debug)
 {
   security_context_t newcon=NULL;
   context_t new_context;
   int mls_enabled = is_selinux_mls_enabled();
-  char *responses=NULL;
+  char *response=NULL;
   char *type=NULL;
   char resp_val = 0;
 
-  pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), puser_context);
+  pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), defaultcon);
 
   while (1) {
-    query_response(pamh,
+    if (query_response(pamh,
 		   _("Would you like to enter a different role or level?"), "n", 
-		   &responses,debug);
-
-    resp_val = responses[0];
-    _pam_drop(responses);
+		   &response, debug) == PAM_SUCCESS) {
+	resp_val = response[0];
+	_pam_drop(response);
+    } else {
+	resp_val = 'N';
+    }
     if ((resp_val == 'y') || (resp_val == 'Y'))
       {
-        new_context = context_new(puser_context);
-        
+        if ((new_context = context_new(defaultcon)) == NULL)
+    	    goto fail_set;
+
 	/* Allow the user to enter role and level individually */
-	query_response(pamh,_("role:"), context_role_get(new_context), 
-		       &responses, debug);
-	if (responses[0]) {
-	  if (get_default_type(responses, &type)) {
-	    pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), responses);
-	    _pam_drop(responses);
+	if (query_response(pamh, _("role:"), context_role_get(new_context), 
+		       &response, debug) == PAM_SUCCESS && response[0]) {
+	  if (get_default_type(response, &type)) {
+	    pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), response);
+	    _pam_drop(response);
 	    continue;
 	  } else {
-	    if (context_role_set(new_context, responses)) 
+	    if (context_role_set(new_context, response)) 
 	      goto fail_set;
 	    if (context_type_set (new_context, type))
 	      goto fail_set;
 	  } 
 	}
-	_pam_drop(responses);
+	_pam_drop(response);
+
 	if (mls_enabled)
 	  {
-	    query_response(pamh,_("level:"), context_range_get(new_context), 
-			   &responses, debug);
-	    if (responses[0]) {
-	      if (context_range_set(new_context, responses))
-		goto fail_set;
+	    if (use_current_range) {
+	        security_context_t mycon = NULL;
+	        context_t my_context;
+
+		if (getcon(&mycon) != 0)
+		    goto fail_set;
+    		my_context = context_new(mycon);
+	        if (my_context == NULL) {
+    		    freecon(mycon);
+		    goto fail_set;
+		}
+		freecon(mycon);
+		if (context_range_set(new_context, context_range_get(my_context))) {
+		    context_free(my_context);
+		    goto fail_set;
+		}
+		context_free(my_context);
+	    } else if (query_response(pamh, _("level:"), context_range_get(new_context), 
+			   &response, debug) == PAM_SUCCESS && response[0]) {
+		if (context_range_set(new_context, response))
+		    goto fail_set;
 	    } 
-	    _pam_drop(responses);
+	    _pam_drop(response);
 	  }
+
 	if (debug)
 	  pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", context_str(new_context));
 
         /* Get the string value of the context and see if it is valid. */
         if (!security_check_context(context_str(new_context))) {
 	  newcon = strdup(context_str(new_context));
-	  context_free (new_context);
+	  if (newcon == NULL)
+	    goto fail_set;
+	  context_free(new_context);
 
           /* we have to check that this user is allowed to go into the
              range they have specified ... role is tied to an seuser, so that'll
              be checked at setexeccon time */
-          if (mls_enabled && !mls_range_allowed(pamh, puser_context, newcon, debug)) {
-	    pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", puser_context, newcon);
+          if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) {
+	    pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon);
 
-    	    send_audit_message(pamh, 0, puser_context, newcon);
+    	    send_audit_message(pamh, 0, defaultcon, newcon);
 
 	    free(newcon);
             goto fail_range;
@@ -309,26 +345,120 @@ config_context (pam_handle_t *pamh, secu
 	  return newcon;
 	}
 	else {
-	  send_audit_message(pamh, 0, puser_context, context_str(new_context));
+	  send_audit_message(pamh, 0, defaultcon, context_str(new_context));
 	  send_text(pamh,_("Not a valid security context"),debug);
 	}
         context_free(new_context); /* next time around allocates another */
       }
     else
-      return strdup(puser_context);
+      return strdup(defaultcon);
   } /* end while */
 
   return NULL;
 
  fail_set:
   free(type);
-  _pam_drop(responses);
+  _pam_drop(response);
   context_free (new_context);
-  send_audit_message(pamh, 0, puser_context, NULL);
+  send_audit_message(pamh, 0, defaultcon, NULL);
  fail_range:
   return NULL;  
 }
 
+static security_context_t
+context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_params, int use_current_range, int debug)
+{
+  security_context_t newcon = NULL;
+  context_t new_context;
+  context_t my_context = NULL;
+  int mls_enabled = is_selinux_mls_enabled();
+  const char *env = NULL;
+  char *type = NULL;
+
+  if ((new_context = context_new(defaultcon)) == NULL)
+    goto fail_set;
+
+  if (env_params && (env = pam_getenv(pamh, "SELINUX_ROLE_REQUESTED")) != NULL && env[0] != '\0') {
+    if (debug)
+	pam_syslog(pamh, LOG_NOTICE, "Requested role: %s", env);
+
+    if (get_default_type(env, &type)) {
+	pam_syslog(pamh, LOG_NOTICE, "No default type for role %s", env);
+	goto fail_set;
+    } else {
+	if (context_role_set(new_context, env)) 
+	    goto fail_set;
+	if (context_type_set(new_context, type))
+	    goto fail_set;
+    }
+  }
+
+  if (mls_enabled) {
+    if ((env = pam_getenv(pamh, "SELINUX_USE_CURRENT_RANGE")) != NULL && env[0] == '1') {
+        if (debug)
+	    pam_syslog(pamh, LOG_NOTICE, "SELINUX_USE_CURRENT_RANGE is set");
+	use_current_range = 1;
+    }
+
+    if (use_current_range) {
+        security_context_t mycon = NULL;
+
+	if (getcon(&mycon) != 0)
+	    goto fail_set;
+        my_context = context_new(mycon);
+        if (my_context == NULL) {
+            freecon(mycon);
+	    goto fail_set;
+	}
+	freecon(mycon);
+	env = context_range_get(my_context);
+    } else {
+        env = pam_getenv(pamh, "SELINUX_LEVEL_REQUESTED");
+    }
+
+    if (env != NULL && env[0] != '\0') {
+        if (debug)
+	    pam_syslog(pamh, LOG_NOTICE, "Requested level: %s", env);
+	if (context_range_set(new_context, env))
+	    goto fail_set;
+    }
+  }
+
+  newcon = strdup(context_str(new_context));
+  if (newcon == NULL)
+    goto fail_set;
+
+  if (debug)
+    pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", newcon);
+  
+  /* Get the string value of the context and see if it is valid. */
+  if (security_check_context(newcon)) {
+    pam_syslog(pamh, LOG_NOTICE, "Not a valid security context %s", newcon);
+    send_audit_message(pamh, 0, defaultcon, newcon);
+    freecon(newcon);
+    newcon = NULL;
+
+    goto fail_set;
+  }
+
+  /* we have to check that this user is allowed to go into the
+     range they have specified ... role is tied to an seuser, so that'll
+     be checked at setexeccon time */
+  if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) {
+    pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon);
+    send_audit_message(pamh, 0, defaultcon, newcon);
+    freecon(newcon);
+    newcon = NULL;
+  }
+
+ fail_set:
+  free(type);
+  context_free(my_context);
+  context_free(new_context);
+  send_audit_message(pamh, 0, defaultcon, NULL);
+  return newcon;
+}
+
 static void
 security_restorelabel_tty(const pam_handle_t *pamh,
 			  const char *tty, security_context_t context)
@@ -439,13 +569,14 @@ PAM_EXTERN int
 pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
 		    int argc, const char **argv)
 {
-  int i, debug = 0, ttys=1, has_tty=isatty(0);
+  int i, debug = 0, ttys=1;
   int verbose=0, close_session=0;
   int select_context = 0;
   int use_current_range = 0;
   int ret = 0;
   security_context_t* contextlist = NULL;
   int num_contexts = 0;
+  int env_params = 0;
   const char *username = NULL;
   const void *tty = NULL;
   char *seuser=NULL;
@@ -472,13 +603,16 @@ pam_sm_open_session(pam_handle_t *pamh, 
     if (strcmp(argv[i], "use_current_range") == 0) {
       use_current_range = 1;
     }
+    if (strcmp(argv[i], "env_params") == 0) {
+      env_params = 1;
+    }
   }
   
   if (debug)
     pam_syslog(pamh, LOG_NOTICE, "Open Session");
 
-  if (select_context && use_current_range) {
-    pam_syslog(pamh, LOG_ERR, "select_context cannot be used with use_current_range");
+  if (select_context && env_params) {
+    pam_syslog(pamh, LOG_ERR, "select_context cannot be used with env_params");
     select_context = 0;
   }
 
@@ -510,12 +644,17 @@ pam_sm_open_session(pam_handle_t *pamh, 
     freeconary(contextlist);
     if (default_user_context == NULL) {
 	  pam_syslog(pamh, LOG_ERR, "Out of memory");
-          return PAM_AUTH_ERR;
+          return PAM_BUF_ERR;
     }
+
     user_context = default_user_context;
-    if (select_context && has_tty) {
-      user_context = config_context(pamh, default_user_context, debug);
-      if (user_context == NULL) {
+    if (select_context) {
+        user_context = config_context(pamh, default_user_context, use_current_range, debug);
+    } else if (env_params || use_current_range) {
+        user_context = context_from_env(pamh, default_user_context, env_params, use_current_range, debug);
+    }
+
+    if (user_context == NULL) {
 	freecon(default_user_context);
 	pam_syslog(pamh, LOG_ERR, "Unable to get valid context for %s",
 		    username);
@@ -524,11 +663,9 @@ pam_sm_open_session(pam_handle_t *pamh, 
           return PAM_AUTH_ERR;
         else
           return PAM_SUCCESS;
-      }
-    } 
+    }
   }
   else { 
-    if (has_tty) {
       user_context = manual_context(pamh,seuser,debug);
       if (user_context == NULL) {
 	pam_syslog (pamh, LOG_ERR, "Unable to get valid context for %s",
@@ -538,59 +675,6 @@ pam_sm_open_session(pam_handle_t *pamh, 
         else
           return PAM_SUCCESS;
       }
-    } else {
-        pam_syslog (pamh, LOG_ERR,
-		    "Unable to get valid context for %s, No valid tty",
-		    username);
-        if (security_getenforce() == 1)
-          return PAM_AUTH_ERR;
-        else
-          return PAM_SUCCESS;
-    }
-  }
-
-  if (use_current_range && is_selinux_mls_enabled()) {
-    security_context_t process_context=NULL;    
-    if (getcon(&process_context) == 0) {
-      context_t pcon, ucon;
-      char *process_level=NULL;
-      security_context_t orig_context;
-      
-      if (user_context)
-        orig_context = user_context;
-      else
-        orig_context = default_user_context;
-
-      pcon = context_new(process_context);
-      freecon(process_context);
-      process_level = strdup(context_range_get(pcon));
-      context_free(pcon);
-
-      if (debug)
-        pam_syslog (pamh, LOG_DEBUG, "process level=%s", process_level);
-
-      ucon = context_new(orig_context);
-
-      context_range_set(ucon, process_level);
-      free(process_level);
-
-      if (!mls_range_allowed(pamh, orig_context, context_str(ucon), debug)) {
-	send_text(pamh, _("Requested MLS level not in permitted range"), debug);
-	/* even if default_user_context is NULL audit that anyway */
-	send_audit_message(pamh, 0, default_user_context, context_str(ucon));
-	context_free(ucon);
-	return PAM_AUTH_ERR;
-      }
-
-      if (debug)
-        pam_syslog (pamh, LOG_DEBUG, "adjusted context=%s", context_str(ucon));
-
-      /* replace the user context with the level adjusted one */
-      freecon(user_context);
-      user_context = strdup(context_str(ucon));
-
-      context_free(ucon);
-    }
   }
 
   if (getexeccon(&prev_user_context)<0) {
@@ -613,7 +697,7 @@ pam_sm_open_session(pam_handle_t *pamh, 
       }
     }
   }
-  if(ttys && tty ) {
+  if (ttys && tty) {
     ttyn=strdup(tty);
     ttyn_context=security_label_tty(pamh,ttyn,user_context);
   }


Index: pam.spec
===================================================================
RCS file: /cvs/pkgs/rpms/pam/devel/pam.spec,v
retrieving revision 1.178
retrieving revision 1.179
diff -u -r1.178 -r1.179
--- pam.spec	22 Apr 2008 19:48:10 -0000	1.178
+++ pam.spec	19 May 2008 16:55:13 -0000	1.179
@@ -5,7 +5,7 @@
 Summary: A security tool which provides authentication for applications
 Name: pam
 Version: 1.0.1
-Release: 2%{?dist}
+Release: 3%{?dist}
 # The library is BSD licensed with option to relicense as GPLv2+ - this option is redundant
 # as the BSD license allows that anyway. pam_timestamp and pam_console modules are GPLv2+,
 # pam_rhosts_auth module is BSD with advertising
@@ -27,6 +27,7 @@
 Patch4:  pam-0.99.8.1-dbpam.patch
 Patch10: pam-1.0.0-sepermit-screensaver.patch
 Patch11: pam-1.0.1-selinux-restore-execcon.patch
+Patch12: pam-1.0.0-selinux-env-params.patch
 Patch21: pam-0.99.10.0-unix-audit-failed.patch
 Patch31: pam-0.99.3.0-cracklib-try-first-pass.patch
 Patch32: pam-0.99.3.0-tally-fail-close.patch
@@ -104,6 +105,7 @@
 %patch4 -p1 -b .dbpam
 %patch10 -p1 -b .screensaver
 %patch11 -p1 -b .restore-execcon
+%patch12 -p0 -b .env-params
 %patch21 -p1 -b .audit-failed
 %patch31 -p1 -b .try-first-pass
 %patch32 -p1 -b .fail-close
@@ -376,6 +378,9 @@
 %doc doc/adg/*.txt doc/adg/html
 
 %changelog
+* Mon May 19 2008 Tomas Mraz <tmraz at redhat.com> 1.0.1-3
+- pam_selinux: add env_params option which will be used by OpenSSH
+
 * Tue Apr 22 2008 Tomas Mraz <tmraz at redhat.com> 1.0.1-2
 - pam_selinux: restore execcon properly (#443667)
 




More information about the fedora-extras-commits mailing list