Exemple #1
0
static struct spwd *
getspnam_a (const char *name)
{
  int err;
  long bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
  struct spwd *ret = NULL;
  struct spwd *buf;

  if (bufsize <= 0)
    bufsize = 8192;

  buf = malloc (sizeof(struct spwd) + bufsize);
  if (buf == NULL)
    {
      errno = ENOMEM;
      return NULL;
    }

  err = getspnam_r (name, buf, (char *)(buf + 1), bufsize, &ret);

  if (ret == NULL)
    {
      free (buf);
      if (err == 0)
        err = ENOENT;
      errno = err;
    }

  return ret;
}
Exemple #2
0
int checkpasswd(char *user, char *pass)
{
#if defined(FREEBSD) || defined(__linux__) || defined(MACOSX)
    struct passwd *pwd;
#elif SOLARIS
    struct spwd *spwd, sp;
    char   buf[512];
#endif
    int matched = 0;

    if (user == NULL) {
        /* user must be specified */
        return(-1);
    }

#if defined(FREEBSD) || defined(__linux__) || defined(MACOSX)
    setreuid(PROCUID, 0);
    pwd = getpwnam(user);
    setreuid(0, PROCUID);
    if (pwd == NULL) {
        /* error in getpwnam */
        return(-1);
    }
    if (pwd->pw_passwd == NULL && pass == NULL) {
        /* null password matched */
        return(0);
    }
    if (*pwd->pw_passwd) {
        if (strcmp(pwd->pw_passwd, crypt(pass, pwd->pw_passwd)) == 0) {
            matched = 1;
        }
    }
    memset(pwd->pw_passwd, 0, strlen(pwd->pw_passwd));

#elif SOLARIS
    setreuid(PROCUID, 0);
    spwd = getspnam_r(user, &sp, buf, sizeof buf);
    setreuid(0, PROCUID);
    if (spwd == NULL) {
        /* error in getspnam */
        return(-1);
    }
    if (spwd->sp_pwdp == NULL && pass == NULL) {
        /* null password matched */
        return(0);
    }
    if (*spwd->sp_pwdp) {
        if (strcmp(spwd->sp_pwdp, crypt(pass, spwd->sp_pwdp)) == 0) {
            matched = 1;
        }
    }
    memset(spwd->sp_pwdp, 0, strlen(spwd->sp_pwdp));
#endif

    if (matched) {
        return(0);
    } else {
        return(-1);
    }
}
int correct_password(const struct passwd *pw)
{
	char *unencrypted, *encrypted;
	const char *correct;
#if ENABLE_FEATURE_SHADOWPASSWDS
	/* Using _r function to avoid pulling in static buffers */
	struct spwd spw;
	struct spwd *result;
	char buffer[256];
#endif

	correct = pw->pw_passwd;
#if ENABLE_FEATURE_SHADOWPASSWDS
	if (LONE_CHAR(pw->pw_passwd, 'x') || LONE_CHAR(pw->pw_passwd, '*')) {
		if (getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result))
			bb_error_msg("no valid shadow password, checking ordinary one");
		else
			correct = spw.sp_pwdp;
	}
#endif

	if (!correct || correct[0] == '\0')
		return 1;

	unencrypted = bb_askpass(0, "Password: ");
	if (!unencrypted) {
		return 0;
	}
	encrypted = crypt(unencrypted, correct);
	memset(unencrypted, 0, strlen(unencrypted));
	return strcmp(encrypted, correct) == 0;
}
/**
 * Check the credentials and return the gid/uid of user.
 *
 * @param    pszUser     username
 * @param    pszPasswd   password
 * @param    gid         where to store the GID of the user
 * @param    uid         where to store the UID of the user
 * @returns IPRT status code
 */
static int rtCheckCredentials(const char *pszUser, const char *pszPasswd, gid_t *pGid, uid_t *pUid)
{
#if defined(RT_OS_LINUX)
    struct passwd *pw;

    pw = getpwnam(pszUser);
    if (!pw)
        return VERR_PERMISSION_DENIED;

    if (!pszPasswd)
        pszPasswd = "";

    struct spwd *spwd;
    /* works only if /etc/shadow is accessible */
    spwd = getspnam(pszUser);
    if (spwd)
        pw->pw_passwd = spwd->sp_pwdp;

    /* be reentrant */
    struct crypt_data *data = (struct crypt_data*)RTMemTmpAllocZ(sizeof(*data));
    char *pszEncPasswd = crypt_r(pszPasswd, pw->pw_passwd, data);
    int fCorrect = !strcmp(pszEncPasswd, pw->pw_passwd);
    RTMemTmpFree(data);
    if (!fCorrect)
        return VERR_PERMISSION_DENIED;

    *pGid = pw->pw_gid;
    *pUid = pw->pw_uid;
    return VINF_SUCCESS;

#elif defined(RT_OS_SOLARIS)
    struct passwd *ppw, pw;
    char szBuf[1024];

    if (getpwnam_r(pszUser, &pw, szBuf, sizeof(szBuf), &ppw) != 0 || ppw == NULL)
        return VERR_PERMISSION_DENIED;

    if (!pszPasswd)
        pszPasswd = "";

    struct spwd spwd;
    char szPwdBuf[1024];
    /* works only if /etc/shadow is accessible */
    if (getspnam_r(pszUser, &spwd, szPwdBuf, sizeof(szPwdBuf)) != NULL)
        ppw->pw_passwd = spwd.sp_pwdp;

    char *pszEncPasswd = crypt(pszPasswd, ppw->pw_passwd);
    if (strcmp(pszEncPasswd, ppw->pw_passwd))
        return VERR_PERMISSION_DENIED;

    *pGid = ppw->pw_gid;
    *pUid = ppw->pw_uid;
    return VINF_SUCCESS;

#else
    NOREF(pszUser); NOREF(pszPasswd); NOREF(pGid); NOREF(pUid);
    return VERR_PERMISSION_DENIED;
#endif
}
Exemple #5
0
struct spwd *
getspnam(const char *nam)
{
	nss_XbyY_buf_t	*b = get_spbuf();

	return (b == NULL ? NULL :
	    getspnam_r(nam, b->result, b->buffer, b->buflen));
}
int correct_password(const struct passwd *pw)
{
	char *unencrypted, *encrypted;
	const char *correct;
	int r;
#if ENABLE_FEATURE_SHADOWPASSWDS
	/* Using _r function to avoid pulling in static buffers */
	struct spwd spw;
	char buffer[256];
#endif

	/* fake salt. crypt() can choke otherwise. */
	correct = "aa";
	if (!pw) {
		/* "aa" will never match */
		goto fake_it;
	}
	correct = pw->pw_passwd;
#if ENABLE_FEATURE_SHADOWPASSWDS
	if ((correct[0] == 'x' || correct[0] == '*') && !correct[1]) {
		/* getspnam_r may return 0 yet set result to NULL.
		 * At least glibc 2.4 does this. Be extra paranoid here. */
		struct spwd *result = NULL;
		r = getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result);
		correct = (r || !result) ? "aa" : result->sp_pwdp;
	}
#endif

	if (!correct[0]) /* empty password field? */
		return 1;

 fake_it:
	unencrypted = bb_askpass(0, "Password: ");
	if (!unencrypted) {
		return 0;
	}
	encrypted = pw_encrypt(unencrypted, correct, 1);
	r = (strcmp(encrypted, correct) == 0);
	free(encrypted);
	memset(unencrypted, 0, strlen(unencrypted));
	return r;
}
Exemple #7
0
static const char *get_passwd(const struct passwd *pw, char buffer[SHADOW_BUFSIZE])
{
	const char *pass;

	if (!pw)
		return "aa"; /* "aa" will never match */

	pass = pw->pw_passwd;
#if ENABLE_FEATURE_SHADOWPASSWDS
	/* Using _r function to avoid pulling in static buffers */
	if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) {
		struct spwd spw;
		int r;
		/* getspnam_r may return 0 yet set result to NULL.
		 * At least glibc 2.4 does this. Be extra paranoid here. */
		struct spwd *result = NULL;
		r = getspnam_r(pw->pw_name, &spw, buffer, SHADOW_BUFSIZE, &result);
		pass = (r || !result) ? "aa" : result->sp_pwdp;
	}
#endif
	return pass;
}
int sulogin_main(int argc, char **argv)
{
	char *cp;
	int timeout = 0;
	char *timeout_arg;
	struct passwd *pwd;
	const char *shell;
#if ENABLE_FEATURE_SHADOWPASSWDS
	/* Using _r function to avoid pulling in static buffers */
	char buffer[256];
	struct spwd spw;
#endif

	logmode = LOGMODE_BOTH;
	openlog(applet_name, 0, LOG_AUTH);

	if (getopt32(argv, "t:", &timeout_arg)) {
		timeout = xatoi_u(timeout_arg);
	}

	if (argv[optind]) {
		close(0);
		close(1);
		dup(xopen(argv[optind], O_RDWR));
		close(2);
		dup(0);
	}

	if (!isatty(0) || !isatty(1) || !isatty(2)) {
		logmode = LOGMODE_SYSLOG;
		bb_error_msg_and_die("not a tty");
	}

	/* Clear dangerous stuff, set PATH */
	sanitize_env_for_suid();

// bb_askpass() already handles this
//	signal(SIGALRM, catchalarm);

	pwd = getpwuid(0);
	if (!pwd) {
		goto auth_error;
	}

#if ENABLE_FEATURE_SHADOWPASSWDS
	{
		/* getspnam_r may return 0 yet set result to NULL.
		 * At least glibc 2.4 does this. Be extra paranoid here. */
		struct spwd *result = NULL;
		int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result);
		if (r || !result) {
			goto auth_error;
		}
		pwd->pw_passwd = result->sp_pwdp;
	}
#endif

	while (1) {
		/* cp points to a static buffer that is zeroed every time */
		cp = bb_askpass(timeout,
				"Give root password for system maintenance\n"
				"(or type Control-D for normal startup):");

		if (!cp || !*cp) {
			bb_info_msg("Normal startup");
			return 0;
		}
		if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) {
			break;
		}
		bb_do_delay(FAIL_DELAY);
		bb_error_msg("login incorrect");
	}
	memset(cp, 0, strlen(cp));
//	signal(SIGALRM, SIG_DFL);

	bb_info_msg("System Maintenance Mode");

	USE_SELINUX(renew_current_security_context());

	shell = getenv("SUSHELL");
	if (!shell)
		shell = getenv("sushell");
	if (!shell) {
		shell = "/bin/sh";
		if (pwd->pw_shell[0])
			shell = pwd->pw_shell;
	}
	/* Exec login shell with no additional parameters. Never returns. */
	run_shell(shell, 1, NULL, NULL);

 auth_error:
	bb_error_msg_and_die("no password entry for root");
}
struct spwd *getspnam(const char* name) {
  struct spwd *tmp;
  getspnam_r(name,&__shadow_pw,__shadow_buf,sizeof(__shadow_buf),&tmp);
  return tmp;
}
/**
 * Check the credentials and return the gid/uid of user.
 *
 * @param    pszUser     username
 * @param    pszPasswd   password
 * @param    gid         where to store the GID of the user
 * @param    uid         where to store the UID of the user
 * @returns IPRT status code
 */
static int rtCheckCredentials(const char *pszUser, const char *pszPasswd, gid_t *pGid, uid_t *pUid)
{
#if defined(RT_OS_LINUX)
    struct passwd *pw;

    pw = getpwnam(pszUser);
    if (!pw)
        return VERR_AUTHENTICATION_FAILURE;

    if (!pszPasswd)
        pszPasswd = "";

    struct spwd *spwd;
    /* works only if /etc/shadow is accessible */
    spwd = getspnam(pszUser);
    if (spwd)
        pw->pw_passwd = spwd->sp_pwdp;

    /* Default fCorrect=true if no password specified. In that case, pw->pw_passwd
     * must be NULL (no password set for this user). Fail if a password is specified
     * but the user does not have one assigned. */
    int fCorrect = !pszPasswd || !*pszPasswd;
    if (pw->pw_passwd && *pw->pw_passwd)
    {
        struct crypt_data *data = (struct crypt_data*)RTMemTmpAllocZ(sizeof(*data));
        /* be reentrant */
        char *pszEncPasswd = crypt_r(pszPasswd, pw->pw_passwd, data);
        fCorrect = pszEncPasswd && !strcmp(pszEncPasswd, pw->pw_passwd);
        RTMemTmpFree(data);
    }
    if (!fCorrect)
        return VERR_AUTHENTICATION_FAILURE;

    *pGid = pw->pw_gid;
    *pUid = pw->pw_uid;
    return VINF_SUCCESS;

#elif defined(RT_OS_SOLARIS)
    struct passwd *ppw, pw;
    char szBuf[1024];

    if (getpwnam_r(pszUser, &pw, szBuf, sizeof(szBuf), &ppw) != 0 || ppw == NULL)
        return VERR_AUTHENTICATION_FAILURE;

    if (!pszPasswd)
        pszPasswd = "";

    struct spwd spwd;
    char szPwdBuf[1024];
    /* works only if /etc/shadow is accessible */
    if (getspnam_r(pszUser, &spwd, szPwdBuf, sizeof(szPwdBuf)) != NULL)
        ppw->pw_passwd = spwd.sp_pwdp;

    char *pszEncPasswd = crypt(pszPasswd, ppw->pw_passwd);
    if (strcmp(pszEncPasswd, ppw->pw_passwd))
        return VERR_AUTHENTICATION_FAILURE;

    *pGid = ppw->pw_gid;
    *pUid = ppw->pw_uid;
    return VINF_SUCCESS;

#else
    NOREF(pszUser); NOREF(pszPasswd); NOREF(pGid); NOREF(pUid);
    return VERR_AUTHENTICATION_FAILURE;
#endif
}
Exemple #11
0
int sulogin_main(int argc UNUSED_PARAM, char **argv)
{
	char *cp;
	int timeout = 0;
	struct passwd *pwd;
	const char *shell;
#if ENABLE_FEATURE_SHADOWPASSWDS
	/* Using _r function to avoid pulling in static buffers */
	char buffer[256];
	struct spwd spw;
#endif

	logmode = LOGMODE_BOTH;
	openlog(applet_name, 0, LOG_AUTH);

	opt_complementary = "t+"; /* -t N */
	getopt32(argv, "t:", &timeout);
	argv += optind;

	if (argv[0]) {
		close(0);
		close(1);
		dup(xopen(argv[0], O_RDWR));
		close(2);
		dup(0);
	}

	/* Malicious use like "sulogin /dev/sda"? */
	if (!isatty(0) || !isatty(1) || !isatty(2)) {
		logmode = LOGMODE_SYSLOG;
		bb_error_msg_and_die("not a tty");
	}

	/* Clear dangerous stuff, set PATH */
	sanitize_env_if_suid();

	pwd = getpwuid(0);
	if (!pwd) {
		goto auth_error;
	}

#if ENABLE_FEATURE_SHADOWPASSWDS
	{
		/* getspnam_r may return 0 yet set result to NULL.
		 * At least glibc 2.4 does this. Be extra paranoid here. */
		struct spwd *result = NULL;
		int r = getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result);
		if (r || !result) {
			goto auth_error;
		}
		pwd->pw_passwd = result->sp_pwdp;
	}
#endif

	while (1) {
		char *encrypted;
		int r;

		/* cp points to a static buffer */
		cp = bb_ask(STDIN_FILENO, timeout,
				"Give root password for system maintenance\n"
				"(or type Control-D for normal startup):");
		if (!cp) {
			/* ^D, ^C, timeout, or read error */
			bb_info_msg("Normal startup");
			return 0;
		}
		encrypted = pw_encrypt(cp, pwd->pw_passwd, 1);
		r = strcmp(encrypted, pwd->pw_passwd);
		free(encrypted);
		if (r == 0) {
			break;
		}
		bb_do_delay(LOGIN_FAIL_DELAY);
		bb_info_msg("Login incorrect");
	}
	memset(cp, 0, strlen(cp));
//	signal(SIGALRM, SIG_DFL);

	bb_info_msg("System Maintenance Mode");

	IF_SELINUX(renew_current_security_context());

	shell = getenv("SUSHELL");
	if (!shell)
		shell = getenv("sushell");
	if (!shell)
		shell = pwd->pw_shell;

	/* Exec login shell with no additional parameters. Never returns. */
	run_shell(shell, 1, NULL, NULL);

 auth_error:
	bb_error_msg_and_die("no password entry for root");
}
Exemple #12
0
void eStreamClient::notifier(int what)
{
	if (!(what & eSocketNotifier::Read))
		return;

	ePtr<eStreamClient> ref = this;
	char buf[512];
	int len;
	if ((len = singleRead(streamFd, buf, sizeof(buf))) <= 0)
	{
		rsn->stop();
		stop();
		parent->connectionLost(this);
		return;
	}
	request.append(buf, len);
	if (running || (request.find('\n') == std::string::npos))
		return;

	if (request.substr(0, 5) == "GET /")
	{
		size_t pos;
		if (eConfigManager::getConfigBoolValue("config.streaming.authentication"))
		{
			bool authenticated = false;
			if ((pos = request.find("Authorization: Basic ")) != std::string::npos)
			{
				std::string authentication, username, password;
				std::string hash = request.substr(pos + 21);
				pos = hash.find('\r');
				hash = hash.substr(0, pos);
				hash += "\n";
				{
					char *in, *out;
					in = strdup(hash.c_str());
					out = (char*)calloc(1, hash.size());
					if (in && out)
					{
						BIO *b64, *bmem;
						b64 = BIO_new(BIO_f_base64());
						bmem = BIO_new_mem_buf(in, hash.size());
						bmem = BIO_push(b64, bmem);
						BIO_read(bmem, out, hash.size());
						BIO_free_all(bmem);
						authentication.append(out, hash.size());
					}
					free(in);
					free(out);
				}
				pos = authentication.find(':');
				if (pos != std::string::npos)
				{
					char *buffer = (char*)malloc(4096);
					if (buffer)
					{
						struct passwd pwd;
						struct passwd *pwdresult = NULL;
						std::string crypt;
						username = authentication.substr(0, pos);
						password = authentication.substr(pos + 1);
						getpwnam_r(username.c_str(), &pwd, buffer, 4096, &pwdresult);
						if (pwdresult)
						{
							struct crypt_data cryptdata;
							char *cryptresult = NULL;
							cryptdata.initialized = 0;
							crypt = pwd.pw_passwd;
							if (crypt == "*" || crypt == "x")
							{
								struct spwd spwd;
								struct spwd *spwdresult = NULL;
								getspnam_r(username.c_str(), &spwd, buffer, 4096, &spwdresult);
								if (spwdresult)
								{
									crypt = spwd.sp_pwdp;
								}
							}
							cryptresult = crypt_r(password.c_str(), crypt.c_str(), &cryptdata);
							authenticated = cryptresult && cryptresult == crypt;
						}
						free(buffer);
					}
				}
			}
			if (!authenticated)
			{
				const char *reply = "HTTP/1.0 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"streamserver\"\r\n\r\n";
				writeAll(streamFd, reply, strlen(reply));
				rsn->stop();
				parent->connectionLost(this);
				return;
			}
		}
		pos = request.find(' ', 5);
		if (pos != std::string::npos)
		{
			std::string serviceref = urlDecode(request.substr(5, pos - 5));
			if (!serviceref.empty())
			{
				const char *reply = "HTTP/1.0 200 OK\r\nConnection: Close\r\nContent-Type: video/mpeg\r\nServer: streamserver\r\n\r\n";
				writeAll(streamFd, reply, strlen(reply));
				if (serviceref.substr(0, 10) == "file?file=") /* convert openwebif stream reqeust back to serviceref */
					serviceref = "1:0:1:0:0:0:0:0:0:0:" + serviceref.substr(10);
				pos = serviceref.find('?');
				if (pos == std::string::npos)
				{
					if (eDVBServiceStream::start(serviceref.c_str(), streamFd) >= 0)
						running = true;
				}
				else
				{
					request = serviceref.substr(pos);
					serviceref = serviceref.substr(0, pos);
					pos = request.find("?bitrate=");
					if (pos != std::string::npos)
					{
						/* we need to stream transcoded data */
						int bitrate = 1024 * 1024;
						int width = 720;
						int height = 576;
						int framerate = 25000;
						int interlaced = 0;
						int aspectratio = 0;
						sscanf(request.substr(pos).c_str(), "?bitrate=%d", &bitrate);
						pos = request.find("?width=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?width=%d", &width);
						pos = request.find("?height=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?height=%d", &height);
						pos = request.find("?framerate=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?framerate=%d", &framerate);
						pos = request.find("?interlaced=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?interlaced=%d", &interlaced);
						pos = request.find("?aspectratio=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?aspectratio=%d", &aspectratio);
						encoderFd = parent->allocateEncoder(this, serviceref, bitrate, width, height, framerate, !!interlaced, aspectratio);
						if (encoderFd >= 0)
						{
							running = true;
							streamThread = new eDVBRecordStreamThread(188);
							if (streamThread)
							{
								streamThread->setTargetFD(streamFd);
								streamThread->start(encoderFd);
							}
						}
					}
				}
			}
		}
	}
	if (!running)
	{
		const char *reply = "HTTP/1.0 400 Bad Request\r\n\r\n";
		writeAll(streamFd, reply, strlen(reply));
		rsn->stop();
		parent->connectionLost(this);
		return;
	}
	request.clear();
}
Exemple #13
0
/*
 * This function looks up "username" in the shadow password file, determines
 * the hash algorithm type, and returns the salt and the password
 * hash for that user.
 * 
 * Given the salt and the user password, then the hash can be created.
 * The generated hash is used as an SRP password (client side), and
 * the generator for the SRP secret (server side).
 *
 * Crypt password file format references:
 * http://php.net/manual/en/function.crypt.php
 * http://en.wikipedia.org/wiki/Crypt_%28C%29#Blowfish-based_scheme
 *
 * Look up from the shadow password file the specified user, and if found,
 * return the salt field parsed out from the hash entry
 *
 * Algorithm ID
 * $1$  MD5
 * 12 characters salt follows
 *
 * $2a$ Blowfish
 * $2b$ Blowfish
 * $2x$ Blowfish
 * $2y$ Blowfish
 * Blowfish salt format:
 * $id$NN$-----22 chars-salt----++++++hash+++++:
 *
 * SHA salt format
 * $5$  SHA-256
 * $6$  SHA-512
 * $ID$salt$hash
 */
int get_sp_salt(const char *username,
                char **ret_salt,
                char **ret_encpwd)
{
    int st = 0;
    int is_locked = 0;
    struct spwd *spval = NULL;
    struct spwd spval_buf = {0};
    char *spbuf_str = NULL;
    int spbuf_str_len = 256;
    int salt_len = 0;
    char *salt = NULL;
    char *encpwd = NULL;
    char *sp = NULL;
    int cur_uid = 0;
    int error = 0;
    
    if (!username || !ret_salt || !ret_encpwd)
    {
        st = -1;
        errno = EINVAL;
        goto error;
    }

    /* Must be root to read shadow password file */
    cur_uid = getuid();
    error = seteuid(0);
    if (error != 0)
    {
        st = -1;
        goto error;
    }

    /* Obtain password file lock, and hold minimum amount of time */
    st = lckpwdf();
    if (st == -1)
    {
        goto error;
    }
    is_locked = 1;

    spbuf_str = calloc(spbuf_str_len, sizeof(char));
    if (!spbuf_str)
    {
        st = -1;
        goto error;
    }
    st = getspnam_r(username,
                    &spval_buf,
                    spbuf_str,
                    spbuf_str_len,
                    &spval);

    if (!spval || st == -1)
    {
        /* Failed due to permissions or entry not found */
        st = -1;
        goto error;
    }
    salt = strdup(spval->sp_pwdp);
    if (!salt)
    {
        /* errno is set */
        st = -1;
        goto error;
    }
    encpwd = strdup(spval->sp_pwdp);
    if (!encpwd)
    {
        /* errno is set */
        st = -1;
        goto error;
    }
    ulckpwdf();
    error = seteuid(cur_uid);
    if (error != 0)
    {
        st = -1;
        goto error;
    }

    is_locked = 0;
   
    /* CRYPT_DES hash is not supported; how to test? */

    /* Determine the hash algorithn, and therefore the salt length */
    if (!strncmp(salt, CRYPT_MD5, strlen(CRYPT_MD5)))
    {
        /* $1$123456789012 */
        salt_len = 12 + 3;
    }
    else if (!strncmp(salt, CRYPT_BLOWFISH_2A, strlen(CRYPT_BLOWFISH_2A)) ||
             !strncmp(salt, CRYPT_BLOWFISH_2B, strlen(CRYPT_BLOWFISH_2B)) ||
             !strncmp(salt, CRYPT_BLOWFISH_2X, strlen(CRYPT_BLOWFISH_2X)) ||
             !strncmp(salt, CRYPT_BLOWFISH_2Y, strlen(CRYPT_BLOWFISH_2Y)))
    {
        /* $2a$05$1234567890123456789012 */
        salt_len = 22 + 7;
    }
    else if (!strncmp(salt, CRYPT_SHA_256, strlen(CRYPT_SHA_256)) ||
             !strncmp(salt, CRYPT_SHA_512, strlen(CRYPT_SHA_512)))
    {
        sp = strrchr(salt, '$');
        salt_len = sp - salt + 1;
    }
    if(salt_len == 0)//locked user, user with nologin etc
    {
        st = -1;
        errno = EPERM;
        goto error;
    }
    salt[salt_len] = '\0';
    *ret_salt = salt;
    *ret_encpwd = encpwd;
    salt = NULL;

error:
    if (is_locked)
    {
        ulckpwdf();
        error = seteuid(cur_uid);
    }
    if (spbuf_str)
    {
        free(spbuf_str);
    }
    if (st == -1)
    {
        if (salt)
        {
            free(salt);
            salt = NULL;
        }
        if (encpwd)
        {
            free(encpwd);
            encpwd = NULL;
        }
    }
    return st;
}
Exemple #14
0
int sulogin_main(int argc, char **argv)
{
	char *cp;
	int timeout = 0;
	char *timeout_arg;
	const char * const *p;
	struct passwd *pwd;
	const char *shell;
#if ENABLE_FEATURE_SHADOWPASSWDS
	/* Using _r function to avoid pulling in static buffers */
	char buffer[256];
	struct spwd spw;
	struct spwd *result;
#endif

	logmode = LOGMODE_BOTH;
	openlog(applet_name, 0, LOG_AUTH);

	if (getopt32(argc, argv, "t:", &timeout_arg)) {
		timeout = xatoi_u(timeout_arg);
	}

	if (argv[optind]) {
		close(0);
		close(1);
		dup(xopen(argv[optind], O_RDWR));
		close(2);
		dup(0);
	}

	if (!isatty(0) || !isatty(1) || !isatty(2)) {
		logmode = LOGMODE_SYSLOG;
		bb_error_msg_and_die("not a tty");
	}

	/* Clear out anything dangerous from the environment */
	for (p = forbid; *p; p++)
		unsetenv(*p);

	signal(SIGALRM, catchalarm);

	pwd = getpwuid(0);
	if (!pwd) {
		goto auth_error;
	}

#if ENABLE_FEATURE_SHADOWPASSWDS
	if (getspnam_r(pwd->pw_name, &spw, buffer, sizeof(buffer), &result)) {
		goto auth_error;
	}
	pwd->pw_passwd = spw.sp_pwdp;
#endif

	while (1) {
		/* cp points to a static buffer that is zeroed every time */
		cp = bb_askpass(timeout,
				"Give root password for system maintenance\n"
				"(or type Control-D for normal startup):");

		if (!cp || !*cp) {
			bb_info_msg("Normal startup");
			return 0;
		}
		if (strcmp(pw_encrypt(cp, pwd->pw_passwd), pwd->pw_passwd) == 0) {
			break;
		}
		bb_do_delay(FAIL_DELAY);
		bb_error_msg("login incorrect");
	}
	memset(cp, 0, strlen(cp));
	signal(SIGALRM, SIG_DFL);

	bb_info_msg("System Maintenance Mode");

	USE_SELINUX(renew_current_security_context());

	shell = getenv("SUSHELL");
	if (!shell) shell = getenv("sushell");
	if (!shell) {
		shell = "/bin/sh";
		if (pwd->pw_shell[0])
			shell = pwd->pw_shell;
	}
	run_shell(shell, 1, 0, 0);
	/* never returns */

auth_error:
	bb_error_msg_and_die("no password entry for 'root'");
}
Exemple #15
0
static void
main_loop(char *devname, boolean_t cttyflag)
{
	int		fd, fb, i;
	char		*user = NULL;		/* authorized user */
	char		*pass;			/* password from user */
	char		*cpass;			/* crypted password */
	struct spwd	spwd;
	struct spwd	*lshpw;			/* local shadow */
	char		shadow[NSS_BUFLEN_SHADOW];
	FILE		*sysmsgfd;

	for (i = 0; i < 3; i++)
		(void) close(i);
	if (cttyflag == B_FALSE) {
		if (setsid() == -1)
			exit(EXIT_FAILURE);
	}
	if ((fd = open(devname, O_RDWR)) < 0)
		exit(EXIT_FAILURE);

	/*
	 * In system maintenance mode, all virtual console instances
	 * of the svc:/system/console-login service are not available
	 * any more, and only the system console is available. So here
	 * we always switch to the system console in case at the moment
	 * the active console isn't it.
	 */
	(void) ioctl(fd, VT_ACTIVATE, 1);

	if (fd != 0)
		(void) dup2(fd, STDIN_FILENO);
	if (fd != 1)
		(void) dup2(fd, STDOUT_FILENO);
	if (fd != 2)
		(void) dup2(fd, STDERR_FILENO);
	if (fd > 2)
		(void) close(fd);

	/* Stop progress bar and reset console mode to text */
	if ((fb = open("/dev/fb", O_RDONLY)) >= 0) {
		(void) ioctl(fb, KDSETMODE, KD_RESETTEXT);
		(void) close(fb);
	}

	sysmsgfd = fopen("/dev/sysmsg", "w");

	sanitize_tty(fileno(stdin));

	for (;;) {
		do {
			(void) printf("\nEnter user name for system "
			    "maintenance (control-d to bypass): ");
			user = sulogin_getinput(devname, ECHOON);
			if (user == NULL) {
				/* signal other children to exit */
				(void) sigsend(P_PID, masterpid, SIGUSR1);
				/* ^D, so straight to default init state */
				exit(EXIT_FAILURE);
			}
		} while (user[0] == '\0');
		(void) printf("Enter %s password (control-d to bypass): ",
		    user);

		if ((pass = sulogin_getinput(devname, ECHOOFF)) == NULL) {
			/* signal other children to exit */
			(void) sigsend(P_PID, masterpid, SIGUSR1);
			/* ^D, so straight to default init state */
			free(user);
			exit(EXIT_FAILURE);
		}
		lshpw = getspnam_r(user, &spwd, shadow, sizeof (shadow));
		if (lshpw == NULL) {
			/*
			 * the user entered doesn't exist, too bad.
			 */
			goto sorry;
		}

		/*
		 * There is a special case error to catch here:
		 * If the password is hashed with an algorithm
		 * other than the old unix crypt the call to crypt(3c)
		 * could fail if /usr is corrupt or not available
		 * since by default /etc/security/crypt.conf will
		 * have the crypt_ modules located under /usr/lib.
		 * Or it could happen if /etc/security/crypt.conf
		 * is corrupted.
		 *
		 * If this happens crypt(3c) will return NULL and
		 * set errno to ELIBACC for the former condition or
		 * EINVAL for the latter, in this case we bypass
		 * authentication and just verify that the user is
		 * authorized.
		 */

		errno = 0;
		cpass = crypt(pass, lshpw->sp_pwdp);
		if (((cpass == NULL) && (lshpw->sp_pwdp[0] == '$')) &&
		    ((errno == ELIBACC) || (errno == EINVAL))) {
			goto checkauth;
		} else if ((cpass == NULL) ||
		    (strcmp(cpass, lshpw->sp_pwdp) != 0)) {
			goto sorry;
		}

checkauth:
		/*
		 * There is a special case error here as well.
		 * If /etc/user_attr is corrupt, getusernam("root")
		 * returns NULL.
		 * In this case, we just give access because this is similar
		 * to the case of root not existing in /etc/passwd.
		 */

		if ((getusernam("root") != NULL) &&
		    (chkauthattr(MAINTENANCE_AUTH, user) != 1)) {
			goto sorry;
		}
		(void) fprintf(sysmsgfd, "\nsingle-user privilege "
		    "assigned to %s on %s.\n", user, devname);
		(void) sigsend(P_PID, masterpid, SIGUSR1);
		(void) wait(NULL);
		free(user);
		free(pass);
		single(su, devname);
		/* single never returns */

sorry:
		(void) printf("\nLogin incorrect or user %s not authorized\n",
		    user);
		free(user);
		free(pass);
		(void) sleep(sleeptime);
	}
}
Exemple #16
0
/*ARGSUSED*/
int
nss_getpwnam(char *name, attrlist *items, pwu_repository_t *rep, void **buf)
{
	attrlist *p;
	struct pwbuf *pwbuf;
	int repositories = REP_ERANGE;	/* changed if ATTR_REP_NAME is set */
	int err = PWU_SUCCESS;

	*buf = calloc(1, sizeof (struct pwbuf));
	pwbuf = (struct pwbuf *)*buf;

	/*
	 * determine which password structure (/etc/passwd or /etc/shadow)
	 * we need for the items we need to update
	 */
	for (p = items; p != NULL; p = p->next) {
		switch (p->type) {
		case ATTR_NAME:
		case ATTR_UID:
		case ATTR_GID:
		case ATTR_AGE:
		case ATTR_COMMENT:
		case ATTR_GECOS:
		case ATTR_HOMEDIR:
		case ATTR_SHELL:
			if (pwbuf->pwd == NULL)
				pwbuf->pwd = (struct passwd *)
				    malloc(sizeof (struct passwd));
			if (pwbuf->pwd == NULL) {
				errno = ENOMEM;
				if (pwbuf->spwd)
					free(pwbuf->spwd);
				return (PWU_NOMEM);
			}
			break;
		case ATTR_PASSWD:
		case ATTR_PASSWD_SERVER_POLICY:
		case ATTR_LSTCHG:
		case ATTR_MIN:
		case ATTR_MAX:
		case ATTR_WARN:
		case ATTR_INACT:
		case ATTR_EXPIRE:
		case ATTR_FLAG:
		case ATTR_LOCK_ACCOUNT:
		case ATTR_EXPIRE_PASSWORD:
		case ATTR_FAILED_LOGINS:
			if (pwbuf->spwd == NULL)
				pwbuf->spwd = (struct spwd *)
				    malloc(sizeof (struct spwd));
			if (pwbuf->spwd == NULL) {
				errno = ENOMEM;
				if (pwbuf->pwd)
					free(pwbuf->pwd);
				return (PWU_NOMEM);
			}
			break;
		case ATTR_REP_NAME:
			/* get the compat names (REP_COMPAT_*) */
			repositories = get_ns(rep, PWU_READ);
			break;
		default:
			/*
			 * Some other repository might have different values
			 * so we ignore those.
			 */
			break;
		}
	}

	if (pwbuf->pwd) {
		if ((pwbuf->pwd_scratch = malloc(PWD_SCRATCH_SIZE)) == NULL) {
			err = PWU_NOMEM;
			goto error;
		}
		if (getpwnam_r(name, pwbuf->pwd, pwbuf->pwd_scratch,
		    PWD_SCRATCH_SIZE) == NULL) {
			err = PWU_NOT_FOUND;
			goto error;
		}
	}

	if (pwbuf->spwd) {
		if ((pwbuf->spwd_scratch = malloc(SPW_SCRATCH_SIZE)) == NULL) {
			err = PWU_NOMEM;
			goto error;
		}
		if (getspnam_r(name, pwbuf->spwd, pwbuf->spwd_scratch,
		    SPW_SCRATCH_SIZE) == NULL) {
			err = PWU_NOT_FOUND;
			goto error;
		}
	}

	/* pwbuf->rep_name tells us where the user in fact comes from */
	if (repositories != REP_ERANGE) {
		struct passwd pwd;
		char pwd_scratch[PWD_SCRATCH_SIZE];

		/* can we find the user locally? */
		if (private_getpwnam_r(name, &pwd, pwd_scratch,
		    PWD_SCRATCH_SIZE) != NULL)
			pwbuf->rep_name = "files";
		else if (repositories & REP_COMPAT_NISPLUS)
			pwbuf->rep_name = "nisplus";
		else if (repositories & REP_COMPAT_LDAP)
			pwbuf->rep_name = "ldap";
		else if (repositories & REP_COMPAT_NIS)
			pwbuf->rep_name = "nis";
		else
			pwbuf->rep_name = "nss";
	} else
		pwbuf->rep_name = "nss";

	return (PWU_SUCCESS);
error:
	if (pwbuf->pwd) free(pwbuf->pwd);
	if (pwbuf->pwd_scratch) free(pwbuf->pwd_scratch);
	if (pwbuf->spwd) free(pwbuf->spwd);
	if (pwbuf->spwd_scratch) free(pwbuf->spwd_scratch);
	free(pwbuf);
	*buf = NULL;

	return (err);
}
Exemple #17
0
int shadow_user_pass_verify(const char *username, const char *password) {
#if defined(COMPILE_WIN32) || defined(NO_SHADOW_H)
	errno = ENOSYS;
	return -1;
#else
	int errsv = 0;
	struct spwd *spentp = NULL;
	size_t salt_len = 0;
	char *salt = NULL, *local_hash = NULL, *user_hash = NULL;
 #ifdef _GNU_SOURCE
	char sp_buf[8192];
	struct spwd spent;
	struct crypt_data cd;
 #endif

	/* Pre-check */
	if (!username || !password) {
		errno = EINVAL;
		return -1;
	}

 #if defined(_GNU_SOURCE)
	/* GNU implementations support native reentrant functions */
	if (getspnam_r(username, &spent, sp_buf, sizeof(sp_buf), &spentp) < 0)
		return -1;
 #else
	pthread_mutex_lock(&_auth_shadow_mutex);

	spentp = getspnam(username);

	errsv = errno;

	pthread_mutex_unlock(&_auth_shadow_mutex);
 #endif

	/* Validate that spentp is valid */
	if (!spentp) {
		errno = errsv;
		return -1;
	}

	/* Search for '$' in the local hash. If found, extensions (non-POSIX) are enabled */
	if (!(local_hash = strrchr(spentp->sp_pwdp, '$'))) {
		/* DES (default) */
		if (strlen(spentp->sp_pwdp) <= 2) {
			errno = ENOSYS;
			return -1;
		}

		salt_len = 2;
	} else {
		/* Extensions */
		local_hash ++;
		salt_len = local_hash - spentp->sp_pwdp;
	}

	/* Allocate memory for salt */
	if (!(salt = malloc(salt_len + 1)))
		return -1;

	/* Isolate salt */
	memcpy(salt, spentp->sp_pwdp, salt_len);
	salt[salt_len] = 0;

 #ifdef _GNU_SOURCE
	/* cd.initialized = 0; */
	tc_memset(&cd, 0, sizeof(struct crypt_data));

	/* Generate password hash */
	if (!(user_hash = crypt_r(password, salt, &cd))) {
		errsv = errno;
		free(salt);
		errno = errsv;
		return -1;
	}

 #else
	pthread_mutex_lock(&_auth_shadow_mutex);

	/* Generate password hash (non-reentrant) */
	if (!(user_hash = crypt(password, salt))) {
		errsv = errno;
		free(salt);
		errno = errsv;
		return -1;
	}

	pthread_mutex_unlock(&_auth_shadow_mutex);
 #endif

	/* Free unused memory */
	free(salt);

	/* Compare hashes */
	if (strcmp(spentp->sp_pwdp, user_hash)) {
		errno = EINVAL;
		return -1;
	}

	return 0;
#endif
}
/**
 * Check the credentials and return the gid/uid of user.
 *
 * @param    pszUser     username
 * @param    pszPasswd   password
 * @param    gid         where to store the GID of the user
 * @param    uid         where to store the UID of the user
 * @returns IPRT status code
 */
static int rtCheckCredentials(const char *pszUser, const char *pszPasswd, gid_t *pGid, uid_t *pUid)
{
#if defined(RT_OS_DARWIN)
    RTLogPrintf("rtCheckCredentials\n");

    /*
     * Resolve user to UID and GID.
     */
    char            szBuf[_4K];
    struct passwd   Pw;
    struct passwd  *pPw;
    if (getpwnam_r(pszUser, &Pw, szBuf, sizeof(szBuf), &pPw) != 0)
        return VERR_AUTHENTICATION_FAILURE;
    if (!pPw)
        return VERR_AUTHENTICATION_FAILURE;

    *pUid = pPw->pw_uid;
    *pGid = pPw->pw_gid;

    /*
     * Use PAM for the authentication.
     * Note! libpam.2.dylib was introduced with 10.6.x (OpenPAM).
     */
    void *hModPam = dlopen("libpam.dylib", RTLD_LAZY | RTLD_GLOBAL);
    if (hModPam)
    {
        int (*pfnPamStart)(const char *, const char *, struct pam_conv *, pam_handle_t **);
        int (*pfnPamAuthenticate)(pam_handle_t *, int);
        int (*pfnPamAcctMgmt)(pam_handle_t *, int);
        int (*pfnPamSetItem)(pam_handle_t *, int, const void *);
        int (*pfnPamEnd)(pam_handle_t *, int);
        *(void **)&pfnPamStart        = dlsym(hModPam, "pam_start");
        *(void **)&pfnPamAuthenticate = dlsym(hModPam, "pam_authenticate");
        *(void **)&pfnPamAcctMgmt     = dlsym(hModPam, "pam_acct_mgmt");
        *(void **)&pfnPamSetItem      = dlsym(hModPam, "pam_set_item");
        *(void **)&pfnPamEnd          = dlsym(hModPam, "pam_end");
        ASMCompilerBarrier();
        if (   pfnPamStart
            && pfnPamAuthenticate
            && pfnPamAcctMgmt
            && pfnPamSetItem
            && pfnPamEnd)
        {
#define pam_start           pfnPamStart
#define pam_authenticate    pfnPamAuthenticate
#define pam_acct_mgmt       pfnPamAcctMgmt
#define pam_set_item        pfnPamSetItem
#define pam_end             pfnPamEnd

            /* Do the PAM stuff.
               Note! Abusing 'login' here for now... */
            pam_handle_t   *hPam        = NULL;
            RTPROCPAMARGS   PamConvArgs = { pszUser, pszPasswd };
            struct pam_conv PamConversation;
            RT_ZERO(PamConversation);
            PamConversation.appdata_ptr = &PamConvArgs;
            PamConversation.conv        = rtPamConv;
            int rc = pam_start("login", pszUser, &PamConversation, &hPam);
            if (rc == PAM_SUCCESS)
            {
                rc = pam_set_item(hPam, PAM_RUSER, pszUser);
                if (rc == PAM_SUCCESS)
                    rc = pam_authenticate(hPam, 0);
                if (rc == PAM_SUCCESS)
                {
                    rc = pam_acct_mgmt(hPam, 0);
                    if (   rc == PAM_SUCCESS
                        || rc == PAM_AUTHINFO_UNAVAIL /*??*/)
                    {
                        pam_end(hPam, PAM_SUCCESS);
                        dlclose(hModPam);
                        return VINF_SUCCESS;
                    }
                    Log(("rtCheckCredentials: pam_acct_mgmt -> %d\n", rc));
                }
                else
                    Log(("rtCheckCredentials: pam_authenticate -> %d\n", rc));
                pam_end(hPam, rc);
            }
            else
                Log(("rtCheckCredentials: pam_start -> %d\n", rc));
        }
        else
            Log(("rtCheckCredentials: failed to resolve symbols: %p %p %p %p %p\n",
                 pfnPamStart, pfnPamAuthenticate, pfnPamAcctMgmt, pfnPamSetItem, pfnPamEnd));
        dlclose(hModPam);
    }
    else
        Log(("rtCheckCredentials: Loading libpam.dylib failed\n"));
    return VERR_AUTHENTICATION_FAILURE;

#elif defined(RT_OS_LINUX)
    struct passwd *pw;

    pw = getpwnam(pszUser);
    if (!pw)
        return VERR_AUTHENTICATION_FAILURE;

    if (!pszPasswd)
        pszPasswd = "";

    struct spwd *spwd;
    /* works only if /etc/shadow is accessible */
    spwd = getspnam(pszUser);
    if (spwd)
        pw->pw_passwd = spwd->sp_pwdp;

    /* Default fCorrect=true if no password specified. In that case, pw->pw_passwd
     * must be NULL (no password set for this user). Fail if a password is specified
     * but the user does not have one assigned. */
    int fCorrect = !pszPasswd || !*pszPasswd;
    if (pw->pw_passwd && *pw->pw_passwd)
    {
        struct crypt_data *data = (struct crypt_data*)RTMemTmpAllocZ(sizeof(*data));
        /* be reentrant */
        char *pszEncPasswd = crypt_r(pszPasswd, pw->pw_passwd, data);
        fCorrect = pszEncPasswd && !strcmp(pszEncPasswd, pw->pw_passwd);
        RTMemTmpFree(data);
    }
    if (!fCorrect)
        return VERR_AUTHENTICATION_FAILURE;

    *pGid = pw->pw_gid;
    *pUid = pw->pw_uid;
    return VINF_SUCCESS;

#elif defined(RT_OS_SOLARIS)
    struct passwd *ppw, pw;
    char szBuf[1024];

    if (getpwnam_r(pszUser, &pw, szBuf, sizeof(szBuf), &ppw) != 0 || ppw == NULL)
        return VERR_AUTHENTICATION_FAILURE;

    if (!pszPasswd)
        pszPasswd = "";

    struct spwd spwd;
    char szPwdBuf[1024];
    /* works only if /etc/shadow is accessible */
    if (getspnam_r(pszUser, &spwd, szPwdBuf, sizeof(szPwdBuf)) != NULL)
        ppw->pw_passwd = spwd.sp_pwdp;

    char *pszEncPasswd = crypt(pszPasswd, ppw->pw_passwd);
    if (strcmp(pszEncPasswd, ppw->pw_passwd))
        return VERR_AUTHENTICATION_FAILURE;

    *pGid = ppw->pw_gid;
    *pUid = ppw->pw_uid;
    return VINF_SUCCESS;

#else
    NOREF(pszUser); NOREF(pszPasswd); NOREF(pGid); NOREF(pUid);
    return VERR_AUTHENTICATION_FAILURE;
#endif
}
Exemple #19
0
void eStreamClient::notifier(int what)
{
	if (what & eSocketNotifier::Read)
	{
		char buf[512];
		int len;
		if ((len = singleRead(streamFd, buf, sizeof(buf))) <= 0)
		{
			rsn->stop();
			stop();
			parent->connectionLost(this);
			return;
		}
		request.append(buf, len);
		if (!running)
		{
			if (request.find('\n') != std::string::npos)
			{
				if (request.substr(0, 5) == "GET /")
				{
					size_t pos;
					if (eConfigManager::getConfigBoolValue("config.streaming.authentication"))
					{
						bool authenticated = false;
						if ((pos = request.find("Authorization: Basic ")) != std::string::npos)
						{
							std::string authentication, username, password;
							std::string hash = request.substr(pos + 21);
							pos = hash.find('\r');
							hash = hash.substr(0, pos);
							hash += "\n";
							{
								char *in, *out;
								in = strdup(hash.c_str());
								out = (char*)calloc(1, hash.size());
								if (in && out)
								{
									BIO *b64, *bmem;
									b64 = BIO_new(BIO_f_base64());
									bmem = BIO_new_mem_buf(in, hash.size());
									bmem = BIO_push(b64, bmem);
									BIO_read(bmem, out, hash.size());
									BIO_free_all(bmem);
									authentication.append(out, hash.size());
								}
								free(in);
								free(out);
							}
							pos = authentication.find(':');
							if (pos != std::string::npos)
							{
								char *buffer = (char*)malloc(4096);
								if (buffer)
								{
									struct passwd pwd;
									struct passwd *pwdresult = NULL;
									std::string crypt;
									username = authentication.substr(0, pos);
									password = authentication.substr(pos + 1);
									getpwnam_r(username.c_str(), &pwd, buffer, 4096, &pwdresult);
									if (pwdresult)
									{
										struct crypt_data cryptdata;
										char *cryptresult = NULL;
										cryptdata.initialized = 0;
										crypt = pwd.pw_passwd;
										if (crypt == "*" || crypt == "x")
										{
											struct spwd spwd;
											struct spwd *spwdresult = NULL;
											getspnam_r(username.c_str(), &spwd, buffer, 4096, &spwdresult);
											if (spwdresult)
											{
												crypt = spwd.sp_pwdp;
											}
										}
										cryptresult = crypt_r(password.c_str(), crypt.c_str(), &cryptdata);
										authenticated = cryptresult && cryptresult == crypt;
									}
									free(buffer);
								}
							}
						}
						if (!authenticated)
						{
							const char *reply = "HTTP/1.0 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"streamserver\"\r\n\r\n";
							writeAll(streamFd, reply, strlen(reply));
							rsn->stop();
							parent->connectionLost(this);
							return;
						}
					}
					pos = request.find(' ', 5);
					if (pos != std::string::npos)
					{
						std::string serviceref = urlDecode(request.substr(5, pos - 5));
						if (!serviceref.empty())
						{
							const char *reply = "HTTP/1.0 200 OK\r\nConnection: Close\r\nContent-Type: video/mpeg\r\nServer: streamserver\r\n\r\n";
							writeAll(streamFd, reply, strlen(reply));
							if (eDVBServiceStream::start(serviceref.c_str(), streamFd) >= 0)
							{
								running = true;
							}
						}
					}
				}
				if (!running)
				{
					const char *reply = "HTTP/1.0 400 Bad Request\r\n\r\n";
					writeAll(streamFd, reply, strlen(reply));
					rsn->stop();
					parent->connectionLost(this);
					return;
				}
				request.clear();
			}
		}
	}
}
Exemple #20
0
void eStreamClient::notifier(int what)
{
	if (!(what & eSocketNotifier::Read))
		return;

	ePtr<eStreamClient> ref = this;
	char buf[512];
	int len;
	if ((len = singleRead(streamFd, buf, sizeof(buf))) <= 0)
	{
		rsn->stop();
		stop();
		parent->connectionLost(this);
		return;
	}
	request.append(buf, len);
	if (running || (request.find('\n') == std::string::npos))
		return;

	if (request.substr(0, 5) == "GET /")
	{
		size_t pos;
		size_t posdur;
		if (eConfigManager::getConfigBoolValue("config.streaming.authentication"))
		{
			bool authenticated = false;
			if ((pos = request.find("Authorization: Basic ")) != std::string::npos)
			{
				std::string authentication, username, password;
				std::string hash = request.substr(pos + 21);
				pos = hash.find('\r');
				hash = hash.substr(0, pos);
				authentication = base64decode(hash);
				pos = authentication.find(':');
				if (pos != std::string::npos)
				{
					char *buffer = (char*)malloc(4096);
					if (buffer)
					{
						struct passwd pwd;
						struct passwd *pwdresult = NULL;
						std::string crypt;
						username = authentication.substr(0, pos);
						password = authentication.substr(pos + 1);
						getpwnam_r(username.c_str(), &pwd, buffer, 4096, &pwdresult);
						if (pwdresult)
						{
							struct crypt_data cryptdata;
							char *cryptresult = NULL;
							cryptdata.initialized = 0;
							crypt = pwd.pw_passwd;
							if (crypt == "*" || crypt == "x")
							{
								struct spwd spwd;
								struct spwd *spwdresult = NULL;
								getspnam_r(username.c_str(), &spwd, buffer, 4096, &spwdresult);
								if (spwdresult)
								{
									crypt = spwd.sp_pwdp;
								}
							}
							cryptresult = crypt_r(password.c_str(), crypt.c_str(), &cryptdata);
							authenticated = cryptresult && cryptresult == crypt;
						}
						free(buffer);
					}
				}
			}
			if (!authenticated)
			{
				const char *reply = "HTTP/1.0 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"streamserver\"\r\n\r\n";
				writeAll(streamFd, reply, strlen(reply));
				rsn->stop();
				parent->connectionLost(this);
				return;
			}
		}
		pos = request.find(' ', 5);
		if (pos != std::string::npos)
		{
			std::string serviceref = urlDecode(request.substr(5, pos - 5));
			if (!serviceref.empty())
			{
				const char *reply = "HTTP/1.0 200 OK\r\nConnection: Close\r\nContent-Type: video/mpeg\r\nServer: streamserver\r\n\r\n";
				writeAll(streamFd, reply, strlen(reply));
				/* We don't expect any incoming data, so set a tiny buffer */
				set_socket_option(streamFd, SO_RCVBUF, 1 * 1024);
				 /* We like 188k packets, so set the TCP window size to that */
				set_socket_option(streamFd, SO_SNDBUF, 188 * 1024);
				/* activate keepalive */
				set_socket_option(streamFd, SO_KEEPALIVE, 1);
				/* configure keepalive */
				set_tcp_option(streamFd, TCP_KEEPINTVL, 10); // every 10 seconds
				set_tcp_option(streamFd, TCP_KEEPIDLE, 1);	// after 1 second of idle
				set_tcp_option(streamFd, TCP_KEEPCNT, 2);	// drop connection after second miss
				/* also set 10 seconds data push timeout */
				set_tcp_option(streamFd, TCP_USER_TIMEOUT, 10 * 1000);

				if (serviceref.substr(0, 10) == "file?file=") /* convert openwebif stream reqeust back to serviceref */
					serviceref = "1:0:1:0:0:0:0:0:0:0:" + serviceref.substr(10);
				/* Strip session ID from URL if it exists, PLi streaming can not handle it */
				pos = serviceref.find("&sessionid=");
				if (pos != std::string::npos) {
					serviceref.erase(pos, std::string::npos);
				}
				pos = serviceref.find("?sessionid=");
				if (pos != std::string::npos) {
					serviceref.erase(pos, std::string::npos);
				}
				pos = serviceref.find('?');
				if (pos == std::string::npos)
				{
					eDebug("[eDVBServiceStream] stream ref: %s", serviceref.c_str());
					if (eDVBServiceStream::start(serviceref.c_str(), streamFd) >= 0)
					{
						running = true;
						m_serviceref = serviceref;
						m_useencoder = false;
					}
				}
				else
				{
					request = serviceref.substr(pos);
					serviceref = serviceref.substr(0, pos);
					pos = request.find("?bitrate=");
					posdur = request.find("?duration=");
					eDebug("[eDVBServiceStream] stream ref: %s", serviceref.c_str());
					if (posdur != std::string::npos)
					{
						if (eDVBServiceStream::start(serviceref.c_str(), streamFd) >= 0)
						{
							running = true;
							m_serviceref = serviceref;
							m_useencoder = false;
						}
						int timeout = 0;
						sscanf(request.substr(posdur).c_str(), "?duration=%d", &timeout);
						eDebug("[eDVBServiceStream] duration: %d seconds", timeout);
						if (timeout)
						{
							m_timeout->startLongTimer(timeout);
						}
					}
					else if (pos != std::string::npos)
					{
						/* we need to stream transcoded data */
						int bitrate = 1024 * 1024;
						int width = 720;
						int height = 576;
						int framerate = 25000;
						int interlaced = 0;
						int aspectratio = 0;
						sscanf(request.substr(pos).c_str(), "?bitrate=%d", &bitrate);
						pos = request.find("?width=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?width=%d", &width);
						pos = request.find("?height=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?height=%d", &height);
						pos = request.find("?framerate=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?framerate=%d", &framerate);
						pos = request.find("?interlaced=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?interlaced=%d", &interlaced);
						pos = request.find("?aspectratio=");
						if (pos != std::string::npos)
							sscanf(request.substr(pos).c_str(), "?aspectratio=%d", &aspectratio);
						encoderFd = -1;
						if (eEncoder::getInstance())
							encoderFd = eEncoder::getInstance()->allocateEncoder(serviceref, bitrate, width, height, framerate, !!interlaced, aspectratio);
						if (encoderFd >= 0)
						{
							running = true;
							streamThread = new eDVBRecordStreamThread(188);
							if (streamThread)
							{
								streamThread->setTargetFD(streamFd);
								streamThread->start(encoderFd);
							}
							m_serviceref = serviceref;
							m_useencoder = true;
						}
					}
				}
			}
		}
	}
	if (!running)
	{
		const char *reply = "HTTP/1.0 400 Bad Request\r\n\r\n";
		writeAll(streamFd, reply, strlen(reply));
		rsn->stop();
		parent->connectionLost(this);
		return;
	}
	request.clear();
}
Exemple #21
0
int passwd_main(int argc UNUSED_PARAM, char **argv)
{
	enum {
		OPT_algo   = (1 << 0), /* -a - password algorithm */
		OPT_lock   = (1 << 1), /* -l - lock account */
		OPT_unlock = (1 << 2), /* -u - unlock account */
		OPT_delete = (1 << 3), /* -d - delete password */
		OPT_lud    = OPT_lock | OPT_unlock | OPT_delete,
	};
	unsigned opt;
	int rc;
	const char *opt_a = CONFIG_FEATURE_DEFAULT_PASSWD_ALGO;
	const char *filename;
	char *myname;
	char *name;
	char *newp;
	struct passwd *pw;
	uid_t myuid;
	struct rlimit rlimit_fsize;
	char c;
#if ENABLE_FEATURE_SHADOWPASSWDS
	/* Using _r function to avoid pulling in static buffers */
	struct spwd spw;
	char buffer[256];
#endif

	logmode = LOGMODE_BOTH;
	openlog(applet_name, 0, LOG_AUTH);
	opt = getopt32(argv, "a:lud", &opt_a);
	//argc -= optind;
	argv += optind;

	myuid = getuid();
	/* -l, -u, -d require root priv and username argument */
	if ((opt & OPT_lud) && (myuid != 0 || !argv[0]))
		bb_show_usage();

	/* Will complain and die if username not found */
	myname = xstrdup(xuid2uname(myuid));
	name = argv[0] ? argv[0] : myname;

	pw = xgetpwnam(name);
	if (myuid != 0 && pw->pw_uid != myuid) {
		/* LOGMODE_BOTH */
		bb_error_msg_and_die("%s can't change password for %s", myname, name);
	}

#if ENABLE_FEATURE_SHADOWPASSWDS
	{
		/* getspnam_r may return 0 yet set result to NULL.
		 * At least glibc 2.4 does this. Be extra paranoid here. */
		struct spwd *result = NULL;
		errno = 0;
		if (getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result) != 0
		 || !result /* no error, but no record found either */
		 || strcmp(result->sp_namp, pw->pw_name) != 0 /* paranoia */
		) {
			if (errno != ENOENT) {
				/* LOGMODE_BOTH */
				bb_perror_msg("no record of %s in %s, using %s",
					name, bb_path_shadow_file,
					bb_path_passwd_file);
			}
			/* else: /etc/shadow does not exist,
			 * apparently we are on a shadow-less system,
			 * no surprise there */
		} else {
			pw->pw_passwd = result->sp_pwdp;
		}
	}
#endif

	/* Decide what the new password will be */
	newp = NULL;
	c = pw->pw_passwd[0] - '!';
	if (!(opt & OPT_lud)) {
		if (myuid != 0 && !c) { /* passwd starts with '!' */
			/* LOGMODE_BOTH */
			bb_error_msg_and_die("can't change "
					"locked password for %s", name);
		}
		printf("Changing password for %s\n", name);
		newp = new_password(pw, myuid, opt_a);
		if (!newp) {
			logmode = LOGMODE_STDIO;
			bb_error_msg_and_die("password for %s is unchanged", name);
		}
	} else if (opt & OPT_lock) {
		if (!c)
			goto skip; /* passwd starts with '!' */
		newp = xasprintf("!%s", pw->pw_passwd);
	} else if (opt & OPT_unlock) {
		if (c)
			goto skip; /* not '!' */
		/* pw->pw_passwd points to static storage,
		 * strdup'ing to avoid nasty surprizes */
		newp = xstrdup(&pw->pw_passwd[1]);
	} else if (opt & OPT_delete) {
		newp = (char*)"";
	}

	rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * 30000;
	setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
	bb_signals(0
		+ (1 << SIGHUP)
		+ (1 << SIGINT)
		+ (1 << SIGQUIT)
		, SIG_IGN);
	umask(077);
	xsetuid(0);

#if ENABLE_FEATURE_SHADOWPASSWDS
	filename = bb_path_shadow_file;
	rc = update_passwd(bb_path_shadow_file, name, newp, NULL);
	if (rc > 0)
		/* password in /etc/shadow was updated */
		newp = (char*) "x";
	if (rc >= 0)
		/* 0 = /etc/shadow missing (not an error), >0 = passwd changed in /etc/shadow */
#endif
	{
		filename = bb_path_passwd_file;
		rc = update_passwd(bb_path_passwd_file, name, newp, NULL);
	}
	/* LOGMODE_BOTH */
	if (rc < 0)
		bb_error_msg_and_die("can't update password file %s", filename);
	bb_error_msg("password for %s changed by %s", name, myname);

	/*if (ENABLE_FEATURE_CLEAN_UP) free(newp); - can't, it may be non-malloced */
 skip:
	if (!newp) {
		bb_error_msg_and_die("password for %s is already %slocked",
			name, (opt & OPT_unlock) ? "un" : "");
	}

	if (ENABLE_FEATURE_CLEAN_UP)
		free(myname);
	return 0;
}
struct spwd *
pam_modutil_getspnam(pam_handle_t *pamh, const char *user)
{
#ifdef HAVE_GETSPNAM_R

    void *buffer=NULL;
    size_t length = PWD_INITIAL_LENGTH;

    do {
	int status;
	void *new_buffer;
	struct spwd *result = NULL;

	new_buffer = realloc(buffer, sizeof(struct spwd) + length);
	if (new_buffer == NULL) {

	    D(("out of memory"));

	    /* no memory for the user - so delete the memory */
	    if (buffer) {
		free(buffer);
	    }
	    return NULL;
	}
	buffer = new_buffer;

	/* make the re-entrant call to get the spwd structure */
        errno = 0;
	status = getspnam_r(user, buffer,
			    sizeof(struct spwd) + (char *) buffer,
			    length, &result);
	if (!status && (result == buffer)) {
	    char *data_name;
	    const void *ignore;
	    int i;

	    data_name = malloc(strlen("_pammodutil_getspnam") + 1 +
	    		       strlen(user) + 1 + intlen(INT_MAX) + 1);
	    if ((pamh != NULL) && (data_name == NULL)) {
	        D(("was unable to register the data item [%s]",
	           pam_strerror(pamh, status)));
		free(buffer);
		return NULL;
	    }

	    if (pamh != NULL) {
	        for (i = 0; i < INT_MAX; i++) {
	            sprintf(data_name, "_pammodutil_getspnam_%s_%d", user, i);
		    status = PAM_NO_MODULE_DATA;
	            if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
		        status = pam_set_data(pamh, data_name,
					      result, pam_modutil_cleanup);
		    }
		    if (status == PAM_SUCCESS) {
		        break;
		    }
		}
	    } else {
	        status = PAM_SUCCESS;
	    }

	    free(data_name);

	    if (status == PAM_SUCCESS) {
		D(("success"));
		return result;
	    }

	    D(("was unable to register the data item [%s]",
	       pam_strerror(pamh, status)));

	    free(buffer);
	    return NULL;

	} else if (errno != ERANGE && errno != EINTR) {
                /* no sense in repeating the call */
                break;
        }
	
	length <<= PWD_LENGTH_SHIFT;

    } while (length < PWD_ABSURD_PWD_LENGTH);

    D(("spwd structure took %u bytes or so of memory",
       length+sizeof(struct spwd)));

    free(buffer);
    return NULL;

#else /* ie. ifndef HAVE_GETSPNAM_R */

    /*
     * Sorry, there does not appear to be a reentrant version of
     * getspnam(). So, we use the standard libc function.
     */
    
    return getspnam(user);

#endif /* def HAVE_GETSPNAM_R */
}