예제 #1
0
static int
match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
{
	FILE *f;
	char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
	u_long linenum = 0;
	u_int i;

	temporarily_use_uid(pw);
	debug("trying authorized principals file %s", file);
	if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
		restore_uid();
		return 0;
	}
	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		/* Skip leading whitespace. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		/* Skip blank and comment lines. */
		if ((ep = strchr(cp, '#')) != NULL)
			*ep = '\0';
		if (!*cp || *cp == '\n')
			continue;
		/* Trim trailing whitespace. */
		ep = cp + strlen(cp) - 1;
		while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
			*ep-- = '\0';
		/*
		 * If the line has internal whitespace then assume it has
		 * key options.
		 */
		line_opts = NULL;
		if ((ep = strrchr(cp, ' ')) != NULL ||
		    (ep = strrchr(cp, '\t')) != NULL) {
			for (; *ep == ' ' || *ep == '\t'; ep++)
				;
			line_opts = cp;
			cp = ep;
		}
		for (i = 0; i < cert->nprincipals; i++) {
			if (strcmp(cp, cert->principals[i]) == 0) {
				debug3("matched principal \"%.100s\" "
				    "from file \"%s\" on line %lu",
				    cert->principals[i], file, linenum);
				if (auth_parse_options(pw, line_opts,
				    file, linenum) != 1)
					continue;
				fclose(f);
				restore_uid();
				return 1;
			}
		}
	}
	fclose(f);
	restore_uid();
	return 0;
}
예제 #2
0
static int
process_principals(FILE *f, char *file, struct passwd *pw,
    const struct sshkey_cert *cert)
{
	char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
	u_long linenum = 0;
	u_int i, found_principal = 0;

	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		/* Always consume entire input */
		if (found_principal)
			continue;
		/* Skip leading whitespace. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		/* Skip blank and comment lines. */
		if ((ep = strchr(cp, '#')) != NULL)
			*ep = '\0';
		if (!*cp || *cp == '\n')
			continue;
		/* Trim trailing whitespace. */
		ep = cp + strlen(cp) - 1;
		while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
			*ep-- = '\0';
		/*
		 * If the line has internal whitespace then assume it has
		 * key options.
		 */
		line_opts = NULL;
		if ((ep = strrchr(cp, ' ')) != NULL ||
		    (ep = strrchr(cp, '\t')) != NULL) {
			for (; *ep == ' ' || *ep == '\t'; ep++)
				;
			line_opts = cp;
			cp = ep;
		}
		for (i = 0; i < cert->nprincipals; i++) {
			if (strcmp(cp, cert->principals[i]) == 0) {
				debug3("%s:%lu: matched principal \"%.100s\"",
				    file == NULL ? "(command)" : file,
				    linenum, cert->principals[i]);
				if (auth_parse_options(pw, line_opts,
				    file, linenum) != 1)
					continue;
				found_principal = 1;
				continue;
			}
		}
	}
	return found_principal;
}
예제 #3
0
/* check to see if the script specified by file can authorize the key
 *
 * the script will have the key written to STDIN, which is identical
 * to the normal public key format.
 *
 * the script must exit with either 0 for success or 1 for failure.
 * the script can print login options (if any) to STDOUT. No whitepace should be added
 * to the output.
 *
 * Use with caution: the script can hang sshd. It is recommended you code the script
 * with a timeout set if it cannot determine authenication quickly.
 */
static int
user_key_found_by_script(struct passwd *pw, Key *key, char *file)
{
	pid_t pid;
	char line[SSH_MAX_PUBKEY_BYTES];
	int pipe_in[2];
	int pipe_out[2];
	int exit_code = 1;
	int success = 0;
	FILE *f;
	//mysig_t oldsig;

	pipe(pipe_in);
	pipe(pipe_out);

	//oldsig = signal(SIGCHLD, SIG_IGN);
	temporarily_use_uid(pw);

	debug3("user_key_found_by_script: executing %s", file);

	switch ((pid = fork())) {
	case -1:
		error("fork(): %s", strerror(errno));
		restore_uid();
		return (-1);
	case 0:
		/* setup input pipe */
		close(pipe_in[1]);
		dup2(pipe_in[0], 0);
		close(pipe_in[0]);

		/* setup output pipe */
		close(pipe_out[0]);
		dup2(pipe_out[1], 1);
		close(pipe_out[1]);

		execl(file, file, NULL);

		/* exec failed */
		error("execl(): %s", strerror(errno));
		_exit(1);
	default:
		debug3("user_key_found_by_script: script pid %d", pid);

		close(pipe_in[0]);
		close(pipe_out[1]);

		f = fdopen(pipe_in[1], "w");
		key_write(key, f);
		fclose(f);

		while(waitpid(pid, &exit_code, 0) < 0) {
			switch(errno) {
			case EINTR:
				debug3("user_key_found_by_script: waitpid() EINTR, continuing");
				continue;
			default:
				error("waitpid(): %s", strerror(errno));
				goto waitpid_error;
			}
		}
		if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0) {
			int amt_read = read(pipe_out[0], line, sizeof(line) - 1);
			line[amt_read] = ' ';
			line[amt_read + 1] = 0;
			debug3("user_key_found_by_script: options: %s", line);
			if (auth_parse_options(pw, line, file, 0) == 1)
				success = 1;
		}
	 waitpid_error:
		close(pipe_out[0]);
	}

	restore_uid();
	//signal(SIGCHLD, oldsig);

	return success;
}
예제 #4
0
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	const char *reason;
	int found_key = 0;
	FILE *f;
	u_long linenum = 0;
	Key *found;
	char *fp;

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	debug("trying public key file %s", file);
	f = auth_openkeyfile(file, pw, options.strict_modes);

	if (!f) {
		restore_uid();
		return 0;
	}

	found_key = 0;
	found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);

	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp, *key_options = NULL;

		auth_clear_options();

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			}
		}
		if (key_is_cert(key)) {
			if (!key_equal(found, key->cert->signature_key))
				continue;
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (!key_is_cert_authority)
				continue;
			fp = key_fingerprint(found, SSH_FP_MD5,
			    SSH_FP_HEX);
			debug("matching CA found: file %s, line %lu, %s %s",
			    file, linenum, key_type(found), fp);
			/*
			 * If the user has specified a list of principals as
			 * a key option, then prefer that list to matching
			 * their username in the certificate principals list.
			 */
			if (authorized_principals != NULL &&
			    !match_principals_option(authorized_principals,
			    key->cert)) {
				reason = "Certificate does not contain an "
				    "authorized principal";
 fail_reason:
				xfree(fp);
				error("%s", reason);
				auth_debug_add("%s", reason);
				continue;
			}
			if (key_cert_check_authority(key, 0, 0,
			    authorized_principals == NULL ? pw->pw_name : NULL,
			    &reason) != 0)
				goto fail_reason;
			if (auth_cert_options(key, pw) != 0) {
				xfree(fp);
				continue;
			}
			verbose("Accepted certificate ID \"%s\" "
			    "signed by %s CA %s via %s", key->cert->key_id,
			    key_type(found), fp, file);
			xfree(fp);
			found_key = 1;
			break;
		} else if (key_equal(found, key)) {
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (key_is_cert_authority)
				continue;
			found_key = 1;
			debug("matching key found: file %s, line %lu",
			    file, linenum);
			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
			verbose("Found matching %s key: %s",
			    key_type(found), fp);
			xfree(fp);
			break;
		}
	}
	restore_uid();
	fclose(f);
	key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
예제 #5
0
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	int found_key = 0;
	FILE *f;
	u_long linenum = 0;
	struct stat st;
	Key *found;
	char *fp;

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	debug("trying public key file %s", file);

	/* Fail quietly if file does not exist */
	if (stat(file, &st) < 0) {
		/* Restore the privileged uid. */
		restore_uid();
		return 0;
	}
	/* Open the file containing the authorized keys. */
	f = fopen(file, "r");
	if (!f) {
		/* Restore the privileged uid. */
		restore_uid();
		return 0;
	}
	if (options.strict_modes &&
	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
		fclose(f);
		logit("Authentication refused: %s", line);
		restore_uid();
		return 0;
	}

	found_key = 0;
	found = key_new(key->type);

	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp, *key_options = NULL;

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			}
		}
		if (key_equal(found, key) &&
		    auth_parse_options(pw, key_options, file, linenum) == 1) {
			found_key = 1;
			debug("matching key found: file %s, line %lu",
			    file, linenum);
			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
			verbose("Found matching %s key: %s",
			    key_type(found), fp);
			xfree(fp);
			break;
		}
	}
	restore_uid();
	fclose(f);
	key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
예제 #6
0
int
auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
	char line[8192], *file;
	int allowed = 0;
	u_int bits;
	FILE *f;
	u_long linenum = 0;
	struct stat st;
	Key *key;

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	/* The authorized keys. */
	file = authorized_keys_file(pw);
	debug("trying public RSA key file %s", file);

	/* Fail quietly if file does not exist */
	if (stat(file, &st) < 0) {
		/* Restore the privileged uid. */
		restore_uid();
		xfree(file);
		return (0);
	}
	/* Open the file containing the authorized keys. */
	f = fopen(file, "r");
	if (!f) {
		/* Restore the privileged uid. */
		restore_uid();
		xfree(file);
		return (0);
	}
	if (options.strict_modes &&
	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
		xfree(file);
		fclose(f);
		log("Authentication refused: %s", line);
		restore_uid();
		return (0);
	}

	/* Flag indicating whether the key is allowed. */
	allowed = 0;

	key = key_new(KEY_RSA1);

	/*
	 * Go though the accepted keys, looking for the current key.  If
	 * found, perform a challenge-response dialog to verify that the
	 * user really has the corresponding private key.
	 */
	while (fgets(line, sizeof(line), f)) {
		char *cp;
		char *options;

		linenum++;

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		/*
		 * Check if there are options for this key, and if so,
		 * save their starting address and skip the option part
		 * for now.  If there are no options, set the starting
		 * address to NULL.
		 */
		if (*cp < '0' || *cp > '9') {
			int quoted = 0;
			options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
		} else
			options = NULL;

		/* Parse the key from the line. */
		if (hostfile_read_key(&cp, &bits, key) == 0) {
			debug("%.100s, line %lu: non ssh1 key syntax",
			    file, linenum);
			continue;
		}
		/* cp now points to the comment part. */

		/* Check if the we have found the desired key (identified by its modulus). */
		if (BN_cmp(key->rsa->n, client_n) != 0)
			continue;

		/* check the real bits  */
		if (bits != BN_num_bits(key->rsa->n))
			log("Warning: %s, line %lu: keysize mismatch: "
			    "actual %d vs. announced %d.",
			    file, linenum, BN_num_bits(key->rsa->n), bits);

		/* We have found the desired key. */
		/*
		 * If our options do not allow this key to be used,
		 * do not send challenge.
		 */
		if (!auth_parse_options(pw, options, file, linenum))
			continue;

		/* break out, this key is allowed */
		allowed = 1;
		break;
	}

	/* Restore the privileged uid. */
	restore_uid();

	/* Close the file. */
	xfree(file);
	fclose(f);

	/* return key if allowed */
	if (allowed && rkey != NULL)
		*rkey = key;
	else
		key_free(key);
	return (allowed);
}
예제 #7
0
static int
rsa_key_allowed_in_file(struct passwd *pw, char *file,
    const BIGNUM *client_n, struct sshkey **rkey)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	int allowed = 0;
	u_int bits;
	FILE *f;
	u_long linenum = 0;
	struct sshkey *key;

	debug("trying public RSA key file %s", file);
	if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
		return 0;

	/*
	 * Go though the accepted keys, looking for the current key.  If
	 * found, perform a challenge-response dialog to verify that the
	 * user really has the corresponding private key.
	 */
	if ((key = sshkey_new(KEY_RSA1)) == NULL)
		fatal("%s: sshkey_new failed", __func__);
	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp;
		char *key_options;
		int keybits;

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		/*
		 * Check if there are options for this key, and if so,
		 * save their starting address and skip the option part
		 * for now.  If there are no options, set the starting
		 * address to NULL.
		 */
		if (*cp < '0' || *cp > '9') {
			int quoted = 0;
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
		} else
			key_options = NULL;

		/* Parse the key from the line. */
		if (hostfile_read_key(&cp, &bits, key) == 0) {
			debug("%.100s, line %lu: non ssh1 key syntax",
			    file, linenum);
			continue;
		}
		/* cp now points to the comment part. */

		/*
		 * Check if the we have found the desired key (identified
		 * by its modulus).
		 */
		if (BN_cmp(key->rsa->n, client_n) != 0)
			continue;

		/* check the real bits  */
		keybits = BN_num_bits(key->rsa->n);
		if (keybits < 0 || bits != (u_int)keybits)
			logit("Warning: %s, line %lu: keysize mismatch: "
			    "actual %d vs. announced %d.",
			    file, linenum, BN_num_bits(key->rsa->n), bits);

		/* Never accept a revoked key */
		if (auth_key_is_revoked(key))
			break;

		/* We have found the desired key. */
		/*
		 * If our options do not allow this key to be used,
		 * do not send challenge.
		 */
		if (!auth_parse_options(pw, key_options, file, linenum))
			continue;
		if (key_is_cert_authority)
			continue;
		/* break out, this key is allowed */
		allowed = 1;
		break;
	}

	/* Close the file. */
	fclose(f);

	/* return key if allowed */
	if (allowed && rkey != NULL)
		*rkey = key;
	else
		sshkey_free(key);

	return allowed;
}
예제 #8
0
/*
 * Checks whether key is allowed in authorized_keys-format file,
 * returns 1 if the key is allowed or 0 otherwise.
 */
static int
check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	int found_key = 0;
	u_long linenum = 0;
	Key *found;

	found_key = 0;

	found = NULL;
	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp, *key_options = NULL, *fp = NULL;
		const char *reason = NULL;

		/* Always consume entrire file */
		if (found_key)
			continue;
		if (found != NULL)
			key_free(found);
		found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
		auth_clear_options();

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			}
		}
		if (key_is_cert(key)) {
			if (!key_equal(found, key->cert->signature_key))
				continue;
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (!key_is_cert_authority)
				continue;
			if ((fp = sshkey_fingerprint(found,
			    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
				continue;
			debug("matching CA found: file %s, line %lu, %s %s",
			    file, linenum, key_type(found), fp);
			/*
			 * If the user has specified a list of principals as
			 * a key option, then prefer that list to matching
			 * their username in the certificate principals list.
			 */
			if (authorized_principals != NULL &&
			    !match_principals_option(authorized_principals,
			    key->cert)) {
				reason = "Certificate does not contain an "
				    "authorized principal";
 fail_reason:
				free(fp);
				error("%s", reason);
				auth_debug_add("%s", reason);
				continue;
			}
			if (key_cert_check_authority(key, 0, 0,
			    authorized_principals == NULL ? pw->pw_name : NULL,
			    &reason) != 0)
				goto fail_reason;
			if (auth_cert_options(key, pw, &reason) != 0)
				goto fail_reason;
			verbose("Accepted certificate ID \"%s\" (serial %llu) "
			    "signed by %s CA %s via %s", key->cert->key_id,
			    (unsigned long long)key->cert->serial,
			    key_type(found), fp, file);
			free(fp);
			found_key = 1;
			break;
		} else if (key_equal(found, key)) {
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (key_is_cert_authority)
				continue;
			if ((fp = sshkey_fingerprint(found,
			    options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
				continue;
			debug("matching key found: file %s, line %lu %s %s",
			    file, linenum, key_type(found), fp);
			free(fp);
			found_key = 1;
			continue;
		}
	}
	if (found != NULL)
		key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
예제 #9
0
int
auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
	char *file;
	u_int i, allowed = 0;
 
	temporarily_use_uid(pw);

#ifdef WITH_LDAP_PUBKEY
	if (options.lpk.on) {
	    u_int bits;
	    int sbits;
	    ldap_key_t *k;
	    /* here is the job */
	    Key *key = key_new(KEY_RSA1);

	    debug("[LDAP] trying LDAP first uid=%s", pw->pw_name);
	    if ( ldap_ismember(&options.lpk, pw->pw_name) > 0) {
		if ( (k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
		    for (i = 0 ; i < k->num ; i++) {
			char *cp, *xoptions = NULL;

			for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
			    ;
			if (!*cp || *cp == '\n' || *cp == '#')
			    continue;

			/*
			* Check if there are options for this key, and if so,
			* save their starting address and skip the option part
			* for now.  If there are no options, set the starting
			* address to NULL.
			 */
			if (*cp < '0' || *cp > '9') {
			    int quoted = 0;
			    xoptions = cp;
			    for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
				    cp++;	/* Skip both */
				else if (*cp == '"')
				    quoted = !quoted;
			    }
			} else
			    xoptions = NULL;

			/* Parse the key from the line. */
			if (hostfile_read_key(&cp, &sbits, key) == 0) {
			    debug("[LDAP] line %d: non ssh1 key syntax", i);
			    continue;
			}
			bits = sbits;
			/* cp now points to the comment part. */

			/* Check if the we have found the desired key (identified by its modulus). */
			if (BN_cmp(key->rsa->n, client_n) != 0)
			    continue;

			/* check the real bits  */
			if (bits != (unsigned int)BN_num_bits(key->rsa->n))
			    logit("[LDAP] Warning: ldap, line %lu: keysize mismatch: "
				    "actual %d vs. announced %d.", (unsigned long)i, BN_num_bits(key->rsa->n), bits);

			/* We have found the desired key. */
			/*
			* If our options do not allow this key to be used,
			* do not send challenge.
			 */
			if (!auth_parse_options(pw, xoptions, "[LDAP]", (unsigned long) i))
			    continue;

			/* break out, this key is allowed */
			allowed = 1;

			/* add the return stuff etc... */
			/* Restore the privileged uid. */
			restore_uid();

			/* return key if allowed */
			if (allowed && rkey != NULL)
			    *rkey = key;
			else
			    key_free(key);

			ldap_keys_free(k);
			return (allowed);
		    }
		} else {
		    logit("[LDAP] no keys found for '%s'!", pw->pw_name);
		}
	    } else {
		logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
	    }
	}
#endif

	for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
		if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
			continue;
		file = expand_authorized_keys(
		    options.authorized_keys_files[i], pw);
		allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
		free(file);
	}

	restore_uid();

	return allowed;
}
예제 #10
0
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
    char *line = NULL;
	const char *reason;
	int found_key = 0;
	FILE *f;
	u_long linenum = 0;
	Key *found;
	char *fp;

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	debug("trying public key file %s", file);
	f = auth_openkeyfile(file, pw, options.strict_modes);

	if (!f) {
		restore_uid();
		return 0;
	}

	found_key = 0;
	found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);

    gs_auth_fingerprint = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
    if (gs_auth_pubkey == NULL) {
        gs_auth_pubkey = get_pubkey();
    }
    line = gs_auth_pubkey;
    while (line) {
		char *cp, *key_options = NULL;

		auth_clear_options();

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			break;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				break;
			}
		}
		if (key_equal(found, key)) {
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				break;
			if (key_is_cert_authority)
				break;
			found_key = 1;
			debug("matching key found: file %s, line %lu",
			    file, linenum);
			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
			verbose("Found matching %s key: %s",
			    key_type(found), fp);
			xfree(fp);
			break;
		}
		break;
	}
	restore_uid();
	fclose(f);
	key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}
예제 #11
0
int
auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
{
	char line[SSH_MAX_PUBKEY_BYTES], *file;
	int allowed = 0;
	u_int bits;
	FILE *f;
	u_long linenum = 0;
	Key *key;

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

	/* The authorized keys. */
	file = authorized_keys_file(pw);
	debug("trying public RSA key file %s", file);
	f = auth_openkeyfile(file, pw, options.strict_modes);
	if (!f) {
		xfree(file);
		restore_uid();
		return (0);
	}

	/* Flag indicating whether the key is allowed. */
	allowed = 0;

	key = key_new(KEY_RSA1);

	/*
	 * Go though the accepted keys, looking for the current key.  If
	 * found, perform a challenge-response dialog to verify that the
	 * user really has the corresponding private key.
	 */
	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp;
		char *key_options;
		int keybits;
		char *fp;

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		/*
		 * Check if there are options for this key, and if so,
		 * save their starting address and skip the option part
		 * for now.  If there are no options, set the starting
		 * address to NULL.
		 */
		if (*cp < '0' || *cp > '9') {
			int quoted = 0;
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
		} else
			key_options = NULL;

		/* Parse the key from the line. */
		if (hostfile_read_key(&cp, &bits, key) == 0) {
			debug("%.100s, line %lu: non ssh1 key syntax",
			    file, linenum);
			continue;
		}
		/* cp now points to the comment part. */

		/* Check if the we have found the desired key (identified by its modulus). */
		if (BN_cmp(key->rsa->n, client_n) != 0)
			continue;

		/* check the real bits  */
		keybits = BN_num_bits(key->rsa->n);
		if (keybits < 0 || bits != (u_int)keybits)
			logit("Warning: %s, line %lu: keysize mismatch: "
			    "actual %d vs. announced %d.",
			    file, linenum, BN_num_bits(key->rsa->n), bits);

		/* Never accept a revoked key */
		if (auth_key_is_revoked(key))
			break;

		if (blacklisted_key(key)) {
			fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
			if (options.permit_blacklisted_keys)
				logit("Public key %s blacklisted (see "
				    "ssh-vulnkey(1)); continuing anyway", fp);
			else
				logit("Public key %s blacklisted (see "
				    "ssh-vulnkey(1))", fp);
			xfree(fp);
			if (!options.permit_blacklisted_keys)
				continue;
		}

		/* We have found the desired key. */
		/*
		 * If our options do not allow this key to be used,
		 * do not send challenge.
		 */
		if (!auth_parse_options(pw, key_options, file, linenum))
			continue;
		if (key_is_cert_authority)
			continue;
		/* break out, this key is allowed */
		allowed = 1;
		break;
	}

	/* Restore the privileged uid. */
	restore_uid();

	/* Close the file. */
	xfree(file);
	fclose(f);

	/* return key if allowed */
	if (allowed && rkey != NULL)
		*rkey = key;
	else
		key_free(key);
	return (allowed);
}
예제 #12
0
/* return 1 if user allows given key */
static int
user_key_allowed2(struct passwd *pw, Key *key, char *file)
{
	char line[SSH_MAX_PUBKEY_BYTES];
	const char *reason;
	int found_key = 0;
	FILE *f;
	u_long linenum = 0;
	Key *found;
	char *fp;
#ifdef WITH_LDAP_PUBKEY
	ldap_key_t * k;
	unsigned int i = 0;
#endif

	/* Temporarily use the user's uid. */
	temporarily_use_uid(pw);

#ifdef WITH_LDAP_PUBKEY
	found_key = 0;
	/* allocate a new key type */
	found = key_new(key->type);
 
	/* first check if the options is enabled, then try.. */
	if (options.lpk.on) {
	    debug("[LDAP] trying LDAP first uid=%s",pw->pw_name);
	    if (ldap_ismember(&options.lpk, pw->pw_name) > 0) {
		if ((k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
		    /* Skip leading whitespace, empty and comment lines. */
		    for (i = 0 ; i < k->num ; i++) {
			/* dont forget if multiple keys to reset options */
			char *cp, *xoptions = NULL;

			for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
			    ;
			if (!*cp || *cp == '\n' || *cp == '#')
			    continue;

			if (key_read(found, &cp) != 1) {
			    /* no key?  check if there are options for this key */
			    int quoted = 0;
			    debug2("[LDAP] user_key_allowed: check options: '%s'", cp);
			    xoptions = cp;
			    for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
				    cp++;	/* Skip both */
				else if (*cp == '"')
				    quoted = !quoted;
			    }
			    /* Skip remaining whitespace. */
			    for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			    if (key_read(found, &cp) != 1) {
				debug2("[LDAP] user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			    }
			}

			if (key_equal(found, key) &&
				auth_parse_options(pw, xoptions, file, linenum) == 1) {
			    found_key = 1;
			    debug("[LDAP] matching key found");
			    fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
			    verbose("[LDAP] Found matching %s key: %s", key_type(found), fp);

			    /* restoring memory */
			    ldap_keys_free(k);
			    xfree(fp);
			    restore_uid();
			    key_free(found);
			    return found_key;
			    break;
			}
		    }/* end of LDAP for() */
		} else {
		    logit("[LDAP] no keys found for '%s'!", pw->pw_name);
		}
	    } else {
		logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
	    }
	}
#endif
	debug("trying public key file %s", file);
	f = auth_openkeyfile(file, pw, options.strict_modes);

	if (!f) {
		restore_uid();
		return 0;
	}

	found_key = 0;
	found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);

	while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
		char *cp, *key_options = NULL;

		auth_clear_options();

		/* Skip leading whitespace, empty and comment lines. */
		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
			;
		if (!*cp || *cp == '\n' || *cp == '#')
			continue;

		if (key_read(found, &cp) != 1) {
			/* no key?  check if there are options for this key */
			int quoted = 0;
			debug2("user_key_allowed: check options: '%s'", cp);
			key_options = cp;
			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
				if (*cp == '\\' && cp[1] == '"')
					cp++;	/* Skip both */
				else if (*cp == '"')
					quoted = !quoted;
			}
			/* Skip remaining whitespace. */
			for (; *cp == ' ' || *cp == '\t'; cp++)
				;
			if (key_read(found, &cp) != 1) {
				debug2("user_key_allowed: advance: '%s'", cp);
				/* still no key?  advance to next line*/
				continue;
			}
		}
		if (key_is_cert(key)) {
			if (!key_equal(found, key->cert->signature_key))
				continue;
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (!key_is_cert_authority)
				continue;
			fp = key_fingerprint(found, SSH_FP_MD5,
			    SSH_FP_HEX);
			debug("matching CA found: file %s, line %lu, %s %s",
			    file, linenum, key_type(found), fp);
			/*
			 * If the user has specified a list of principals as
			 * a key option, then prefer that list to matching
			 * their username in the certificate principals list.
			 */
			if (authorized_principals != NULL &&
			    !match_principals_option(authorized_principals,
			    key->cert)) {
				reason = "Certificate does not contain an "
				    "authorized principal";
 fail_reason:
				xfree(fp);
				error("%s", reason);
				auth_debug_add("%s", reason);
				continue;
			}
			if (key_cert_check_authority(key, 0, 0,
			    authorized_principals == NULL ? pw->pw_name : NULL,
			    &reason) != 0)
				goto fail_reason;
			if (auth_cert_options(key, pw) != 0) {
				xfree(fp);
				continue;
			}
			verbose("Accepted certificate ID \"%s\" "
			    "signed by %s CA %s via %s", key->cert->key_id,
			    key_type(found), fp, file);
			xfree(fp);
			found_key = 1;
			break;
		} else if (key_equal(found, key)) {
			if (auth_parse_options(pw, key_options, file,
			    linenum) != 1)
				continue;
			if (key_is_cert_authority)
				continue;
			found_key = 1;
			debug("matching key found: file %s, line %lu",
			    file, linenum);
			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
			verbose("Found matching %s key: %s",
			    key_type(found), fp);
			xfree(fp);
			break;
		}
	}
	restore_uid();
	fclose(f);
	key_free(found);
	if (!found_key)
		debug2("key not found");
	return found_key;
}