- extern ServerOptions options;
- char line[8192];
- int authenticated;
- unsigned int bits;
- FILE *f;
- unsigned long linenum = 0;
- struct stat st;
- BIGNUM *e, *n;
-
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw->pw_uid);
-
- /* The authorized keys. */
- snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir,
- SSH_USER_PERMITTED_KEYS);
-
- /* Fail quietly if file does not exist */
- if (stat(line, &st) < 0)
- {
- /* Restore the privileged uid. */
- restore_uid();
- return 0;
- }
-
- /* Open the file containing the authorized keys. */
- f = fopen(line, "r");
- if (!f)
- {
- /* Restore the privileged uid. */
- restore_uid();
- packet_send_debug("Could not open %.900s for reading.", line);
- packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
- return 0;
- }
-
- if (options.strict_modes) {
- int fail=0;
- char buf[1024];
- /* Check open file in order to avoid open/stat races */
- if (fstat(fileno(f), &st) < 0 ||
- (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
- (st.st_mode & 022) != 0) {
- snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
- "bad ownership or modes for '%s'.", pw->pw_name, line);
- fail=1;
- }else{
- /* Check path to SSH_USER_PERMITTED_KEYS */
- int i;
- static const char *check[] = {
- "", SSH_USER_DIR, NULL
- };
- for (i=0; check[i]; i++) {
- snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
- if (stat(line, &st) < 0 ||
- (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
- (st.st_mode & 022) != 0) {
- snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
- "bad ownership or modes for '%s'.", pw->pw_name, line);
- fail=1;
- break;
- }
- }
- }
- if (fail) {
- log(buf);
- packet_send_debug(buf);
- restore_uid();
- return 0;
- }
- }
-
- /* Flag indicating whether authentication has succeeded. */
- authenticated = 0;
-
- /* Initialize mp-int variables. */
- e = BN_new();
- n = BN_new();
-
- /* 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. */
- for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
- ;
-
- /* Skip empty and comment lines. */
- 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;
- }