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