Пример #1
0
main()
{
        if (getuid() != 0) {
#if (defined(AIX) && defined(USE_SETREUID))
		/* setreuid is badly broken on AIX 4.1, we avoid it completely */
                fprintf(stderr,"avoiding possibly broken setreuid\n");
		exit(1);
#endif

		/* if not running as root then at least check to see if we get ENOSYS - this 
		   handles Linux 2.0.x with glibc 2.1 */
                fprintf(stderr,"not running as root: checking for ENOSYS\n");
		exit(have_syscall());
	}

	gain_root_privilege();
	gain_root_group_privilege();
	set_effective_gid(1);
	set_effective_uid(1);
	save_re_uid();
	restore_re_uid();
	gain_root_privilege();
	gain_root_group_privilege();
	become_user_permanently(1, 1);
	setuid(0);
	if (getuid() == 0) {
		fprintf(stderr,"uid not set permanently\n");
		exit(1);
	}

	printf("OK\n");

	exit(0);
}
Пример #2
0
static void gain_root(void)
{
	if (non_root_mode()) {
		return;
	}

	if (geteuid() != 0) {
		set_effective_uid(0);

		if (geteuid() != 0) {
			DEBUG(0,
			      ("Warning: You appear to have a trapdoor "
			       "uid system\n"));
		}
	}

	if (getegid() != 0) {
		set_effective_gid(0);

		if (getegid() != 0) {
			DEBUG(0,
			      ("Warning: You appear to have a trapdoor "
			       "gid system\n"));
		}
	}
}
Пример #3
0
void restore_re_uid_fromroot(void)
{
#if defined(USE_SETRESUID) || defined(USE_LINUX_THREAD_CREDENTIALS)
	samba_setresuid(saved_ruid, saved_euid, -1);
#elif USE_SETREUID
	samba_setreuid(saved_ruid, -1);
	samba_setreuid(-1,saved_euid);
#elif USE_SETUIDX
	samba_setuidx(ID_REAL, saved_ruid);
	samba_setuidx(ID_EFFECTIVE, saved_euid);
#else
	set_effective_uid(saved_euid);
	if (getuid() != saved_ruid)
		samba_setuid(saved_ruid);
	set_effective_uid(saved_euid);
#endif

	assert_uid(saved_ruid, saved_euid);
}
Пример #4
0
static void restore_re_uid_fromroot(void)
{
#if USE_SETRESUID
	setresuid(saved_ruid, saved_euid, -1);
#elif USE_SETREUID
	setreuid(saved_ruid, -1);
	setreuid(-1,saved_euid);
#elif USE_SETUIDX
	setuidx(ID_REAL, saved_ruid);
	setuidx(ID_EFFECTIVE, saved_euid);
#else
	set_effective_uid(saved_euid);
	if (getuid() != saved_ruid)
		setuid(saved_ruid);
	set_effective_uid(saved_euid);
#endif

	assert_uid(saved_ruid, saved_euid);
}
static bool become_uid(uid_t uid)
{
	/* Check for dodgy uid values */

	if (uid == (uid_t)-1 || 
	    ((sizeof(uid_t) == 2) && (uid == (uid_t)65535))) {
		if (!become_uid_done) {
			DEBUG(1,("WARNING: using uid %d is a security risk\n",
				 (int)uid));
			become_uid_done = true;
		}
	}

	/* Set effective user id */

	set_effective_uid(uid);

	DO_PROFILE_INC(uid_changes);
	return True;
}
Пример #6
0
void restore_re_uid(void)
{
	set_effective_uid(0);
	restore_re_uid_fromroot();
}
Пример #7
0
static void krb5_ticket_gain_handler(struct tevent_context *event_ctx,
				     struct tevent_timer *te,
				     struct timeval now,
				     void *private_data)
{
	struct WINBINDD_CCACHE_ENTRY *entry =
		talloc_get_type_abort(private_data, struct WINBINDD_CCACHE_ENTRY);
#ifdef HAVE_KRB5
	int ret;
	struct timeval t;
	struct WINBINDD_MEMORY_CREDS *cred_ptr = entry->cred_ptr;
	struct winbindd_domain *domain = NULL;
#endif

	DEBUG(10,("krb5_ticket_gain_handler called\n"));
	DEBUGADD(10,("event called for: %s, %s\n",
		entry->ccname, entry->username));

	TALLOC_FREE(entry->event);

#ifdef HAVE_KRB5

	if (!cred_ptr || !cred_ptr->pass) {
		DEBUG(10,("krb5_ticket_gain_handler: no memory creds\n"));
		return;
	}

	if ((domain = find_domain_from_name(entry->realm)) == NULL) {
		DEBUG(0,("krb5_ticket_gain_handler: unknown domain\n"));
		return;
	}

	if (!domain->online) {
		goto retry_later;
	}

	set_effective_uid(entry->uid);

	ret = kerberos_kinit_password_ext(entry->principal_name,
					  cred_ptr->pass,
					  0, /* hm, can we do time correction here ? */
					  &entry->refresh_time,
					  &entry->renew_until,
					  entry->ccname,
					  False, /* no PAC required anymore */
					  True,
					  WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
					  NULL);
	gain_root_privilege();

	if (ret) {
		DEBUG(3,("krb5_ticket_gain_handler: "
			"could not kinit: %s\n",
			error_message(ret)));
		/* evil. If we cannot do it, destroy any the __maybe__ 
		 * __existing__ ticket */
		ads_kdestroy(entry->ccname);
		goto retry_later;
	}

	DEBUG(10,("krb5_ticket_gain_handler: "
		"successful kinit for: %s in ccache: %s\n",
		entry->principal_name, entry->ccname));

	goto got_ticket;

  retry_later:
 
#if defined(DEBUG_KRB5_TKT_RENEWAL)
 	t = timeval_set(time(NULL) + 30, 0);
#else
	t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0);
#endif

	add_krb5_ticket_gain_handler_event(entry, t);
	return;

  got_ticket:

#if defined(DEBUG_KRB5_TKT_RENEWAL)
	t = timeval_set(time(NULL) + 30, 0);
#else
	t = timeval_set(krb5_event_refresh_time(entry->refresh_time), 0);
#endif

	if (entry->refresh_time == 0) {
		entry->refresh_time = t.tv_sec;
	}
	entry->event = tevent_add_timer(winbind_event_context(),
				       entry,
				       t,
				       krb5_ticket_refresh_handler,
				       entry);

	return;
#endif
}
Пример #8
0
static void krb5_ticket_refresh_handler(struct tevent_context *event_ctx,
					struct tevent_timer *te,
					struct timeval now,
					void *private_data)
{
	struct WINBINDD_CCACHE_ENTRY *entry =
		talloc_get_type_abort(private_data, struct WINBINDD_CCACHE_ENTRY);
#ifdef HAVE_KRB5
	int ret;
	time_t new_start;
	time_t expire_time = 0;
	struct WINBINDD_MEMORY_CREDS *cred_ptr = entry->cred_ptr;
#endif

	DEBUG(10,("krb5_ticket_refresh_handler called\n"));
	DEBUGADD(10,("event called for: %s, %s\n",
		entry->ccname, entry->username));

	TALLOC_FREE(entry->event);

#ifdef HAVE_KRB5

	/* Kinit again if we have the user password and we can't renew the old
	 * tgt anymore 
	 * NB
	 * This happens when machine are put to sleep for a very long time. */

	if (entry->renew_until < time(NULL)) {
rekinit:
		if (cred_ptr && cred_ptr->pass) {

			set_effective_uid(entry->uid);

			ret = kerberos_kinit_password_ext(entry->principal_name,
							  cred_ptr->pass,
							  0, /* hm, can we do time correction here ? */
							  &entry->refresh_time,
							  &entry->renew_until,
							  entry->ccname,
							  False, /* no PAC required anymore */
							  True,
							  WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
							  NULL);
			gain_root_privilege();

			if (ret) {
				DEBUG(3,("krb5_ticket_refresh_handler: "
					"could not re-kinit: %s\n",
					error_message(ret)));
				/* destroy the ticket because we cannot rekinit
				 * it, ignore error here */
				ads_kdestroy(entry->ccname);

				/* Don't break the ticket refresh chain: retry 
				 * refreshing ticket sometime later when KDC is 
				 * unreachable -- BoYang. More error code handling
				 * here? 
				 * */

				if ((ret == KRB5_KDC_UNREACH)
				    || (ret == KRB5_REALM_CANT_RESOLVE)) {
#if defined(DEBUG_KRB5_TKT_RENEWAL)
					new_start = time(NULL) + 30;
#else
					new_start = time(NULL) +
						    MAX(30, lp_winbind_cache_time());
#endif
					add_krb5_ticket_gain_handler_event(entry,
							timeval_set(new_start, 0));
					return;
				}
				TALLOC_FREE(entry->event);
				return;
			}

			DEBUG(10,("krb5_ticket_refresh_handler: successful re-kinit "
				"for: %s in ccache: %s\n",
				entry->principal_name, entry->ccname));

#if defined(DEBUG_KRB5_TKT_RENEWAL)
			new_start = time(NULL) + 30;
#else
			/* The tkt should be refreshed at one-half the period
			   from now to the expiration time */
			expire_time = entry->refresh_time;
			new_start = krb5_event_refresh_time(entry->refresh_time);
#endif
			goto done;
		} else {
				/* can this happen? 
				 * No cached credentials
				 * destroy ticket and refresh chain 
				 * */
				ads_kdestroy(entry->ccname);
				TALLOC_FREE(entry->event);
				return;
		}
	}

	set_effective_uid(entry->uid);

	ret = smb_krb5_renew_ticket(entry->ccname,
				    entry->principal_name,
				    entry->service,
				    &new_start);
#if defined(DEBUG_KRB5_TKT_RENEWAL)
	new_start = time(NULL) + 30;
#else
	expire_time = new_start;
	new_start = krb5_event_refresh_time(new_start);
#endif

	gain_root_privilege();

	if (ret) {
		DEBUG(3,("krb5_ticket_refresh_handler: "
			"could not renew tickets: %s\n",
			error_message(ret)));
		/* maybe we are beyond the renewing window */

		/* evil rises here, we refresh ticket failed,
		 * but the ticket might be expired. Therefore,
		 * When we refresh ticket failed, destory the 
		 * ticket */

		ads_kdestroy(entry->ccname);

		/* avoid breaking the renewal chain: retry in
		 * lp_winbind_cache_time() seconds when the KDC was not
		 * available right now. 
		 * the return code can be KRB5_REALM_CANT_RESOLVE. 
		 * More error code handling here? */

		if ((ret == KRB5_KDC_UNREACH) 
		    || (ret == KRB5_REALM_CANT_RESOLVE)) {
#if defined(DEBUG_KRB5_TKT_RENEWAL)
			new_start = time(NULL) + 30;
#else
			new_start = time(NULL) +
				    MAX(30, lp_winbind_cache_time());
#endif
			/* ticket is destroyed here, we have to regain it
			 * if it is possible */
			add_krb5_ticket_gain_handler_event(entry,
						timeval_set(new_start, 0));
			return;
		}

		/* This is evil, if the ticket was already expired.
		 * renew ticket function returns KRB5KRB_AP_ERR_TKT_EXPIRED.
		 * But there is still a chance that we can rekinit it. 
		 *
		 * This happens when user login in online mode, and then network
		 * down or something cause winbind goes offline for a very long time,
		 * and then goes online again. ticket expired, renew failed.
		 * This happens when machine are put to sleep for a long time,
		 * but shorter than entry->renew_util.
		 * NB
		 * Looks like the KDC is reachable, we want to rekinit as soon as
		 * possible instead of waiting some time later. */
		if ((ret == KRB5KRB_AP_ERR_TKT_EXPIRED)
		    || (ret == KRB5_FCC_NOFILE)) goto rekinit;

		return;
	}

done:
	/* in cases that ticket will be unrenewable soon, we don't try to renew ticket 
	 * but try to regain ticket if it is possible */
	if (entry->renew_until && expire_time
	     && (entry->renew_until <= expire_time)) {
		/* try to regain ticket 10 seconds before expiration */
		expire_time -= 10;
		add_krb5_ticket_gain_handler_event(entry,
					timeval_set(expire_time, 0));
		return;
	}

	if (entry->refresh_time == 0) {
		entry->refresh_time = new_start;
	}
	entry->event = tevent_add_timer(winbind_event_context(), entry,
				       timeval_set(new_start, 0),
				       krb5_ticket_refresh_handler,
				       entry);

#endif
}
Пример #9
0
void become_root_uid_only(void)
{
	save_re_uid();
	set_effective_uid(0);
}
Пример #10
0
/*******************************************************************
check on a DCE/DFS authentication
********************************************************************/
static BOOL dfs_auth(char *user, char *password)
{
	error_status_t err;
	int err2;
	int prterr;
	signed32 expire_time, current_time;
	boolean32 password_reset;
	struct passwd *pw;
	sec_passwd_rec_t passwd_rec;
	sec_login_auth_src_t auth_src = sec_login_auth_src_network;
	unsigned char dce_errstr[dce_c_error_string_len];
	gid_t egid;

	if (dcelogin_atmost_once)
		return (False);

#ifdef HAVE_CRYPT
	/*
	 * We only go for a DCE login context if the given password
	 * matches that stored in the local password file.. 
	 * Assumes local passwd file is kept in sync w/ DCE RGY!
	 */

	if (strcmp((char *)crypt(password, this_salt), this_crypted))
	{
		return (False);
	}
#endif

	sec_login_get_current_context(&my_dce_sec_context, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr));

		return (False);
	}

	sec_login_certify_identity(my_dce_sec_context, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr));

		return (False);
	}

	sec_login_get_expiration(my_dce_sec_context, &expire_time, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr));

		return (False);
	}

	time(&current_time);

	if (expire_time < (current_time + 60))
	{
		struct passwd *pw;
		sec_passwd_rec_t *key;

		sec_login_get_pwent(my_dce_sec_context,
				    (sec_login_passwd_t *) & pw, &err);
		if (err != error_status_ok)
		{
			dce_error_inq_text(err, dce_errstr, &err2);
			DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));

			return (False);
		}

		sec_login_refresh_identity(my_dce_sec_context, &err);
		if (err != error_status_ok)
		{
			dce_error_inq_text(err, dce_errstr, &err2);
			DEBUG(0, ("DCE can't refresh identity. %s\n",
				  dce_errstr));

			return (False);
		}

		sec_key_mgmt_get_key(rpc_c_authn_dce_secret, NULL,
				     (unsigned char *)pw->pw_name,
				     sec_c_key_version_none,
				     (void **)&key, &err);
		if (err != error_status_ok)
		{
			dce_error_inq_text(err, dce_errstr, &err2);
			DEBUG(0, ("DCE can't get key for %s. %s\n",
				  pw->pw_name, dce_errstr));

			return (False);
		}

		sec_login_valid_and_cert_ident(my_dce_sec_context, key,
					       &password_reset, &auth_src,
					       &err);
		if (err != error_status_ok)
		{
			dce_error_inq_text(err, dce_errstr, &err2);
			DEBUG(0,
			      ("DCE can't validate and certify identity for %s. %s\n",
			       pw->pw_name, dce_errstr));
		}

		sec_key_mgmt_free_key(key, &err);
		if (err != error_status_ok)
		{
			dce_error_inq_text(err, dce_errstr, &err2);
			DEBUG(0, ("DCE can't free key.\n", dce_errstr));
		}
	}

	if (sec_login_setup_identity((unsigned char *)user,
				     sec_login_no_flags,
				     &my_dce_sec_context, &err) == 0)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE Setup Identity for %s failed: %s\n",
			  user, dce_errstr));
		return (False);
	}

	sec_login_get_pwent(my_dce_sec_context,
			    (sec_login_passwd_t *) & pw, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));

		return (False);
	}

	sec_login_purge_context(&my_dce_sec_context, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE can't purge context. %s\n", dce_errstr));

		return (False);
	}

	/*
	 * NB. I'd like to change these to call something like change_to_user()
	 * instead but currently we don't have a connection
	 * context to become the correct user. This is already
	 * fairly platform specific code however, so I think
	 * this should be ok. I have added code to go
	 * back to being root on error though. JRA.
	 */

	egid = getegid();

	set_effective_gid(pw->pw_gid);
	set_effective_uid(pw->pw_uid);

	if (sec_login_setup_identity((unsigned char *)user,
				     sec_login_no_flags,
				     &my_dce_sec_context, &err) == 0)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE Setup Identity for %s failed: %s\n",
			  user, dce_errstr));
		goto err;
	}

	sec_login_get_pwent(my_dce_sec_context,
			    (sec_login_passwd_t *) & pw, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
		goto err;
	}

	passwd_rec.version_number = sec_passwd_c_version_none;
	passwd_rec.pepper = NULL;
	passwd_rec.key.key_type = sec_passwd_plain;
	passwd_rec.key.tagged_union.plain = (idl_char *) password;

	sec_login_validate_identity(my_dce_sec_context,
				    &passwd_rec, &password_reset,
				    &auth_src, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0,
		      ("DCE Identity Validation failed for principal %s: %s\n",
		       user, dce_errstr));
		goto err;
	}

	sec_login_certify_identity(my_dce_sec_context, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE certify identity failed: %s\n", dce_errstr));
		goto err;
	}

	if (auth_src != sec_login_auth_src_network)
	{
		DEBUG(0, ("DCE context has no network credentials.\n"));
	}

	sec_login_set_context(my_dce_sec_context, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0,
		      ("DCE login failed for principal %s, cant set context: %s\n",
		       user, dce_errstr));

		sec_login_purge_context(&my_dce_sec_context, &err);
		goto err;
	}

	sec_login_get_pwent(my_dce_sec_context,
			    (sec_login_passwd_t *) & pw, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr));
		goto err;
	}

	DEBUG(0, ("DCE login succeeded for principal %s on pid %d\n",
		  user, sys_getpid()));

	DEBUG(3, ("DCE principal: %s\n"
		  "          uid: %d\n"
		  "          gid: %d\n",
		  pw->pw_name, pw->pw_uid, pw->pw_gid));
	DEBUG(3, ("         info: %s\n"
		  "          dir: %s\n"
		  "        shell: %s\n",
		  pw->pw_gecos, pw->pw_dir, pw->pw_shell));

	sec_login_get_expiration(my_dce_sec_context, &expire_time, &err);
	if (err != error_status_ok)
	{
		dce_error_inq_text(err, dce_errstr, &err2);
		DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr));
		goto err;
	}

	set_effective_uid(0);
	set_effective_gid(0);

	DEBUG(0,
	      ("DCE context expires: %s", asctime(localtime(&expire_time))));

	dcelogin_atmost_once = 1;
	return (True);

      err:

	/* Go back to root, JRA. */
	set_effective_uid(0);
	set_effective_gid(egid);
	return (False);
}
Пример #11
0
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
  int r;
  struct dqblk D;
  uid_t euser_id;
#if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
  char dev_disk[256];
  SMB_STRUCT_STAT S;

  /* find the block device file */

#ifdef HPUX
  /* Need to set the cache flag to 1 for HPUX. Seems
   * to have a significant performance boost when
   * lstat calls on /dev access this function.
   */
  if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
#else
  if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) 
	return (False);
#endif /* ifdef HPUX */

#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */

  euser_id = geteuid();

#ifdef HPUX
  /* for HPUX, real uid must be same as euid to execute quotactl for euid */
  save_re_uid();
  if (set_re_uid() != 0) return False;
  
  r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);

  restore_re_uid();
#else 
#if defined(__FreeBSD__) || defined(__OpenBSD__)
  {
    /* FreeBSD patches from Marty Moll <*****@*****.**> */
    gid_t egrp_id;
 
    save_re_uid();
    set_effective_uid(0);

    egrp_id = getegid();
    r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);

    /* As FreeBSD has group quotas, if getting the user
       quota fails, try getting the group instead. */
    if (r) {
	    r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
    }

    restore_re_uid();
  }
#elif defined(AIX)
  /* AIX has both USER and GROUP quotas: 
     Get the USER quota ([email protected]) */
  r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
  r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
#endif /* HPUX */

  /* Use softlimit to determine disk space, except when it has been exceeded */
#if defined(__FreeBSD__) || defined(__OpenBSD__)
  *bsize = DEV_BSIZE;
#else /* !__FreeBSD__ && !__OpenBSD__ */
  *bsize = 1024;
#endif /*!__FreeBSD__ && !__OpenBSD__ */

  if (r)
    {
      if (errno == EDQUOT) 
	{
 	  *dfree =0;
 	  *dsize =D.dqb_curblocks;
 	  return (True);
	}
      else return(False);
    }

  /* If softlimit is zero, set it equal to hardlimit.
   */

  if (D.dqb_bsoftlimit==0)
    D.dqb_bsoftlimit = D.dqb_bhardlimit;

  if (D.dqb_bsoftlimit==0)
    return(False);
  /* Use softlimit to determine disk space, except when it has been exceeded */
  if ((D.dqb_curblocks>D.dqb_bsoftlimit)
#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
#endif
    ) {
      *dfree = 0;
      *dsize = D.dqb_curblocks;
    }
  else {
    *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
    *dsize = D.dqb_bsoftlimit;
  }
  return (True);
}
Пример #12
0
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
  uid_t euser_id;
  int r;
  struct dqblk D;
  struct fs_disk_quota        F;
  SMB_STRUCT_STAT S;
  FILE *fp;
  struct mntent *mnt;
  SMB_DEV_T devno;
  int found;
  
  /* find the block device file */
  
  if ( sys_stat(path, &S) == -1 ) {
    return(False) ;
  }

  devno = S.st_dev ;
  
  fp = setmntent(MOUNTED,"r");
  found = False ;
  
  while ((mnt = getmntent(fp))) {
    if ( sys_stat(mnt->mnt_dir,&S) == -1 )
      continue ;
    if (S.st_dev == devno) {
      found = True ;
      break ;
    }
  }
  endmntent(fp) ;
  
  if (!found) {
    return(False);
  }

  euser_id=geteuid();
  save_re_uid();
  set_effective_uid(0);  

  /* Use softlimit to determine disk space, except when it has been exceeded */

  *bsize = 512;

  if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
  {
    r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);

    restore_re_uid();

    if (r==-1)
      return(False);
        
    /* Use softlimit to determine disk space, except when it has been exceeded */
    if (
        (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
        (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
        (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
        (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
       )
    {
      *dfree = 0;
      *dsize = D.dqb_curblocks;
    }
    else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
    {
      return(False);
    }
    else 
    {
      *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
      *dsize = D.dqb_bsoftlimit;
    }

  }
  else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
  {
    r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);

    restore_re_uid();

    if (r==-1)
      return(False);
        
    /* Use softlimit to determine disk space, except when it has been exceeded */
    if (
        (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
        (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
        (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
        (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
       )
    {
      *dfree = 0;
      *dsize = F.d_bcount;
    }
    else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
    {
      return(False);
    }
    else 
    {
      *dfree = (F.d_blk_softlimit - F.d_bcount);
      *dsize = F.d_blk_softlimit;
    }

  }
  else
  {
	  restore_re_uid();
	  return(False);
  }

  return (True);

}
Пример #13
0
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
	uid_t euser_id;
	int ret;
	struct dqblk D;
#if defined(SUNOS5)
	struct quotctl command;
	int file;
	static struct mnttab mnt;
	static pstring name;
	pstring devopt;
#else /* SunOS4 */
	struct mntent *mnt;
	static pstring name;
#endif
	FILE *fd;
	SMB_STRUCT_STAT sbuf;
	SMB_DEV_T devno ;
	static SMB_DEV_T devno_cached = 0 ;
	static int found ;

	euser_id = geteuid();
  
	if ( sys_stat(path,&sbuf) == -1 )
		return(False) ;
  
	devno = sbuf.st_dev ;
	DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno));
	if ( devno != devno_cached ) {
		devno_cached = devno ;
#if defined(SUNOS5)
		if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
			return(False) ;
    
		found = False ;
		slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno);
		while (getmntent(fd, &mnt) == 0) {
			if( !hasmntopt(&mnt, devopt) )
				continue;

			DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));

			/* quotas are only on vxfs, UFS or NFS */
			if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
				strcmp( mnt.mnt_fstype, "nfs" ) == 0    ||
				strcmp( mnt.mnt_fstype, "vxfs" ) == 0  ) { 
					found = True ;
					break;
			}
		}
    
		pstrcpy(name,mnt.mnt_mountp) ;
		pstrcat(name,"/quotas") ;
		fclose(fd) ;
#else /* SunOS4 */
		if ((fd = setmntent(MOUNTED, "r")) == NULL)
			return(False) ;
    
		found = False ;
		while ((mnt = getmntent(fd)) != NULL) {
			if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
				continue ;
			DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev));
			if (sbuf.st_dev == devno) {
				found = True ;
				break;
			}
		}
    
		pstrcpy(name,mnt->mnt_fsname) ;
		endmntent(fd) ;
#endif
	}

	if ( ! found )
		return(False) ;

	save_re_uid();
	set_effective_uid(0);

#if defined(SUNOS5)
	if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
		BOOL retval;
		DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
		retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
		restore_re_uid();
		return retval;
	}

	DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
	if((file=sys_open(name, O_RDONLY,0))<0) {
		restore_re_uid();
		return(False);
	}
	command.op = Q_GETQUOTA;
	command.uid = euser_id;
	command.addr = (caddr_t) &D;
	ret = ioctl(file, Q_QUOTACTL, &command);
	close(file);
#else
	DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
	ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
#endif

	restore_re_uid();

	if (ret < 0) {
		DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));

#if defined(SUNOS5) && defined(VXFS_QUOTA)
		/* If normal quotactl() fails, try vxfs private calls */
		set_effective_uid(euser_id);
		DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
		if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
			BOOL retval;
			retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
			return(retval);
		}
#else
		return(False);
#endif
	}

	/* If softlimit is zero, set it equal to hardlimit.
	 */
  
	if (D.dqb_bsoftlimit==0)
		D.dqb_bsoftlimit = D.dqb_bhardlimit;

	/* Use softlimit to determine disk space. A user exceeding the quota is told
	 * that there's no space left. Writes might actually work for a bit if the
	 * hardlimit is set higher than softlimit. Effectively the disk becomes
	 * made of rubber latex and begins to expand to accommodate the user :-)
	 */

	if (D.dqb_bsoftlimit==0)
		return(False);
	*bsize = DEV_BSIZE;
	*dsize = D.dqb_bsoftlimit;

	if (D.dqb_curblocks > D.dqb_bsoftlimit) {
		*dfree = 0;
		*dsize = D.dqb_curblocks;
	} else
		*dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
      
	DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
		path,(double)*bsize,(double)*dfree,(double)*dsize));

	return(True);
}
Пример #14
0
BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
	int r;
	SMB_STRUCT_STAT S;
	FILE *fp;
	LINUX_SMB_DISK_QUOTA D;
	struct mntent *mnt;
	SMB_DEV_T devno;
	int found;
	uid_t euser_id;

	euser_id = geteuid();
  
	/* find the block device file */
  
	if ( sys_stat(path, &S) == -1 )
		return(False) ;

	devno = S.st_dev ;
  
	fp = setmntent(MOUNTED,"r");
	found = False ;
  
	while ((mnt = getmntent(fp))) {
		if ( sys_stat(mnt->mnt_dir,&S) == -1 )
			continue ;

		if (S.st_dev == devno) {
			found = True ;
			break;
		}
	}

	endmntent(fp) ;
  
	if (!found)
		return(False);

	save_re_uid();
	set_effective_uid(0);  

	if (strcmp(mnt->mnt_type, "xfs")) {
		r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, &D);
		if (r == -1) {
			r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, &D);
			if (r == -1)
				r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, &D);
		}
	} else {
		r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, &D);
	}

	restore_re_uid();

	/* Use softlimit to determine disk space, except when it has been exceeded */
	*bsize = D.bsize;
	if (r == -1) {
		if (errno == EDQUOT) {
			*dfree =0;
			*dsize =D.curblocks;
			return (True);
		} else {
			return(False);
		}
	}

	/* Use softlimit to determine disk space, except when it has been exceeded */
	if (
		(D.softlimit && D.curblocks >= D.softlimit) ||
		(D.hardlimit && D.curblocks >= D.hardlimit) ||
		(D.isoftlimit && D.curinodes >= D.isoftlimit) ||
		(D.ihardlimit && D.curinodes>=D.ihardlimit)
	) {
		*dfree = 0;
		*dsize = D.curblocks;
	} else if (D.softlimit==0 && D.hardlimit==0) {
		return(False);
	} else {
		if (D.softlimit == 0)
			D.softlimit = D.hardlimit;
		*dfree = D.softlimit - D.curblocks;
		*dsize = D.softlimit;
	}

	return (True);
}
Пример #15
0
BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
  uid_t user_id, euser_id;
  int ret;
  struct vx_dqblk D;
  struct vx_quotctl quotabuf;
  struct vx_genioctl genbuf;
  pstring qfname;
  int file;

  /*
   * "name" may or may not include a trailing "/quotas".
   * Arranging consistency of calling here in "quotas.c" may not be easy and
   * it might be easier to examine and adjust it here.
   * Fortunately, VxFS seems not to mind at present.
   */
  pstrcpy(qfname, name) ;
  /* pstrcat(qfname, "/quotas") ; */	/* possibly examine and adjust "name" */

  euser_id = geteuid();
  set_effective_uid(0);

  DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
  if((file=sys_open(qfname, O_RDONLY,0))<0) {
    set_effective_uid(euser_id);
    return(False);
  }
  genbuf.ioc_cmd = VX_QUOTACTL;
  genbuf.ioc_up = (void *) &quotabuf;

  quotabuf.cmd = VX_GETQUOTA;
  quotabuf.uid = euser_id;
  quotabuf.addr = (caddr_t) &D;
  ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
  close(file);

  set_effective_uid(euser_id);

  if (ret < 0) {
    DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
    return(False);
  }

  /* If softlimit is zero, set it equal to hardlimit.
   */

  if (D.dqb_bsoftlimit==0)
    D.dqb_bsoftlimit = D.dqb_bhardlimit;

  /* Use softlimit to determine disk space. A user exceeding the quota is told
   * that there's no space left. Writes might actually work for a bit if the
   * hardlimit is set higher than softlimit. Effectively the disk becomes
   * made of rubber latex and begins to expand to accommodate the user :-)
   */
  DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
         path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
         D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));

  if (D.dqb_bsoftlimit==0)
    return(False);
  *bsize = DEV_BSIZE;
  *dsize = D.dqb_bsoftlimit;

  if (D.dqb_curblocks > D.dqb_bsoftlimit) {
     *dfree = 0;
     *dsize = D.dqb_curblocks;
  } else
    *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
      
  DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
         path,(double)*bsize,(double)*dfree,(double)*dsize));

  return(True);
}