Ejemplo n.º 1
0
 bool PamHandle::openSession() {
     m_result = pam_open_session(m_handle, m_silent);
     if (m_result != PAM_SUCCESS) {
         qWarning() << "[PAM] openSession:" << pam_strerror(m_handle, m_result);
     }
     return m_result == PAM_SUCCESS;
 }
Ejemplo n.º 2
0
void Authenticator::open_session(void) {
    switch((last_result=pam_setcred(pam_handle, PAM_ESTABLISH_CRED))) {
    default:
    case PAM_CRED_ERR:
    case PAM_CRED_UNAVAIL:
        _end();
        throw Exception(pam_handle, "pam_setcred()", last_result);

    case PAM_CRED_EXPIRED:
    case PAM_USER_UNKNOWN:
        throw Cred_Exception(pam_handle, "pam_setcred()", last_result);

    case PAM_SUCCESS:
        break;
    }

    switch((last_result=pam_open_session(pam_handle, 0))) {
    // The documentation and implementation of Linux PAM differs:
    // PAM_SESSION_ERROR is described in the documentation but
    // don't exists in the actual implementation. This issue needs
    // to be fixes at some point.

    default:
        //case PAM_SESSION_ERROR:
        pam_setcred(pam_handle, PAM_DELETE_CRED);
        _end();
        throw Exception(pam_handle, "pam_open_session()", last_result);

    case PAM_SUCCESS:
        break;
    };
    return;
}
Ejemplo n.º 3
0
Archivo: xlsh.c Proyecto: drwilly/xlsh
int xlsh_session_open(const char* service, const char* user,
                      pam_handle_t** handle)
{
  struct pam_conv conv = { xlsh_session_conv, NULL };
  pam_handle_t* pam_handle;

  if(pam_start(service, user, &conv, &pam_handle) != PAM_SUCCESS)
    return XLSH_ERROR;

  if(xlsh_X)
    pam_set_item(pam_handle, PAM_TTY, XLSH_XTTY);
  else
    pam_set_item(pam_handle, PAM_TTY, ttyname(0));

  if(pam_authenticate(pam_handle, 0) != PAM_SUCCESS) {
    pam_end(pam_handle, 0);
    return XLSH_ERROR;
  }
  if(pam_acct_mgmt(pam_handle, 0) != PAM_SUCCESS) {
    pam_end(pam_handle, 0);
    return XLSH_ERROR;
  }
  if(pam_setcred(pam_handle, PAM_ESTABLISH_CRED) != PAM_SUCCESS) {
    pam_end(pam_handle, 0);
    return XLSH_ERROR;
  }
  if(pam_open_session(pam_handle, 0) != PAM_SUCCESS) {
    pam_setcred(pam_handle, PAM_DELETE_CRED);
    pam_end(pam_handle, 0);
    return XLSH_ERROR;
  }

  *handle = pam_handle;
  return XLSH_EOK;
}
Ejemplo n.º 4
0
static enum pamtest_err run_test_case(pam_handle_t *ph,
				      struct pam_testcase *tc)
{
	switch (tc->pam_operation) {
	case PAMTEST_AUTHENTICATE:
		tc->op_rv = pam_authenticate(ph, tc->flags);
		return PAMTEST_ERR_OK;
	case PAMTEST_SETCRED:
		tc->op_rv = pam_setcred(ph, tc->flags);
		return PAMTEST_ERR_OK;
	case PAMTEST_ACCOUNT:
		tc->op_rv = pam_acct_mgmt(ph, tc->flags);
		return PAMTEST_ERR_OK;
	case PAMTEST_OPEN_SESSION:
		tc->op_rv = pam_open_session(ph, tc->flags);
		return PAMTEST_ERR_OK;
	case PAMTEST_CLOSE_SESSION:
		tc->op_rv = pam_close_session(ph, tc->flags);
		return PAMTEST_ERR_OK;
	case PAMTEST_CHAUTHTOK:
		tc->op_rv = pam_chauthtok(ph, tc->flags);
		return PAMTEST_ERR_OK;
	case PAMTEST_GETENVLIST:
		tc->case_out.envlist = pam_getenvlist(ph);
		return PAMTEST_ERR_OK;
	case PAMTEST_KEEPHANDLE:
		tc->case_out.ph = ph;
		return PAMTEST_ERR_KEEPHANDLE;
	default:
		return PAMTEST_ERR_OP;
	}

	return PAMTEST_ERR_OP;
}
Ejemplo n.º 5
0
static int
setup_pam(struct weston_launch *wl)
{
	int err;

	wl->pc.conv = pam_conversation_fn;
	wl->pc.appdata_ptr = wl;

	err = pam_start("login", wl->pw->pw_name, &wl->pc, &wl->ph);
	if (err != PAM_SUCCESS) {
		fprintf(stderr, "failed to start pam transaction: %d: %s\n",
			err, pam_strerror(wl->ph, err));
		return -1;
	}

	err = pam_set_item(wl->ph, PAM_TTY, ttyname(wl->tty));
	if (err != PAM_SUCCESS) {
		fprintf(stderr, "failed to set PAM_TTY item: %d: %s\n",
			err, pam_strerror(wl->ph, err));
		return -1;
	}

	err = pam_open_session(wl->ph, 0);
	if (err != PAM_SUCCESS) {
		fprintf(stderr, "failed to open pam session: %d: %s\n",
			err, pam_strerror(wl->ph, err));
		return -1;
	}

	return 0;
}
Ejemplo n.º 6
0
bool XProcess::pam_startSession(){
  //This should only be run if pam_checkPW was successful
  int ret = pam_open_session(pamh,0);
  bool ok = FALSE;
  if(ret == PAM_SUCCESS){ ok = TRUE; }
  else{ pam_logFailure(ret); }
  
  return ok;
}
Ejemplo n.º 7
0
bool PAMAuthenticator::authenticate(void)
{
	pam_conv c;
	c.conv        = PAMAuthenticator::conv;
	c.appdata_ptr = this;

	int res = pam_start("repwatchproxy", 0, &c, &this->m_ph);
	if (res == PAM_SUCCESS) {
		res = pam_set_item(this->m_ph, PAM_RUSER, this->m_user.constData());
		if (res != PAM_SUCCESS) {
			goto getout;
		}

		res = pam_set_item(this->m_ph, PAM_RHOST, this->m_host.constData());
		if (res != PAM_SUCCESS) {
			goto getout;
		}

		res = pam_authenticate(this->m_ph, 0);
		if (res != PAM_SUCCESS) {
			goto getout;
		}

		res = pam_acct_mgmt(this->m_ph, 0);
		if (PAM_NEW_AUTHTOK_REQD == res) {
			res = pam_chauthtok(this->m_ph, PAM_CHANGE_EXPIRED_AUTHTOK);
		}

		if (res != PAM_SUCCESS) {
			goto getout;
		}

		res = pam_setcred(this->m_ph, PAM_ESTABLISH_CRED);
		if (res != PAM_SUCCESS) {
			goto getout;
		}

		res = pam_open_session(this->m_ph, 0);
		if (res != PAM_SUCCESS) {
			goto getout;
		}

		return true;

getout:
		qWarning("%s: %s", Q_FUNC_INFO, pam_strerror(this->m_ph, res));
		pam_end(this->m_ph, res);
	}
	else {
		qCritical("PAM initialization failed");
	}

	this->m_ph = 0;
	return false;
}
Ejemplo n.º 8
0
int main(int argc, char *argv[]) {
	char **args;
	pam_handle_t *pamh=NULL;
	int retval;
	struct passwd *pw;


	if (argc==1){
		return -1;
	}
	pw=getpwuid(getuid());


	retval = pam_start(PAM_NAME, pw->pw_name, &conv, &pamh);

	if (retval == PAM_SUCCESS)
		retval = pam_acct_mgmt(pamh, 0);	/* permitted access? */
	else
		fprintf(stderr,"%s: pam_start failed\n",PAM_NAME);
	
	if (retval == PAM_SUCCESS)
		retval = pam_open_session(pamh, 0);
	else
		fprintf(stderr,"%s: pam_acct failed\n",PAM_NAME);
		
	if (retval != PAM_SUCCESS)
		fprintf(stderr,"%s: pam_acct failed\n",PAM_NAME);
	

	if (pam_end(pamh,retval) != PAM_SUCCESS) {	/* close Linux-PAM */
		pamh = NULL;
		fprintf(stderr, "check_user: failed to release authenticator\n");
		exit(1);
	}

	if (retval != PAM_SUCCESS)
		return 99;

#ifdef LOG
	log=fopen(LOG,"a");
	if (log!=NULL){
		for (i=0;i<argc;i++){
			fprintf(log,"%s ",argv[i]);
		}
		fprintf(log,"\n");
		fclose(log);
	}
#endif

	args = &argv[1];

	execvp(args[0], args);
}
Ejemplo n.º 9
0
void context::open_session()
{
    _M_code = setcred();
    if(errc(_M_code) != errc::success) throw cred_error(_M_pamh, _M_code);

    _M_code = pam_open_session(_M_pamh, 0);
    if(errc(_M_code) != errc::success)
    {
        rmcred();
        throw session_error(_M_pamh, _M_code);
    }
}
Ejemplo n.º 10
0
Archivo: pam_ses.c Proyecto: IFCA/slurm
int
pam_setup (char *user, char *host)
{
	/*
	 * Any application using PAM must provide a conversion function, which
	 * is used for direct communication between a loaded module and the
	 * application. In this case, SLURM does need a communication mechanism,
	 * so the default (or null) conversation function may be used.
	 */
	struct pam_conv conv = {misc_conv, NULL};
        int             rc = 0;

	if (!conf->use_pam)
		return SLURM_SUCCESS;
	/*
	 * SLURM uses PAM to obtain resource limits established by the system
	 * administrator. PAM's session management library is responsible for
	 * handling resource limits. When a PAM session is opened on behalf of
	 * a user, the limits imposed by the sys admin are picked up. Opening
	 * a PAM session requires a PAM handle, which is obtained when the PAM
	 * interface is initialized. (PAM handles are required with essentially
	 * all PAM calls.) It's also necessary to have the users PAM credentials
	 * to open a user session.
 	 */
        if ((rc = pam_start (SLURM_SERVICE_PAM, user, &conv, &pam_h))
			!= PAM_SUCCESS) {
                error ("pam_start: %s", pam_strerror(pam_h, rc));
                return SLURM_ERROR;
        } else if ((rc = pam_set_item (pam_h, PAM_USER, user))
			!= PAM_SUCCESS) {
                error ("pam_set_item USER: %s", pam_strerror(pam_h, rc));
                return SLURM_ERROR;
        } else if ((rc = pam_set_item (pam_h, PAM_RUSER, user))
			!= PAM_SUCCESS) {
                error ("pam_set_item RUSER: %s", pam_strerror(pam_h, rc));
                return SLURM_ERROR;
        } else if ((rc = pam_set_item (pam_h, PAM_RHOST, host))
			!= PAM_SUCCESS) {
                error ("pam_set_item HOST: %s", pam_strerror(pam_h, rc));
              return SLURM_ERROR;
        } else if ((rc = pam_setcred (pam_h, PAM_ESTABLISH_CRED))
			!= PAM_SUCCESS) {
                error ("pam_setcred: %s", pam_strerror(pam_h, rc));
                return SLURM_ERROR;
        } else if ((rc = pam_open_session (pam_h, 0)) != PAM_SUCCESS) {
                error("pam_open_session: %s", pam_strerror(pam_h, rc));
                return SLURM_ERROR;
        }

	return SLURM_SUCCESS;

}
Ejemplo n.º 11
0
static void do_auth(char *service, char*user, char*pwd, char* mode, int sid)
{
    pam_handle_t *pamh=NULL;
    int retval;
    struct session *sessp;

    conv.appdata_ptr = (void*)strdup(pwd);
    retval = pam_start(service, user, &conv, &pamh);
    
    if (retval != PAM_SUCCESS) {
        werr(pamh, sid, retval, "start");
        return;
    }
    pam_set_item(pamh, PAM_RUSER, user);

    retval = pam_authenticate(pamh, 0); 
    if (retval != PAM_SUCCESS) {
        werr(pamh, sid, retval, "auth");
        return;
    }
    if (mode[0] == 'A') {
        retval = pam_acct_mgmt(pamh, 0); 
        if (retval != PAM_SUCCESS) {
            werr(pamh, sid, retval, "accounting");
            return;
        }
        /*fprintf(stderr, "did ok acct \n\r");*/
    }
    if (mode[1] == 'S') {
        retval = pam_open_session(pamh, 0);
        if (retval != PAM_SUCCESS) {
            werr(pamh, sid, retval, "session");
            return;
        }
        /*fprintf(stderr, "did ok open sess \n\r"); */
    }
    if ((sessp = malloc(sizeof(struct session))) == NULL) {
        werr(pamh, sid, -1, "malloc");
        return;
    }
    if (mode[1] == 'S') 
        sessp->session_mode = 1;
    else
        sessp->session_mode = 0;
    sessp->sid = sid;
    sessp->pamh = pamh;
    sessp->next = sessions;
    sessions = sessp;
    
    wok(sid);
}
Ejemplo n.º 12
0
int AuthPAMCheckSession(TSession *Session)
{
if (! pamh)
{
	if (! PAMStart(Session, Session->RealUser)) return(FALSE);
}

if (pam_acct_mgmt(pamh, 0)==PAM_SUCCESS) 
{
	pam_open_session(pamh, 0);
	return(TRUE);
}
return(FALSE);
}
Ejemplo n.º 13
0
Archivo: pam.c Proyecto: CVi/sudo
int
pam_begin_session(struct passwd *pw, sudo_auth *auth)
{
    int status = PAM_SUCCESS;

    /*
     * If there is no valid user we cannot open a PAM session.
     * This is not an error as sudo can run commands with arbitrary
     * uids, it just means we are done from a session management standpoint.
     */
    if (pw == NULL) {
	if (pamh != NULL) {
	    (void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
	    pamh = NULL;
	}
	goto done;
    }

    /* If the user did not have to authenticate there is no pam handle yet. */
    if (pamh == NULL)
	pam_init(pw, NULL, NULL);

    /*
     * Update PAM_USER to reference the user we are running the command
     * as, as opposed to the user we authenticated as.
     */
    (void) pam_set_item(pamh, PAM_USER, pw->pw_name);

    /*
     * Set credentials (may include resource limits, device ownership, etc).
     * We don't check the return value here because in Linux-PAM 0.75
     * it returns the last saved return code, not the return code
     * for the setcred module.  Because we haven't called pam_authenticate(),
     * this is not set and so pam_setcred() returns PAM_PERM_DENIED.
     * We can't call pam_acct_mgmt() with Linux-PAM for a similar reason.
     */
    (void) pam_setcred(pamh, PAM_ESTABLISH_CRED);

#ifndef NO_PAM_SESSION
    status = pam_open_session(pamh, 0);
    if (status != PAM_SUCCESS) {
	(void) pam_end(pamh, status | PAM_DATA_SILENT);
	pamh = NULL;
    }
#endif

done:
    return status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE;
}
Ejemplo n.º 14
0
int pam_begin_session(const char* username, int fd)
{
  int rv, i;
  if (!pam_h &&
      (rv = pam_start(PAM_APPL_NAME, username, &conv, &pam_h)) != PAM_SUCCESS)
    fatal("pam_start() failure: %d", rv);
#ifdef SUN_PAM_TTY_BUG
  if ((rv = pam_set_item(pam_h, PAM_TTY, "/dev/nld")) != PAM_SUCCESS)
    fatal("pam_set_item(PAM_TTY,/dev/nld");
#endif

  conv_reject_prompts = 1;
  pam_conv_fd = fd;

  /* On Solaris and HP-UX, the docs say we can't call setcred first, and the
   * modules actually enforce that. LinuxPAM says we must call setcred first,
   * and that's preferable, so we do it in all other cases. */
#ifdef SUN_PAM
  int setcred_first = 0;
#else
  int setcred_first = 1;
#endif

  for (i = 0; i < 2; ++i) {
    if (i != setcred_first) {
      if ((rv = pam_setcred(pam_h, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
        debug("pam_setcred(PAM_ESTABLISH_CRED): %s", pam_strerror(pam_h, rv));
        if (authenticated) {
          pam_conv_fd = -1;
          return -1;
        }
      } else {
        setcred = 1;
      }
    } else {
      if ((rv = pam_open_session(pam_h, 0)) != PAM_SUCCESS) {
        debug("pam_open_session(): %s", pam_strerror(pam_h, rv));
        if (authenticated) {
          pam_conv_fd = -1;
          return -1;
        }
      } else {
        opened_session = 1;
      }
    }
  }
  pam_conv_fd = -1;
  return 0;
}
Ejemplo n.º 15
0
int
main (void)
{
  int retval;

  /* 1: Call with NULL as pam handle */
  retval = pam_open_session (NULL, 0);
  if (retval == PAM_SUCCESS)
    {
      fprintf (stderr, "pam_open_session (NULL, 0) returned PAM_SUCCESS\n");
      return 1;
    }

  return 0;
}
Ejemplo n.º 16
0
int main(int argc, char *argv[])
{
	char *user = (argc > 1) ? argv[1] : getlogin();
	char *service = (argc > 2) ? argv[2] : "pamtest";
	struct pam_conv conv;
	int rc;
	pam_handle_t *pamh = NULL;

	conv.conv = pamtestConv;
	conv.appdata_ptr = NULL;

	fprintf(stderr, "%s:%d Starting with user=%s service=%s\n",
		__FILE__, __LINE__, user, service);

	rc = pam_start(service, user, &conv, &pamh);
	CHECK_STATUS(pamh, "pam_start", rc);

	rc = pam_authenticate(pamh, 0);
	CHECK_STATUS(pamh, "pam_authenticate", rc);

	rc = pam_acct_mgmt(pamh, 0);
	CHECK_STATUS(pamh, "pam_acct_mgmt", rc);

	if (rc == PAM_SUCCESS) {
		rc = pam_open_session(pamh, 0);
		CHECK_STATUS(pamh, "pam_open_session", rc);

		rc = pam_close_session(pamh, 0);
		CHECK_STATUS(pamh, "pam_close_session", rc);
	}

	if (rc != PAM_SUCCESS) {
		return rc;
	}

	if (pamh != NULL) {
		rc = pam_end(pamh, PAM_SUCCESS);
		CHECK_STATUS(pamh, "pam_end", rc);
	}

	return rc;
}
Ejemplo n.º 17
0
void
do_pam_session(void)
{
	debug3("PAM: opening session");
	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
	    (const void *)&store_conv);
	if (sshpam_err != PAM_SUCCESS)
		fatal("PAM: failed to set PAM_CONV: %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	sshpam_err = pam_open_session(sshpam_handle, 0);
	if (sshpam_err == PAM_SUCCESS)
		sshpam_session_open = 1;
	else {
		sshpam_session_open = 0;
		disable_forwarding();
		error("PAM: pam_open_session(): %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	}

}
Ejemplo n.º 18
0
int checkpass_pam(char *password)
{
	struct pam_conv conv = { conv_func, password };
	int retval = pam_start("bftpd", user, (struct pam_conv *) &conv,
						   (pam_handle_t **) & pamh);
	if (retval != PAM_SUCCESS) {
		printf("Error while initializing PAM: %s\n",
			   pam_strerror(pamh, retval));
		return 1;
	}
	pam_fail_delay(pamh, 0);
	retval = pam_authenticate(pamh, 0);
	if (retval == PAM_SUCCESS)
		retval = pam_acct_mgmt(pamh, 0);
	if (retval == PAM_SUCCESS)
		pam_open_session(pamh, 0);
	if (retval != PAM_SUCCESS)
		return 1;
	else
		return 0;
}
Ejemplo n.º 19
0
gboolean pam_session_open(void)
{
  g_pamLastStatus = pam_setcred(g_pamHandle, PAM_ESTABLISH_CRED);
  if (g_pamLastStatus != PAM_SUCCESS)
    {
      fprintf(stderr, "Jolicloud-DisplayManager: Unable to define pam credentials. Error %d\n",
	      g_pamLastStatus);
      return FALSE;
    }

  g_pamLastStatus = pam_open_session(g_pamHandle, 0);
  if (g_pamLastStatus != PAM_SUCCESS)
    {
      fprintf(stderr, "Jolicloud-DisplayManager: Unable to open session with pan. Error %d\n",
	      g_pamLastStatus);
      pam_setcred(g_pamHandle, PAM_DELETE_CRED);
      return FALSE;
    }

  return TRUE;
}
Ejemplo n.º 20
0
/*
 * Note that the position of the pam_setcred() call is discussable:
 *
 *  - the PAM docs recommend pam_setcred() before pam_open_session()
 *  - but the original RFC http://www.opengroup.org/rfc/mirror-rfc/rfc86.0.txt
 *    uses pam_setcred() after pam_open_session()
 *
 * The old login versions (before year 2011) followed the RFC. This is probably
 * not optimal, because there could be a dependence between some session modules
 * and the user's credentials.
 *
 * The best is probably to follow openssh and call pam_setcred() before and
 * after pam_open_session().                -- [email protected] (18-Nov-2011)
 *
 */
static void loginpam_session(struct login_context *cxt)
{
	int rc;
	pam_handle_t *pamh = cxt->pamh;

	rc = pam_setcred(pamh, PAM_ESTABLISH_CRED);
	if (is_pam_failure(rc))
		loginpam_err(pamh, rc);

	rc = pam_open_session(pamh, 0);
	if (is_pam_failure(rc)) {
		pam_setcred(cxt->pamh, PAM_DELETE_CRED);
		loginpam_err(pamh, rc);
	}

	rc = pam_setcred(pamh, PAM_REINITIALIZE_CRED);
	if (is_pam_failure(rc)) {
		pam_close_session(pamh, 0);
		loginpam_err(pamh, rc);
	}
}
Ejemplo n.º 21
0
struct passwd *checkpw (struct passwd *pw,char *pass,int argc,char *argv[])
{
  pam_handle_t *hdl;
  struct pam_conv conv;
  struct checkpw_cred cred;
  conv.conv = &checkpw_conv;
  conv.appdata_ptr = &cred;
  cred.uname = pw->pw_name;
  cred.pass = pass;
  if ((pam_start ((char *) mail_parameters (NIL,GET_SERVICENAME,NIL),
		  pw->pw_name,&conv,&hdl) != PAM_SUCCESS) ||
      (pam_set_item (hdl,PAM_RHOST,tcp_clientaddr ()) != PAM_SUCCESS) ||
      (pam_authenticate (hdl,NIL) != PAM_SUCCESS) ||
      (pam_acct_mgmt (hdl,NIL) != PAM_SUCCESS) ||
      (pam_setcred (hdl,PAM_ESTABLISH_CRED) != PAM_SUCCESS)) {
				/* clean up */
    pam_setcred (hdl,PAM_DELETE_CRED);
    pam_end (hdl,PAM_AUTH_ERR);	/* failed */
    return NIL;
  }
#if 0
  /*
   * Some people have reported that this causes a SEGV in strncpy() from
   * pam_unix.so.1
   */
  /*
   * This pam_open_session() call is inconsistant with how we handle other
   * platforms, where we don't write [uw]tmp records.  However, unlike our
   * code on other platforms, pam_acct_mgmt() will check those records for
   * inactivity and deny the authentication.
   */
  pam_open_session (hdl,NIL);	/* make sure account doesn't go inactive */
#endif
				/* arm hook to delete credentials */
  mail_parameters (NIL,SET_LOGOUTHOOK,(void *) checkpw_cleanup);
  mail_parameters (NIL,SET_LOGOUTDATA,(void *) hdl);
  return pw;
}
Ejemplo n.º 22
0
void
do_pam_session(struct ssh *ssh)
{
	debug3("PAM: opening session");

	expose_authinfo(__func__);

	sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
	    (const void *)&store_conv);
	if (sshpam_err != PAM_SUCCESS)
		fatal("PAM: failed to set PAM_CONV: %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	sshpam_err = pam_open_session(sshpam_handle, 0);
	if (sshpam_err == PAM_SUCCESS)
		sshpam_session_open = 1;
	else {
		sshpam_session_open = 0;
		auth_restrict_session(ssh);
		error("PAM: pam_open_session(): %s",
		    pam_strerror(sshpam_handle, sshpam_err));
	}

}
Ejemplo n.º 23
0
int lxdm_auth_session_begin(LXDM_AUTH *a,const char *name,int tty,int display,char mcookie[16])
{
	int err;
	char x[256];
	
	if(!a->handle)
	{
		return -1;
	}
	sprintf(x, "tty%d", tty);
	pam_set_item(a->handle, PAM_TTY, x);
#ifdef PAM_XDISPLAY
	sprintf(x,":%d",display);
	pam_set_item(a->handle, PAM_XDISPLAY, x);
#endif
#if !defined(DISABLE_XAUTH) && defined(PAM_XAUTHDATA)
	struct pam_xauth_data value;
	value.name="MIT-MAGIC-COOKIE-1";
	value.namelen=18;
	value.data=mcookie;
	value.datalen=16;
	pam_set_item (a->handle, PAM_XAUTHDATA, &value);
#endif
	if(name && name[0])
	{
		char *env;
		env = g_strdup_printf ("DESKTOP_SESSION=%s", name);
		pam_putenv (a->handle, env);
		g_free (env);
	}
	err = pam_open_session(a->handle, 0); /* FIXME pam session failed */
	if( err != PAM_SUCCESS )
		g_warning( "pam open session error \"%s\"\n", pam_strerror(a->handle, err));
	else
		a->in_session=1;
	return 0;
}
Ejemplo n.º 24
0
static int
open_session (pam_handle_t *pamh,
              const char *user)
{
  char login[256];
  int res;

  /*
   * If we're already in the right session, then skip cockpit-session.
   * This is used when testing, or running as your own user.
   *
   * This doesn't apply if this code is running as a service, or otherwise
   * unassociated from a terminal, we get a non-zero return value from
   * getlogin_r() in that case.
   */

  want_session = (getlogin_r (login, sizeof (login)) != 0 ||
                  strcmp (login, user) != 0);

  if (want_session)
    {
      debug ("checking access for %s", user);
      res = pam_acct_mgmt (pamh, 0);
      if (res != PAM_SUCCESS)
        {
          warnx ("user account access failed: %s: %s", user, pam_strerror (pamh, res));

          /* We change PAM_AUTH_ERR to PAM_PERM_DENIED so that we can
           * distinguish between failures here and in *
           * pam_authenticate.
           */
          if (res == PAM_AUTH_ERR)
            res = PAM_PERM_DENIED;

          return res;
        }

      debug ("opening pam session for %s", user);

      res = pam_set_item (pamh, PAM_TTY, line);
      if (res != PAM_SUCCESS)
        {
          warnx ("couldn't set tty: %s", pam_strerror (pamh, res));
          return res;
        }

      res = pam_setcred (pamh, PAM_ESTABLISH_CRED);
      if (res != PAM_SUCCESS)
        {
          warnx ("establishing credentials failed: %s: %s", user, pam_strerror (pamh, res));
          return res;
        }

      res = pam_open_session (pamh, 0);
      if (res != PAM_SUCCESS)
        {
          warnx ("couldn't open session: %s: %s", user, pam_strerror (pamh, res));
          return res;
        }

      res = pam_setcred (pamh, PAM_REINITIALIZE_CRED);
      if (res != PAM_SUCCESS)
        {
          warnx ("reinitializing credentials failed: %s: %s", user, pam_strerror (pamh, res));
          return res;
        }
    }

  return PAM_SUCCESS;
}
Ejemplo n.º 25
0
static void
create_watching_parent (void) {
    pid_t child;
    sigset_t ourset;
    struct sigaction oldact[3];
    int status = 0;
    int retval;

    retval = pam_open_session (pamh, 0);
    if (is_pam_failure(retval)) {
        cleanup_pam (retval);
        errx (EXIT_FAILURE, _("cannot open session: %s"),
              pam_strerror (pamh, retval));
    } else {
        _pam_session_opened = 1;
    }

    memset(oldact, 0, sizeof(oldact));

    child = fork ();
    if (child == (pid_t) - 1) {
        cleanup_pam (PAM_ABORT);
        err (EXIT_FAILURE, _("cannot create child process"));
    }

    /* the child proceeds to run the shell */
    if (child == 0) {
        return;
    }

    /* In the parent watch the child.  */

    /* su without pam support does not have a helper that keeps
       sitting on any directory so let's go to /.  */
    if (chdir ("/") != 0) {
        warn (_("cannot change directory to %s"), "/");
    }

    sigfillset (&ourset);
    if (sigprocmask (SIG_BLOCK, &ourset, NULL)) {
        warn (_("cannot block signals"));
        caught_signal = true;
    }
    if (!caught_signal) {
        struct sigaction action;
        action.sa_handler = su_catch_sig;
        sigemptyset (&action.sa_mask);
        action.sa_flags = 0;
        sigemptyset (&ourset);
        if (!same_session) {
            if (sigaddset(&ourset, SIGINT) || sigaddset(&ourset, SIGQUIT)) {
                warn (_("cannot set signal handler"));
                caught_signal = true;
            }
        }
        if (!caught_signal && (sigaddset(&ourset, SIGTERM)
                               || sigaddset(&ourset, SIGALRM)
                               || sigaction(SIGTERM, &action, &oldact[0])
                               || sigprocmask(SIG_UNBLOCK, &ourset, NULL))) {
            warn (_("cannot set signal handler"));
            caught_signal = true;
        }
        if (!caught_signal && !same_session && (sigaction(SIGINT, &action, &oldact[1])
                                                || sigaction(SIGQUIT, &action, &oldact[2]))) {
            warn (_("cannot set signal handler"));
            caught_signal = true;
        }
    }
    if (!caught_signal) {
        pid_t pid;
        for (;;) {
            pid = waitpid (child, &status, WUNTRACED);

            if (pid != (pid_t) - 1 && WIFSTOPPED (status)) {
                kill (getpid (), SIGSTOP);
                /* once we get here, we must have resumed */
                kill (pid, SIGCONT);
            } else {
                break;
            }
        }
        if (pid != (pid_t) - 1) {
            if (WIFSIGNALED (status)) {
                fprintf (stderr, "%s%s\n", strsignal (WTERMSIG (status)),
                         WCOREDUMP (status) ? _(" (core dumped)") : "");
                status = WTERMSIG (status) + 128;
            } else {
                status = WEXITSTATUS (status);
            }
        } else if (caught_signal) {
            status = caught_signal + 128;
        } else {
            status = 1;
        }
    } else {
        status = 1;
    }

    if (caught_signal) {
        fprintf (stderr, _("\nSession terminated, killing shell..."));
        kill (child, SIGTERM);
    }

    cleanup_pam (PAM_SUCCESS);

    if (caught_signal) {
        sleep (2);
        kill (child, SIGKILL);
        fprintf (stderr, _(" ...killed.\n"));

        /* Let's terminate itself with the received signal.
         *
         * It seems that shells use WIFSIGNALED() rather than our exit status
         * value to detect situations when is necessary to cleanup (reset)
         * terminal settings (kzak -- Jun 2013).
         */
        switch (caught_signal) {
        case SIGTERM:
            sigaction(SIGTERM, &oldact[0], NULL);
            break;
        case SIGINT:
            sigaction(SIGINT, &oldact[1], NULL);
            break;
        case SIGQUIT:
            sigaction(SIGQUIT, &oldact[2], NULL);
            break;
        default:
            /* just in case that signal stuff initialization failed and
             * caught_signal = true */
            caught_signal = SIGKILL;
            break;
        }
        kill(getpid(), caught_signal);
    }
    exit (status);
}
Ejemplo n.º 26
0
gchar *
mdm_verify_user (MdmDisplay *d,
		 const char *username,
		 gboolean allow_retry)
{
	gint pamerr = 0;
	struct passwd *pwent = NULL;
	char *login, *passreq;
	char *pam_stack = NULL;
	MDM_PAM_QUAL void *p;
	int null_tok = 0;
	gboolean credentials_set = FALSE;
	gboolean error_msg_given = FALSE;
	gboolean started_timer   = FALSE;

    verify_user_again:

	pamerr = 0;
	login = NULL;
	error_msg_given = FALSE;
	credentials_set = FALSE;
	started_timer = FALSE;
	null_tok = 0;

	/* Don't start a timed login if we've already entered a username */
	if (username != NULL) {
		login = g_strdup (username);
		mdm_slave_greeter_ctl_no_ret (MDM_SETLOGIN, login);
	} else {
		/* start the timer for timed logins */
		if ( ! ve_string_empty (mdm_daemon_config_get_value_string (MDM_KEY_TIMED_LOGIN)) &&
		    d->timed_login_ok && (d->attached)) {
			mdm_slave_greeter_ctl_no_ret (MDM_STARTTIMER, "");
			started_timer = TRUE;
		}
	}

	cur_mdm_disp = d;

 authenticate_again:

	if (prev_user && !login) {
		login = g_strdup (prev_user);
	} else if (login && !prev_user) {
		prev_user = g_strdup (login);
		auth_retries = 0;
	} else if (login && prev_user && strcmp (login, prev_user)) {
		g_free (prev_user);
		prev_user = g_strdup (login);
		auth_retries = 0;
	}

	/*
	 * Initialize a PAM session for the user...
	 * Get value per-display so different displays can use different
	 * PAM Stacks, in case one display should use a different
	 * authentication mechanism than another display.
	 */
	pam_stack = mdm_daemon_config_get_value_string_per_display (MDM_KEY_PAM_STACK,
		(char *)d->name);

	if ( ! create_pamh (d, pam_stack, login, &pamc, d->name, &pamerr)) {
		if (started_timer)
			mdm_slave_greeter_ctl_no_ret (MDM_STOPTIMER, "");
		g_free (pam_stack);
		goto pamerr;
	}

	g_free (pam_stack);

	/*
	 * have to unset login otherwise there is no chance to ever enter
	 * a different user
	 */
	g_free (login);
	login = NULL;

	pam_set_item (pamh, PAM_USER_PROMPT, _("Username:"******"PASSREQ=");

	if (mdm_daemon_config_get_value_bool (MDM_KEY_PASSWORD_REQUIRED) ||
            ((passreq != NULL) && g_ascii_strcasecmp (passreq, "YES") == 0))
		null_tok |= PAM_DISALLOW_NULL_AUTHTOK;

	mdm_verify_select_user (NULL);

	/* Start authentication session */
	did_we_ask_for_password = FALSE;
	if ((pamerr = pam_authenticate (pamh, null_tok)) != PAM_SUCCESS) {
		if ( ! ve_string_empty (selected_user)) {
			pam_handle_t *tmp_pamh;

			/* Face browser was used to select a user,
			   just completely rewhack everything since it
			   seems various PAM implementations are
			   having goats with just setting PAM_USER
			   and trying to pam_authenticate again */

			g_free (login);
			login = selected_user;
			selected_user = NULL;

			mdm_sigterm_block_push ();
			mdm_sigchld_block_push ();
			tmp_pamh = pamh;
			pamh     = NULL;
			mdm_sigchld_block_pop ();
			mdm_sigterm_block_pop ();

			/* FIXME: what about errors */
			/* really this has been a sucess, not a failure */
			pam_end (tmp_pamh, pamerr);

			g_free (prev_user);
			prev_user    = NULL;
			auth_retries = 0;

			mdm_slave_greeter_ctl_no_ret (MDM_SETLOGIN, login);

			goto authenticate_again;
		}

		if (started_timer)
			mdm_slave_greeter_ctl_no_ret (MDM_STOPTIMER, "");

		if (mdm_slave_action_pending ()) {
			/* FIXME: see note above about PAM_FAIL_DELAY */
			/* #ifndef PAM_FAIL_DELAY */
			mdm_sleep_no_signal (mdm_daemon_config_get_value_int (MDM_KEY_RETRY_DELAY));
			/* wait up to 100ms randomly */
			usleep (g_random_int_range (0, 100000));
			/* #endif */ /* PAM_FAIL_DELAY */
			mdm_error ("Couldn't authenticate user");

			if (prev_user) {

				unsigned max_auth_retries = 3;
				char *val = mdm_read_default ("LOGIN_RETRIES=");

				if (val) {
					max_auth_retries = atoi (val);
					g_free (val);
				}

				if (allow_retry == FALSE || pamerr == PAM_MAXTRIES ||
				    ++auth_retries >= max_auth_retries) {

					g_free (prev_user);
					prev_user    = NULL;
					auth_retries = 0;
				}
			}
		} else {
			/* cancel, configurator etc pressed */
			g_free (prev_user);
			prev_user    = NULL;
			auth_retries = 0;
		}

		goto pamerr;
	}

	/* stop the timer for timed logins */
	if (started_timer)
		mdm_slave_greeter_ctl_no_ret (MDM_STOPTIMER, "");

	g_free (login);
	login = NULL;
	g_free (prev_user);
	prev_user = NULL;

	if ((pamerr = pam_get_item (pamh, PAM_USER, &p)) != PAM_SUCCESS) {
		login = NULL;
		/* is not really an auth problem, but it will
		   pretty much look as such, it shouldn't really
		   happen */
		if (mdm_slave_action_pending ())
			mdm_error ("Couldn't authenticate user");
		goto pamerr;
	}

	login = g_strdup ((const char *)p);
	/* kind of anal, the greeter likely already knows, but it could have
	   been changed */
	mdm_slave_greeter_ctl_no_ret (MDM_SETLOGIN, login);

	if ( ! mdm_slave_check_user_wants_to_log_in (login)) {
		/* cleanup stuff */
		mdm_slave_greeter_ctl_no_ret (MDM_SETLOGIN, "");
		g_free (login);
		login = NULL;
		mdm_slave_greeter_ctl_no_ret (MDM_RESETOK, "");

		mdm_verify_cleanup (d);

		goto verify_user_again;
	}

	/* Check if user is root and is allowed to log in */

	pwent = getpwnam (login);
	if (( ! mdm_daemon_config_get_value_bool (MDM_KEY_ALLOW_ROOT) ||
            ( ! d->attached )) &&
            (pwent != NULL && pwent->pw_uid == 0)) {
		mdm_error ("Root login disallowed on display '%s'", d->name);
		mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
					      _("\nThe system administrator "
						"is not allowed to login "
						"from this screen"));
		/*mdm_slave_greeter_ctl_no_ret (MDM_ERRDLG,
		  _("Root login disallowed"));*/
		error_msg_given = TRUE;

		goto pamerr;
	}

	if (mdm_daemon_config_get_value_bool (MDM_KEY_DISPLAY_LAST_LOGIN)) {
		char *info = mdm_get_last_info (login);
		mdm_slave_greeter_ctl_no_ret (MDM_MSG, info);
		g_free (info);
	}

	/* Check if the user's account is healthy. */
	pamerr = pam_acct_mgmt (pamh, null_tok);
	switch (pamerr) {
	case PAM_SUCCESS :
		break;
	case PAM_NEW_AUTHTOK_REQD :
		if ((pamerr = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK)) != PAM_SUCCESS) {
			mdm_error ("Authentication token change failed for user %s", login);
			mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
						      _("\nThe change of the authentication token failed. "
							"Please try again later or contact the system administrator."));
			error_msg_given = TRUE;
			goto pamerr;
		}
		break;
	case PAM_ACCT_EXPIRED :
		mdm_error ("User %s no longer permitted to access the system", login);
		mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
					      _("\nThe system administrator has disabled your account."));
		error_msg_given = TRUE;
		goto pamerr;
	case PAM_PERM_DENIED :
		mdm_error ("User %s not permitted to gain access at this time", login);
		mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
					      _("\nThe system administrator has disabled access to the system temporarily."));
		error_msg_given = TRUE;
		goto pamerr;
	default :
		if (mdm_slave_action_pending ())
			mdm_error ("Couldn't set acct. mgmt for %s", login);
		goto pamerr;
	}

	pwent = getpwnam (login);
	if (/* paranoia */ pwent == NULL ||
	    ! mdm_setup_gids (login, pwent->pw_gid)) {
		mdm_error ("Cannot set user group for %s", login);
		mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX,
					      _("\nCannot set your user group; "
						"you will not be able to log in. "
						"Please contact your system administrator."));
		goto pamerr;
	}

	did_setcred = TRUE;

	/* Set credentials */
	pamerr = pam_setcred (pamh, PAM_ESTABLISH_CRED);
	if (pamerr != PAM_SUCCESS) {
		did_setcred = FALSE;
		if (mdm_slave_action_pending ())
			mdm_error ("Couldn't set credentials for %s", login);
		goto pamerr;
	}

	credentials_set = TRUE;
	opened_session  = TRUE;

	/* Register the session */
	pamerr = pam_open_session (pamh, 0);
	if (pamerr != PAM_SUCCESS) {
		opened_session = FALSE;
		/* we handle this above */
		did_setcred = FALSE;
		if (mdm_slave_action_pending ())
			mdm_error ("Couldn't open session for %s", login);
		goto pamerr;
	}

	/* Workaround to avoid mdm messages being logged as PAM_pwdb */
	mdm_log_shutdown ();
	mdm_log_init ();

	cur_mdm_disp = NULL;

	/*
	 * Login succeeded.
	 * This function is a no-op if libaudit is not present.
	 */
	log_to_audit_system(login, d->hostname, d->name, AU_SUCCESS);

	return login;

 pamerr:
	/*
	 * Take care of situation where we get here before setting pwent.
	 * Since login can be passed in as NULL, get the actual value if
	 * possible.
	 */
	if ((pam_get_item (pamh, PAM_USER, &p)) == PAM_SUCCESS) {
		g_free (login);
		login = g_strdup ((const char *)p);
	}
	if (pwent == NULL && login != NULL) {
		pwent = getpwnam (login);
	}

	/*
	 * Log the failed login attempt.
	 * This function is a no-op if libaudit is not present.
	 */
	log_to_audit_system(login, d->hostname, d->name, AU_FAILED);

	/* The verbose authentication is turned on, output the error
	 * message from the PAM subsystem */
	if ( ! error_msg_given &&
	     mdm_slave_action_pending ()) {
		mdm_slave_write_utmp_wtmp_record (d,
					MDM_SESSION_RECORD_TYPE_FAILED_ATTEMPT,
					login, getpid ());

		/*
		 * I'm not sure yet if I should display this message for any
		 * other issues - heeten
		 * Adding AUTHINFO_UNAVAIL to the list - its what an unknown
		 * user is.
		 */
		if (pamerr == PAM_AUTH_ERR ||
		    pamerr == PAM_USER_UNKNOWN ||
		    pamerr == PAM_AUTHINFO_UNAVAIL) {
			gboolean is_capslock = FALSE;
			const char *basemsg;
			char *msg;
			char *ret;

			ret = mdm_slave_greeter_ctl (MDM_QUERY_CAPSLOCK, "");
			if ( ! ve_string_empty (ret))
				is_capslock = TRUE;
			g_free (ret);

			/* Only give this message if we actually asked for
			   password, otherwise it would be silly to say that
			   the password may have been wrong */
			if (did_we_ask_for_password) {
				basemsg = _("\nIncorrect username or password.  "
					    "Letters must be typed in the correct "
					    "case.");
			} else {
				basemsg = _("\nAuthentication failed.  "
					    "Letters must be typed in the correct "
					    "case.");
			}
			if (is_capslock) {
				msg = g_strconcat (basemsg, "  ",
						   _("Caps Lock is on."),
						   NULL);
			} else {
				msg = g_strdup (basemsg);
			}
			mdm_slave_greeter_ctl_no_ret (MDM_ERRBOX, msg);
			g_free (msg);
		} else {
			mdm_slave_greeter_ctl_no_ret (MDM_ERRDLG, _("Authentication failed"));
		}
	}

	did_setcred = FALSE;
	opened_session = FALSE;

	if (pamh != NULL) {
		pam_handle_t *tmp_pamh;
		mdm_sigterm_block_push ();
		mdm_sigchld_block_push ();
		tmp_pamh = pamh;
		pamh = NULL;
		mdm_sigchld_block_pop ();
		mdm_sigterm_block_pop ();

		/* Throw away the credentials */
		if (credentials_set)
			pam_setcred (tmp_pamh, PAM_DELETE_CRED);
		pam_end (tmp_pamh, pamerr);
	}
	pamh = NULL;

	/* Workaround to avoid mdm messages being logged as PAM_pwdb */
	mdm_log_shutdown ();
	mdm_log_init ();

	g_free (login);

	cur_mdm_disp = NULL;

	return NULL;
}
Ejemplo n.º 27
0
int main(int argc, char **argv)
{
	int devnull_fd = -1;
#ifdef TIOCNOTTY
	int tty_fd = -1;
#endif

#ifdef HAVE_PAM
	pam_handle_t *pamh = NULL;
	int pamr;
	const char *const *pamenv = NULL;
#endif

	int opt;
	bool start = false;
	bool stop = false;
	bool oknodo = false;
	bool test = false;
	char *exec = NULL;
	char *startas = NULL;
	char *name = NULL;
	char *pidfile = NULL;
	char *retry = NULL;
	int sig = -1;
	int nicelevel = 0, ionicec = -1, ioniced = 0;
	bool background = false;
	bool makepidfile = false;
	bool interpreted = false;
	bool progress = false;
	uid_t uid = 0;
	gid_t gid = 0;
	char *home = NULL;
	int tid = 0;
	char *redirect_stderr = NULL;
	char *redirect_stdout = NULL;
	int stdin_fd;
	int stdout_fd;
	int stderr_fd;
	pid_t pid, spid;
	int i;
	char *svcname = getenv("RC_SVCNAME");
	RC_STRINGLIST *env_list;
	RC_STRING *env;
	char *tmp, *newpath, *np;
	char *p;
	char *token;
	char exec_file[PATH_MAX];
	struct passwd *pw;
	struct group *gr;
	char line[130];
	FILE *fp;
	size_t len;
	mode_t numask = 022;
	char **margv;
	unsigned int start_wait = 0;

	applet = basename_c(argv[0]);
	TAILQ_INIT(&schedule);
#ifdef DEBUG_MEMORY
	atexit(cleanup);
#endif

	signal_setup(SIGINT, handle_signal);
	signal_setup(SIGQUIT, handle_signal);
	signal_setup(SIGTERM, handle_signal);

	if ((tmp = getenv("SSD_NICELEVEL")))
		if (sscanf(tmp, "%d", &nicelevel) != 1)
			eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
			    applet, tmp);

	/* Get our user name and initial dir */
	p = getenv("USER");
	home = getenv("HOME");
	if (home == NULL || p == NULL) {
		pw = getpwuid(getuid());
		if (pw != NULL) {
			if (p == NULL)
				setenv("USER", pw->pw_name, 1);
			if (home == NULL) {
				setenv("HOME", pw->pw_dir, 1);
				home = pw->pw_dir;
			}
		}
	}

	while ((opt = getopt_long(argc, argv, getoptstring, longopts,
		    (int *) 0)) != -1)
		switch (opt) {
		case 'I': /* --ionice */
			if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0)
				eerrorx("%s: invalid ionice `%s'",
				    applet, optarg);
			if (ionicec == 0)
				ioniced = 0;
			else if (ionicec == 3)
				ioniced = 7;
			ionicec <<= 13; /* class shift */
			break;

		case 'K':  /* --stop */
			stop = true;
			break;

		case 'N':  /* --nice */
			if (sscanf(optarg, "%d", &nicelevel) != 1)
				eerrorx("%s: invalid nice level `%s'",
				    applet, optarg);
			break;

		case 'P':  /* --progress */
			progress = true;
			break;

		case 'R':  /* --retry <schedule>|<timeout> */
			retry = optarg;
			break;

		case 'S':  /* --start */
			start = true;
			break;

		case 'b':  /* --background */
			background = true;
			break;

		case 'c':  /* --chuid <username>|<uid> */
			/* DEPRECATED */
			ewarn("WARNING: -c/--chuid is deprecated and will be removed in the future, please use -u/--user instead");
		case 'u':  /* --user <username>|<uid> */
		{
			p = optarg;
			tmp = strsep(&p, ":");
			changeuser = xstrdup(tmp);
			if (sscanf(tmp, "%d", &tid) != 1)
				pw = getpwnam(tmp);
			else
				pw = getpwuid((uid_t)tid);

			if (pw == NULL)
				eerrorx("%s: user `%s' not found",
				    applet, tmp);
			uid = pw->pw_uid;
			home = pw->pw_dir;
			unsetenv("HOME");
			if (pw->pw_dir)
				setenv("HOME", pw->pw_dir, 1);
			unsetenv("USER");
			if (pw->pw_name)
				setenv("USER", pw->pw_name, 1);
			if (gid == 0)
				gid = pw->pw_gid;

			if (p) {
				tmp = strsep (&p, ":");
				if (sscanf(tmp, "%d", &tid) != 1)
					gr = getgrnam(tmp);
				else
					gr = getgrgid((gid_t) tid);

				if (gr == NULL)
					eerrorx("%s: group `%s'"
					    " not found",
					    applet, tmp);
				gid = gr->gr_gid;
			}
		}
		break;

		case 'd':  /* --chdir /new/dir */
			ch_dir = optarg;
			break;

		case 'e': /* --env */
			putenv(optarg);
			break;

		case 'g':  /* --group <group>|<gid> */
			if (sscanf(optarg, "%d", &tid) != 1)
				gr = getgrnam(optarg);
			else
				gr = getgrgid((gid_t)tid);
			if (gr == NULL)
				eerrorx("%s: group `%s' not found",
				    applet, optarg);
			gid = gr->gr_gid;
			break;

		case 'i': /* --interpreted */
			interpreted = true;
			break;

		case 'k':
			if (parse_mode(&numask, optarg))
				eerrorx("%s: invalid mode `%s'",
				    applet, optarg);
			break;

		case 'm':  /* --make-pidfile */
			makepidfile = true;
			break;

		case 'n':  /* --name <process-name> */
			name = optarg;
			break;

		case 'o':  /* --oknodo */
			/* DEPRECATED */
			ewarn("WARNING: -o/--oknodo is deprecated and will be removed in the future");
			oknodo = true;
			break;

		case 'p':  /* --pidfile <pid-file> */
			pidfile = optarg;
			break;

		case 's':  /* --signal <signal> */
			sig = parse_signal(optarg);
			break;

		case 't':  /* --test */
			test = true;
			break;

		case 'r':  /* --chroot /new/root */
			ch_root = optarg;
			break;

		case 'a': /* --startas <name> */
			/* DEPRECATED */
			ewarn("WARNING: -a/--startas is deprecated and will be removed in the future, please use -x/--exec or -n/--name instead");
			startas = optarg;
			break;
		case 'w':
			if (sscanf(optarg, "%d", &start_wait) != 1)
				eerrorx("%s: `%s' not a number",
				    applet, optarg);
			break;
		case 'x':  /* --exec <executable> */
			exec = optarg;
			break;

		case '1':   /* --stdout /path/to/stdout.lgfile */
			redirect_stdout = optarg;
			break;

		case '2':  /* --stderr /path/to/stderr.logfile */
			redirect_stderr = optarg;
			break;

		case_RC_COMMON_GETOPT
		}

	endpwent();
	argc -= optind;
	argv += optind;

	/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
	 * instead of forcing --stop --oknodo as well */
	if (!start &&
	    !stop &&
	    sig != SIGINT &&
	    sig != SIGTERM &&
	    sig != SIGQUIT &&
	    sig != SIGKILL)
		oknodo = true;

	if (!exec)
		exec = startas;
	else if (!name)
		name = startas;

	if (!exec) {
		exec = *argv;
		if (!exec)
			exec = name;
		if (name && start)
			*argv = name;
	} else if (name) {
		*--argv = name;
		++argc;
    } else if (exec) {
		*--argv = exec;
		++argc;
	};

	if (stop || sig != -1) {
		if (sig == -1)
			sig = SIGTERM;
		if (!*argv && !pidfile && !name && !uid)
			eerrorx("%s: --stop needs --exec, --pidfile,"
			    " --name or --user", applet);
		if (background)
			eerrorx("%s: --background is only relevant with"
			    " --start", applet);
		if (makepidfile)
			eerrorx("%s: --make-pidfile is only relevant with"
			    " --start", applet);
		if (redirect_stdout || redirect_stderr)
			eerrorx("%s: --stdout and --stderr are only relevant"
			    " with --start", applet);
	} else {
		if (!exec)
			eerrorx("%s: nothing to start", applet);
		if (makepidfile && !pidfile)
			eerrorx("%s: --make-pidfile is only relevant with"
			    " --pidfile", applet);
		if ((redirect_stdout || redirect_stderr) && !background)
			eerrorx("%s: --stdout and --stderr are only relevant"
			    " with --background", applet);
	}

	/* Expand ~ */
	if (ch_dir && *ch_dir == '~')
		ch_dir = expand_home(home, ch_dir);
	if (ch_root && *ch_root == '~')
		ch_root = expand_home(home, ch_root);
	if (exec) {
		if (*exec == '~')
			exec = expand_home(home, exec);

		/* Validate that the binary exists if we are starting */
		if (*exec == '/' || *exec == '.') {
			/* Full or relative path */
			if (ch_root)
				snprintf(exec_file, sizeof(exec_file),
				    "%s/%s", ch_root, exec);
			else
				snprintf(exec_file, sizeof(exec_file),
				    "%s", exec);
		} else {
			/* Something in $PATH */
			p = tmp = xstrdup(getenv("PATH"));
			*exec_file = '\0';
			while ((token = strsep(&p, ":"))) {
				if (ch_root)
					snprintf(exec_file, sizeof(exec_file),
					    "%s/%s/%s",
					    ch_root, token, exec);
				else
					snprintf(exec_file, sizeof(exec_file),
					    "%s/%s", token, exec);
				if (exists(exec_file))
					break;
				*exec_file = '\0';
			}
			free(tmp);
		}
	}
	if (start && !exists(exec_file)) {
		eerror("%s: %s does not exist", applet,
		    *exec_file ? exec_file : exec);
		exit(EXIT_FAILURE);
	}

	/* If we don't have a pidfile we should check if it's interpreted
	 * or not. If it we, we need to pass the interpreter through
	 * to our daemon calls to find it correctly. */
	if (interpreted && !pidfile) {
		fp = fopen(exec_file, "r");
		if (fp) {
			p = fgets(line, sizeof(line), fp);
			fclose(fp);
			if (p != NULL && line[0] == '#' && line[1] == '!') {
				p = line + 2;
				/* Strip leading spaces */
				while (*p == ' ' || *p == '\t')
					p++;
				/* Remove the trailing newline */
				len = strlen(p) - 1;
				if (p[len] == '\n')
					p[len] = '\0';
				token = strsep(&p, " ");
				strncpy(exec_file, token, sizeof(exec_file));
				opt = 0;
				for (nav = argv; *nav; nav++)
					opt++;
				nav = xmalloc(sizeof(char *) * (opt + 3));
				nav[0] = exec_file;
				len = 1;
				if (p)
					nav[len++] = p;
				for (i = 0; i < opt; i++)
					nav[i + len] = argv[i];
				nav[i + len] = '\0';
			}
		}
	}
	margv = nav ? nav : argv;

	if (stop || sig != -1) {
		if (sig == -1)
			sig = SIGTERM;
		if (!stop)
			oknodo = true;
		if (retry)
			parse_schedule(retry, sig);
		else if (test || oknodo)
			parse_schedule("0", sig);
		else
			parse_schedule(NULL, sig);
		i = run_stop_schedule(exec, (const char *const *)margv,
		    pidfile, uid, test, progress);

		if (i < 0)
			/* We failed to stop something */
			exit(EXIT_FAILURE);
		if (test || oknodo)
			return i > 0 ? EXIT_SUCCESS : EXIT_FAILURE;

		/* Even if we have not actually killed anything, we should
		 * remove information about it as it may have unexpectedly
		 * crashed out. We should also return success as the end
		 * result would be the same. */
		if (pidfile && exists(pidfile))
			unlink(pidfile);
		if (svcname)
			rc_service_daemon_set(svcname, exec,
			    (const char *const *)argv,
			    pidfile, false);
		exit(EXIT_SUCCESS);
	}

	if (pidfile)
		pid = get_pid(pidfile);
	else
		pid = 0;

	if (do_stop(exec, (const char * const *)margv, pid, uid,
		0, test) > 0)
		eerrorx("%s: %s is already running", applet, exec);

	if (test) {
		if (rc_yesno(getenv("EINFO_QUIET")))
			exit (EXIT_SUCCESS);

		einfon("Would start");
		while (argc-- > 0)
			printf(" %s", *argv++);
		printf("\n");
		eindent();
		if (uid != 0)
			einfo("as user id %d", uid);
		if (gid != 0)
			einfo("as group id %d", gid);
		if (ch_root)
			einfo("in root `%s'", ch_root);
		if (ch_dir)
			einfo("in dir `%s'", ch_dir);
		if (nicelevel != 0)
			einfo("with a priority of %d", nicelevel);
		if (name)
			einfo ("with a process name of %s", name);
		eoutdent();
		exit(EXIT_SUCCESS);
	}

	ebeginv("Detaching to start `%s'", exec);
	eindentv();

	/* Remove existing pidfile */
	if (pidfile)
		unlink(pidfile);

	if (background)
		signal_setup(SIGCHLD, handle_signal);

	if ((pid = fork()) == -1)
		eerrorx("%s: fork: %s", applet, strerror(errno));

	/* Child process - lets go! */
	if (pid == 0) {
		pid_t mypid = getpid();
		umask(numask);

#ifdef TIOCNOTTY
		tty_fd = open("/dev/tty", O_RDWR);
#endif

		devnull_fd = open("/dev/null", O_RDWR);

		if (nicelevel) {
			if (setpriority(PRIO_PROCESS, mypid, nicelevel) == -1)
				eerrorx("%s: setpritory %d: %s",
				    applet, nicelevel,
				    strerror(errno));
		}

		if (ionicec != -1 &&
		    ioprio_set(1, mypid, ionicec | ioniced) == -1)
			eerrorx("%s: ioprio_set %d %d: %s", applet,
			    ionicec, ioniced, strerror(errno));

		if (ch_root && chroot(ch_root) < 0)
			eerrorx("%s: chroot `%s': %s",
			    applet, ch_root, strerror(errno));

		if (ch_dir && chdir(ch_dir) < 0)
			eerrorx("%s: chdir `%s': %s",
			    applet, ch_dir, strerror(errno));

		if (makepidfile && pidfile) {
			fp = fopen(pidfile, "w");
			if (! fp)
				eerrorx("%s: fopen `%s': %s", applet, pidfile,
				    strerror(errno));
			fprintf(fp, "%d\n", mypid);
			fclose(fp);
		}

#ifdef HAVE_PAM
		if (changeuser != NULL) {
			pamr = pam_start("start-stop-daemon",
			    changeuser, &conv, &pamh);

			if (pamr == PAM_SUCCESS)
				pamr = pam_acct_mgmt(pamh, PAM_SILENT);
			if (pamr == PAM_SUCCESS)
				pamr = pam_open_session(pamh, PAM_SILENT);
			if (pamr != PAM_SUCCESS)
				eerrorx("%s: pam error: %s",
					applet, pam_strerror(pamh, pamr));
		}
#endif

		if (gid && setgid(gid))
			eerrorx("%s: unable to set groupid to %d",
			    applet, gid);
		if (changeuser && initgroups(changeuser, gid))
			eerrorx("%s: initgroups (%s, %d)",
			    applet, changeuser, gid);
		if (uid && setuid(uid))
			eerrorx ("%s: unable to set userid to %d",
			    applet, uid);

		/* Close any fd's to the passwd database */
		endpwent();

#ifdef TIOCNOTTY
		ioctl(tty_fd, TIOCNOTTY, 0);
		close(tty_fd);
#endif

		/* Clean the environment of any RC_ variables */
		env_list = rc_stringlist_new();
		i = 0;
		while (environ[i])
			rc_stringlist_add(env_list, environ[i++]);

#ifdef HAVE_PAM
		if (changeuser != NULL) {
			pamenv = (const char *const *)pam_getenvlist(pamh);
			if (pamenv) {
				while (*pamenv) {
					/* Don't add strings unless they set a var */
					if (strchr(*pamenv, '='))
						putenv(xstrdup(*pamenv));
					else
						unsetenv(*pamenv);
					pamenv++;
				}
			}
		}
#endif

		TAILQ_FOREACH(env, env_list, entries) {
			if ((strncmp(env->value, "RC_", 3) == 0 &&
				strncmp(env->value, "RC_SERVICE=", 10) != 0 &&
				strncmp(env->value, "RC_SVCNAME=", 10) != 0) ||
			    strncmp(env->value, "SSD_NICELEVEL=", 14) == 0)
			{
				p = strchr(env->value, '=');
				*p = '\0';
				unsetenv(env->value);
				continue;
			}
		}
		rc_stringlist_free(env_list);

		/* For the path, remove the rcscript bin dir from it */
		if ((token = getenv("PATH"))) {
			len = strlen(token);
			newpath = np = xmalloc(len + 1);
			while (token && *token) {
				p = strchr(token, ':');
				if (p) {
					*p++ = '\0';
					while (*p == ':')
						p++;
				}
				if (strcmp(token, RC_LIBEXECDIR "/bin") != 0 &&
				    strcmp(token, RC_LIBEXECDIR "/sbin") != 0)
				{
					len = strlen(token);
					if (np != newpath)
						*np++ = ':';
					memcpy(np, token, len);
					np += len;
				}
				token = p;
			}
			*np = '\0';
			unsetenv("PATH");
			setenv("PATH", newpath, 1);
		}

		stdin_fd = devnull_fd;
		stdout_fd = devnull_fd;
		stderr_fd = devnull_fd;
		if (redirect_stdout) {
			if ((stdout_fd = open(redirect_stdout,
				    O_WRONLY | O_CREAT | O_APPEND,
				    S_IRUSR | S_IWUSR)) == -1)
				eerrorx("%s: unable to open the logfile"
				    " for stdout `%s': %s",
				    applet, redirect_stdout, strerror(errno));
		}
		if (redirect_stderr) {
			if ((stderr_fd = open(redirect_stderr,
				    O_WRONLY | O_CREAT | O_APPEND,
				    S_IRUSR | S_IWUSR)) == -1)
				eerrorx("%s: unable to open the logfile"
				    " for stderr `%s': %s",
				    applet, redirect_stderr, strerror(errno));
		}

		if (background)
			dup2(stdin_fd, STDIN_FILENO);
		if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
			dup2(stdout_fd, STDOUT_FILENO);
		if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
			dup2(stderr_fd, STDERR_FILENO);

		for (i = getdtablesize() - 1; i >= 3; --i)
			close(i);

		setsid();
		execvp(exec, argv);
#ifdef HAVE_PAM
		if (changeuser != NULL && pamr == PAM_SUCCESS)
			pam_close_session(pamh, PAM_SILENT);
#endif
		eerrorx("%s: failed to exec `%s': %s",
		    applet, exec,strerror(errno));
	}
Ejemplo n.º 28
0
int main(int argc, char **argv) {
  hardened_shadow_openlog("su");

  if (!hardened_shadow_get_current_username(&current_username))
    errx(EXIT_FAILURE, "Cannot determine your user name.");

  parse_args(argc, argv);

  uid_t my_uid = getuid();
  bool is_root = (my_uid == 0);

  if (!is_root && (!isatty(STDIN_FILENO) || !ttyname(STDIN_FILENO)))
    errx(EXIT_FAILURE, "must be run from a terminal");

  const struct pam_conv pam_conversation = {
    misc_conv,
    NULL
  };
  pam_handle_t *pam_handle = NULL;
  int pam_rv = pam_start("su", target_username, &pam_conversation, &pam_handle);
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_start: error %d", pam_rv);
    su_fatal();
  }

  pam_rv = pam_set_item(pam_handle, PAM_TTY, ttyname(STDIN_FILENO));
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_set_item: %s",
                           pam_strerror(pam_handle, pam_rv));
    goto pam_cleanup;
  }

  pam_rv = pam_set_item(pam_handle, PAM_RUSER, current_username);
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_set_item: %s",
                           pam_strerror(pam_handle, pam_rv));
    goto pam_cleanup;
  }

  pam_rv = pam_fail_delay(pam_handle, 1000000);
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_fail_delay: %s",
                           pam_strerror(pam_handle, pam_rv));
    goto pam_cleanup;
  }

  pam_rv = pam_authenticate(pam_handle, 0);
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_authenticate: %s",
                           pam_strerror(pam_handle, pam_rv));
    goto pam_cleanup;
  }

  pam_rv = pam_acct_mgmt(pam_handle, 0);
  if (pam_rv != PAM_SUCCESS) {
    if (is_root) {
      warnx("%s (ignored)", pam_strerror(pam_handle, pam_rv));
    } else if (pam_rv == PAM_NEW_AUTHTOK_REQD) {
      pam_rv = pam_chauthtok(pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
      if (pam_rv != PAM_SUCCESS) {
	hardened_shadow_syslog(LOG_ERR, "pam_chauthtok: %s",
                               pam_strerror(pam_handle, pam_rv));
        goto pam_cleanup;
      }
    } else {
      hardened_shadow_syslog(LOG_ERR, "pam_acct_mgmt: %s",
                             pam_strerror(pam_handle, pam_rv));
      goto pam_cleanup;
    }
  }

  if (setgid(target_gid) != 0) {
    hardened_shadow_syslog(LOG_ERR, "bad group ID `%d' for user `%s': %s",
                           target_gid, target_username, strerror(errno));
    pam_rv = PAM_ABORT;
    goto pam_cleanup;
  }
  if (initgroups(target_username, target_gid) != 0) {
    hardened_shadow_syslog(LOG_ERR, "initgroups failed for user `%s': %s",
                           target_username, strerror(errno));
    pam_rv = PAM_ABORT;
    goto pam_cleanup;
  }

  pam_rv = pam_setcred(pam_handle, PAM_ESTABLISH_CRED);
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_setcred: %s",
                           pam_strerror(pam_handle, pam_rv));
    goto pam_cleanup;
  }

  pam_rv = pam_open_session(pam_handle, 0);
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_open_session: %s",
                           pam_strerror(pam_handle, pam_rv));
    goto pam_cred_cleanup;
  }

  char **pam_env = pam_getenvlist(pam_handle);
  if (!pam_env)
    errx(EXIT_FAILURE, "pam_getenvlist returned NULL");

  struct environment_options environment_options = {
    .pam_environment = pam_env,
    .preserve_environment = preserve_environment,
    .login_shell = login_shell,
    .target_username = target_username,
    .target_homedir = target_homedir,
    .target_shell = shell,
  };
  if (!hardened_shadow_prepare_environment(&environment_options)) {
    pam_rv = PAM_ABORT;
    goto pam_session_cleanup;
  }

  if (setuid(target_uid) != 0) {
    hardened_shadow_syslog(LOG_ERR, "bad user ID `%d' for user `%s': %s",
                           target_uid, target_username, strerror(errno));
    goto pam_session_cleanup;
  }

  int shell_argc = command ? 4 : 2;
  char **shell_argv = calloc(shell_argc, sizeof(*shell_argv));
  if (!shell_argv) {
    hardened_shadow_syslog(LOG_ERR, "memory allocation failure");
    goto pam_session_cleanup;
  }
  /* When argv[0] starts with a dash ("-"), bash will recognize
   * it as a login shell. This is what shadow-utils does. */
  shell_argv[0] = login_shell ? "-su" : shell;
  if (command) {
    shell_argv[1] = "-c";
    shell_argv[2] = command;
  }
  shell_argv[shell_argc - 1] = NULL;
  int status;
  if (!run_shell(shell, shell_argv, &status)) {
    pam_rv = PAM_ABORT;
    goto pam_session_cleanup;
  }
  free(shell_argv);

  pam_rv = pam_setcred(pam_handle, PAM_DELETE_CRED);
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_setcred: %s",
                           pam_strerror(pam_handle, pam_rv));
    pam_close_session(pam_handle, 0);
    pam_end(pam_handle, pam_rv);
    errx(EXIT_FAILURE, "pam_setcred");
  }

  pam_rv = pam_close_session(pam_handle, 0);
  if (pam_rv != PAM_SUCCESS) {
    hardened_shadow_syslog(LOG_ERR, "pam_close_session: %s",
                           pam_strerror(pam_handle, pam_rv));
    pam_end(pam_handle, pam_rv);
    errx(EXIT_FAILURE, "pam_close_session");
  }

  pam_end(pam_handle, pam_rv);

  free(shell);
  free(current_username);
  free(target_username);
  free(target_homedir);

  hardened_shadow_closelog();

  if (WIFEXITED(status))
    return WEXITSTATUS(status);

  return WTERMSIG(status) + 128;
pam_session_cleanup:
  pam_close_session(pam_handle, 0);
pam_cred_cleanup:
  pam_setcred(pam_handle, PAM_DELETE_CRED);
pam_cleanup:
  pam_end(pam_handle, pam_rv);
  su_fatal();
}
Ejemplo n.º 29
0
/**
 * Switch the process's effective and real user IDs to the ID associated with
 * the specified user name. Also switches to that user's group ID to the
 * primary group associated with the user.
 *
 * This function calls die() if anything fails.
 *
 * Parameters:
 *     user_name - name of user to which to switch
 *     uid       - current process user ID
 *     pid_file  - if non-NULL, specifies PID file path, ownership of which
 *                 should be changed to the user
 */
static void switch_user(const char *user_name, uid_t uid, const char *pid_file)
{
    struct  passwd *pw;
#if WITH_PAM
    int pamret;
    pam_handle_t *pamh;
    const char *pamuser;
    const char *failed_msg;
    struct passwd pwdstruct;
    char pwdbuf[256];
#endif /* WITH_PAM */

    if (uid != 0)
        die("Must be root to specify a different user.\n");

    if ( (pw = getpwnam(user_name)) == NULL )
        die("Can't find user \"%s\" in password file.\n", user_name);

#if WITH_PAM
        pamret = pam_start("daemonize", user, &conv, &pamh);
        if (pamret != PAM_SUCCESS) {
            syslog(LOG_WARNING, "pam_%s call failed: %s (%d)", "start",
                    pam_strerror(pamh, pamret), pamret);
        }

        pamret = pam_authenticate(pamh, 0);
        if (pamret != PAM_SUCCESS) {
            syslog(LOG_WARNING, "pam_%s call failed: %s (%d)", "authenticate",
                    pam_strerror(pamh, pamret), pamret);
        }
        /* check that the account is healthy */
        pamret = pam_acct_mgmt(pamh, 0);
        if (pamret != PAM_SUCCESS) {
            syslog(LOG_WARNING, "pam_%s call failed: %s (%d)", "acct_mgmt",
                    pam_strerror(pamh, pamret), pamret);
        }

        pamret = pam_open_session(pamh, 0);
        if (pamret != PAM_SUCCESS) {
            syslog(LOG_WARNING, "pam_%s call failed: %s (%d)", "open_session",
                    pam_strerror(pamh, pamret), pamret);
        }
        if (pamret == PAM_SUCCESS)
        {
            /* success */
            syslog(LOG_INFO, "pam_limits call success: %s (%d)",
                        pam_strerror(pamh, pamret), pamret);
        }

#endif /* WITH_PAM */

    if (setgid(pw->pw_gid) != 0)
        die("Can't set gid to %d: %s\n", pw->pw_gid, strerror (errno));

    /*
      For systems supporting multiple group memberships, make sure ALL
      groups are added to the process, just in case someone depends on them.

      Patch by Ken Farnen <*****@*****.**>, 18 February 2010. Modified
      to put the #ifdef in the config.h header, rather than in here.
    */
    if (initgroups(pw->pw_name, pw->pw_gid) == -1)
        die("Can't initialize secondary groups for \"%s\": %s\n",
            pw->pw_name, strerror (errno));

    if (pid_file != NULL)
    {
        verbose("Changing ownership of PID file to \"%s\" (%d)\n",
                user, pw->pw_uid);
        if (chown(pid_file, pw->pw_uid, pw->pw_gid) == -1)
        {
            die("Can't change owner of PID file \"%s\" to \"%s\" (%d): %s\n",
                pid_file, user, pw->pw_uid, strerror (errno));
        }
    }

    if (setegid(pw->pw_gid) != 0)
        die("Can't set egid to %d: %s\n", pw->pw_gid, strerror (errno));

    if (setuid(pw->pw_uid) != 0)
        die("Can't set uid to %d: %s\n", pw->pw_uid, strerror (errno));

    if (seteuid(pw->pw_uid) != 0)
        die("Can't set euid to %d: %s\n", pw->pw_uid, strerror (errno));

    /*
      Initialize environment to match new username.
      Patch by Ken Farnen <*****@*****.**>, 18 February 2010.
    */
    setenv("USER", pw->pw_name,1);
    setenv("LOGNAME", pw->pw_name,1);
    setenv("HOME", pw->pw_dir,1);
}
Ejemplo n.º 30
0
static Bool
StartClient (
    struct verify_info	*verify,
    struct display	*d,
    int			*pidp,
    char		*name,
    char		*passwd)
{
    char	**f, *home;
    char	*failsafeArgv[2];
    int	pid;
#ifdef HAS_SETUSERCONTEXT
    struct passwd* pwd;
#endif
#ifdef USE_PAM 
    pam_handle_t *pamh = thepamh();
#endif

    if (verify->argv) {
	Debug ("StartSession %s: ", verify->argv[0]);
	for (f = verify->argv; *f; f++)
		Debug ("%s ", *f);
	Debug ("; ");
    }
    if (verify->userEnviron) {
	for (f = verify->userEnviron; *f; f++)
		Debug ("%s ", *f);
	Debug ("\n");
    }
#ifdef USE_PAM
    if (pamh) pam_open_session(pamh, 0);
#endif    
    switch (pid = fork ()) {
    case 0:
	CleanUpChild ();
#ifdef XDMCP
	/* The chooser socket is not closed by CleanUpChild() */
	DestroyWellKnownSockets();
#endif

	/* Do system-dependent login setup here */

#ifdef USE_PAM
	/* pass in environment variables set by libpam and modules it called */
	if (pamh) {
	    long i;
	    char **pam_env = pam_getenvlist(pamh);
	    for(i = 0; pam_env && pam_env[i]; i++) {
		verify->userEnviron = putEnv(pam_env[i], verify->userEnviron);
	    }
	}
#endif


#ifndef AIXV3
#ifndef HAS_SETUSERCONTEXT
	if (setgid(verify->gid) < 0)
	{
	    LogError("setgid %d (user \"%s\") failed, errno=%d\n",
		     verify->gid, name, errno);
	    return (0);
	}
#if defined(BSD) && (BSD >= 199103)
	if (setlogin(name) < 0)
	{
	    LogError("setlogin for \"%s\" failed, errno=%d", name, errno);
	    return(0);
	}
#endif
#ifndef QNX4
	if (initgroups(name, verify->gid) < 0)
	{
	    LogError("initgroups for \"%s\" failed, errno=%d\n", name, errno);
	    return (0);
	}
#endif   /* QNX4 doesn't support multi-groups, no initgroups() */
#ifdef USE_PAM
	if (thepamh()) {
	    pam_setcred(thepamh(), PAM_ESTABLISH_CRED);
	}
#endif
	if (setuid(verify->uid) < 0)
	{
	    LogError("setuid %d (user \"%s\") failed, errno=%d\n",
		     verify->uid, name, errno);
	    return (0);
	}
#else /* HAS_SETUSERCONTEXT */
	/*
	 * Set the user's credentials: uid, gid, groups,
	 * environment variables, resource limits, and umask.
	 */
	pwd = getpwnam(name);
	if (pwd)
	{
	    if (setusercontext(NULL, pwd, pwd->pw_uid, LOGIN_SETALL) < 0)
	    {
		LogError("setusercontext for \"%s\" failed, errno=%d\n", name,
		    errno);
		return (0);
	    }
	    endpwent();
	}
	else
	{
	    LogError("getpwnam for \"%s\" failed, errno=%d\n", name, errno);
	    return (0);
	}
#endif /* HAS_SETUSERCONTEXT */
#else /* AIXV3 */
	/*
	 * Set the user's credentials: uid, gid, groups,
	 * audit classes, user limits, and umask.
	 */
	if (setpcred(name, NULL) == -1)
	{
	    LogError("setpcred for \"%s\" failed, errno=%d\n", name, errno);
	    return (0);
	}
#endif /* AIXV3 */

	/*
	 * for user-based authorization schemes,
	 * use the password to get the user's credentials.
	 */
#ifdef SECURE_RPC
	/* do like "keylogin" program */
	{
	    char    netname[MAXNETNAMELEN+1], secretkey[HEXKEYBYTES+1];
	    int	    nameret, keyret;
	    int	    len;
	    int     key_set_ok = 0;

	    nameret = getnetname (netname);
	    Debug ("User netname: %s\n", netname);
	    len = strlen (passwd);
	    if (len > 8)
		bzero (passwd + 8, len - 8);
	    keyret = getsecretkey(netname,secretkey,passwd);
	    Debug ("getsecretkey returns %d, key length %d\n",
		    keyret, strlen (secretkey));
	    /* is there a key, and do we have the right password? */
	    if (keyret == 1)
	    {
		if (*secretkey)
		{
		    keyret = key_setsecret(secretkey);
		    Debug ("key_setsecret returns %d\n", keyret);
		    if (keyret == -1)
			LogError ("failed to set NIS secret key\n");
		    else
			key_set_ok = 1;
		}
		else
		{
		    /* found a key, but couldn't interpret it */
		    LogError ("password incorrect for NIS principal \"%s\"\n",
			      nameret ? netname : name);
		}
	    }
	    if (!key_set_ok)
	    {
		/* remove SUN-DES-1 from authorizations list */
		int i, j;
		for (i = 0; i < d->authNum; i++)
		{
		    if (d->authorizations[i]->name_length == 9 &&
			memcmp(d->authorizations[i]->name, "SUN-DES-1", 9) == 0)
		    {
			for (j = i+1; j < d->authNum; j++)
			    d->authorizations[j-1] = d->authorizations[j];
			d->authNum--;
			break;
		    }
		}
	    }
	    bzero(secretkey, strlen(secretkey));
	}
#endif
#ifdef K5AUTH
	/* do like "kinit" program */
	{
	    int i, j;
	    int result;
	    extern char *Krb5CCacheName();

	    result = Krb5Init(name, passwd, d);
	    if (result == 0) {
		/* point session clients at the Kerberos credentials cache */
		verify->userEnviron =
		    setEnv(verify->userEnviron,
			   "KRB5CCNAME", Krb5CCacheName(d->name));
	    } else {
		for (i = 0; i < d->authNum; i++)
		{
		    if (d->authorizations[i]->name_length == 14 &&
			memcmp(d->authorizations[i]->name, "MIT-KERBEROS-5", 14) == 0)
		    {
			/* remove Kerberos from authorizations list */
			for (j = i+1; j < d->authNum; j++)
			    d->authorizations[j-1] = d->authorizations[j];
			d->authNum--;
			break;
		    }
		}
	    }
	}
#endif /* K5AUTH */
	bzero(passwd, strlen(passwd));
	SetUserAuthorization (d, verify);
	home = getEnv (verify->userEnviron, "HOME");
	if (home)
	    if (chdir (home) == -1) {
		LogError ("user \"%s\": cannot chdir to home \"%s\" (err %d), using \"/\"\n",
			  getEnv (verify->userEnviron, "USER"), home, errno);
		chdir ("/");
		verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
	    }
	if (verify->argv) {
		Debug ("executing session %s\n", verify->argv[0]);
		execute (verify->argv, verify->userEnviron);
		LogError ("Session \"%s\" execution failed (err %d)\n", verify->argv[0], errno);
	} else {
		LogError ("Session has no command/arguments\n");
	}
	failsafeArgv[0] = d->failsafeClient;
	failsafeArgv[1] = 0;
	execute (failsafeArgv, verify->userEnviron);
	exit (1);
    case -1:
	bzero(passwd, strlen(passwd));
	Debug ("StartSession, fork failed\n");
	LogError ("can't start session on \"%s\", fork failed, errno=%d\n",
		  d->name, errno);
	return 0;
    default:
	bzero(passwd, strlen(passwd));
	Debug ("StartSession, fork succeeded %d\n", pid);
	*pidp = pid;
	return 1;
    }
}