[BACK]Return to authfile.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/authfile.c, Revision 1.107

1.107   ! djm         1: /* $OpenBSD: authfile.c,v 1.106 2014/04/29 18:01:49 markus Exp $ */
1.1       deraadt     2: /*
1.99      markus      3:  * Copyright (c) 2000, 2013 Markus Friedl.  All rights reserved.
1.19      deraadt     4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  *
                     14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     15:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     16:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     17:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     18:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     19:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     20:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     21:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     22:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     23:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.9       deraadt    24:  */
1.1       deraadt    25:
1.62      stevesk    26:
                     27: #include <sys/types.h>
                     28: #include <sys/stat.h>
1.72      stevesk    29: #include <sys/param.h>
1.76      deraadt    30: #include <sys/uio.h>
1.1       deraadt    31:
1.69      stevesk    32: #include <errno.h>
1.68      stevesk    33: #include <fcntl.h>
1.74      stevesk    34: #include <stdio.h>
1.73      stevesk    35: #include <stdlib.h>
1.71      stevesk    36: #include <string.h>
1.70      stevesk    37: #include <unistd.h>
1.15      markus     38:
1.25      markus     39: #include "cipher.h"
                     40: #include "key.h"
1.1       deraadt    41: #include "ssh.h"
1.25      markus     42: #include "log.h"
1.27      itojun     43: #include "authfile.h"
1.44      markus     44: #include "rsa.h"
1.60      dtucker    45: #include "misc.h"
1.61      djm        46: #include "atomicio.h"
1.107   ! djm        47: #include "sshbuf.h"
        !            48: #include "ssherr.h"
1.1       deraadt    49:
1.88      djm        50: #define MAX_KEY_FILE_SIZE      (1024 * 1024)
                     51:
1.86      djm        52: /* Save a key blob to a file */
                     53: static int
1.107   ! djm        54: sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
1.86      djm        55: {
1.107   ! djm        56:        int fd, oerrno;
1.86      djm        57:
1.107   ! djm        58:        if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
        !            59:                return SSH_ERR_SYSTEM_ERROR;
        !            60:        if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf),
        !            61:            sshbuf_len(keybuf)) != sshbuf_len(keybuf)) {
        !            62:                oerrno = errno;
1.86      djm        63:                close(fd);
                     64:                unlink(filename);
1.107   ! djm        65:                errno = oerrno;
        !            66:                return SSH_ERR_SYSTEM_ERROR;
1.86      djm        67:        }
                     68:        close(fd);
1.107   ! djm        69:        return 0;
1.86      djm        70: }
                     71:
                     72: int
1.107   ! djm        73: sshkey_save_private(struct sshkey *key, const char *filename,
        !            74:     const char *passphrase, const char *comment,
        !            75:     int force_new_format, const char *new_format_cipher, int new_format_rounds)
1.86      djm        76: {
1.107   ! djm        77:        struct sshbuf *keyblob = NULL;
        !            78:        int r;
1.86      djm        79:
1.107   ! djm        80:        if ((keyblob = sshbuf_new()) == NULL)
        !            81:                return SSH_ERR_ALLOC_FAIL;
        !            82:        if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
        !            83:            force_new_format, new_format_cipher, new_format_rounds)) != 0)
1.86      djm        84:                goto out;
1.107   ! djm        85:        if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
1.86      djm        86:                goto out;
1.107   ! djm        87:        r = 0;
1.86      djm        88:  out:
1.107   ! djm        89:        sshbuf_free(keyblob);
        !            90:        return r;
1.86      djm        91: }
                     92:
1.88      djm        93: /* Load a key from a fd into a buffer */
                     94: int
1.107   ! djm        95: sshkey_load_file(int fd, const char *filename, struct sshbuf *blob)
1.86      djm        96: {
1.88      djm        97:        u_char buf[1024];
1.86      djm        98:        size_t len;
1.51      fgsch      99:        struct stat st;
1.107   ! djm       100:        int r;
1.8       markus    101:
1.107   ! djm       102:        if (fstat(fd, &st) < 0)
        !           103:                return SSH_ERR_SYSTEM_ERROR;
1.88      djm       104:        if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
1.107   ! djm       105:            st.st_size > MAX_KEY_FILE_SIZE)
        !           106:                return SSH_ERR_INVALID_FORMAT;
1.88      djm       107:        for (;;) {
                    108:                if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
                    109:                        if (errno == EPIPE)
                    110:                                break;
1.107   ! djm       111:                        r = SSH_ERR_SYSTEM_ERROR;
        !           112:                        goto out;
1.88      djm       113:                }
1.107   ! djm       114:                if ((r = sshbuf_put(blob, buf, len)) != 0)
        !           115:                        goto out;
        !           116:                if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) {
        !           117:                        r = SSH_ERR_INVALID_FORMAT;
        !           118:                        goto out;
1.88      djm       119:                }
                    120:        }
                    121:        if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
1.107   ! djm       122:            st.st_size != (off_t)sshbuf_len(blob)) {
        !           123:                r = SSH_ERR_FILE_CHANGED;
        !           124:                goto out;
1.8       markus    125:        }
1.107   ! djm       126:        r = 0;
1.88      djm       127:
1.107   ! djm       128:  out:
        !           129:        explicit_bzero(buf, sizeof(buf));
        !           130:        if (r != 0)
        !           131:                sshbuf_reset(blob);
        !           132:        return r;
1.86      djm       133: }
1.8       markus    134:
1.106     markus    135: #ifdef WITH_SSH1
1.86      djm       136: /*
                    137:  * Loads the public part of the ssh v1 key file.  Returns NULL if an error was
                    138:  * encountered (the file does not exist or is not readable), and the key
                    139:  * otherwise.
                    140:  */
1.107   ! djm       141: static int
        !           142: sshkey_load_public_rsa1(int fd, const char *filename,
        !           143:     struct sshkey **keyp, char **commentp)
1.86      djm       144: {
1.107   ! djm       145:        struct sshbuf *b = NULL;
        !           146:        int r;
1.86      djm       147:
1.107   ! djm       148:        *keyp = NULL;
        !           149:        if (commentp != NULL)
        !           150:                *commentp = NULL;
1.8       markus    151:
1.107   ! djm       152:        if ((b = sshbuf_new()) == NULL)
        !           153:                return SSH_ERR_ALLOC_FAIL;
        !           154:        if ((r = sshkey_load_file(fd, filename, b)) != 0)
        !           155:                goto out;
        !           156:        if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
        !           157:                goto out;
        !           158:        r = 0;
        !           159:  out:
        !           160:        sshbuf_free(b);
        !           161:        return r;
1.1       deraadt   162: }
1.107   ! djm       163: #endif /* WITH_SSH1 */
1.1       deraadt   164:
1.107   ! djm       165: #ifdef WITH_OPENSSL
        !           166: /* XXX Deprecate? */
        !           167: int
        !           168: sshkey_load_private_pem(int fd, int type, const char *passphrase,
        !           169:     struct sshkey **keyp, char **commentp)
1.1       deraadt   170: {
1.107   ! djm       171:        struct sshbuf *buffer = NULL;
        !           172:        int r;
1.8       markus    173:
1.107   ! djm       174:        *keyp = NULL;
1.97      djm       175:        if (commentp != NULL)
1.107   ! djm       176:                *commentp = NULL;
1.15      markus    177:
1.107   ! djm       178:        if ((buffer = sshbuf_new()) == NULL)
        !           179:                return SSH_ERR_ALLOC_FAIL;
        !           180:        if ((r = sshkey_load_file(fd, NULL, buffer)) != 0)
        !           181:                goto out;
        !           182:        if ((r = sshkey_parse_private_pem_fileblob(buffer, type, passphrase,
        !           183:            keyp, commentp)) != 0)
        !           184:                goto out;
        !           185:        r = 0;
        !           186:  out:
        !           187:        sshbuf_free(buffer);
        !           188:        return r;
1.86      djm       189: }
1.107   ! djm       190: #endif /* WITH_OPENSSL */
1.86      djm       191:
1.107   ! djm       192: /* XXX remove error() calls from here? */
1.63      dtucker   193: int
1.107   ! djm       194: sshkey_perm_ok(int fd, const char *filename)
1.15      markus    195: {
                    196:        struct stat st;
                    197:
1.38      markus    198:        if (fstat(fd, &st) < 0)
1.107   ! djm       199:                return SSH_ERR_SYSTEM_ERROR;
1.38      markus    200:        /*
                    201:         * if a key owned by the user is accessed, then we check the
                    202:         * permissions of the file. if the key owned by a different user,
                    203:         * then we don't care.
                    204:         */
                    205:        if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
1.15      markus    206:                error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                    207:                error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");
                    208:                error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
1.38      markus    209:                error("Permissions 0%3.3o for '%s' are too open.",
1.54      djm       210:                    (u_int)st.st_mode & 0777, filename);
1.15      markus    211:                error("It is recommended that your private key files are NOT accessible by others.");
1.29      markus    212:                error("This private key will be ignored.");
1.107   ! djm       213:                return SSH_ERR_KEY_BAD_PERMISSIONS;
1.15      markus    214:        }
1.107   ! djm       215:        return 0;
1.29      markus    216: }
                    217:
1.107   ! djm       218: /* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
        !           219: int
        !           220: sshkey_load_private_type(int type, const char *filename, const char *passphrase,
        !           221:     struct sshkey **keyp, char **commentp, int *perm_ok)
1.86      djm       222: {
1.107   ! djm       223:        int fd, r;
        !           224:        struct sshbuf *buffer = NULL;
1.99      markus    225:
1.107   ! djm       226:        *keyp = NULL;
        !           227:        if (commentp != NULL)
        !           228:                *commentp = NULL;
1.86      djm       229:
1.107   ! djm       230:        if ((fd = open(filename, O_RDONLY)) < 0) {
1.78      dtucker   231:                if (perm_ok != NULL)
                    232:                        *perm_ok = 0;
1.107   ! djm       233:                return SSH_ERR_SYSTEM_ERROR;
1.78      dtucker   234:        }
1.107   ! djm       235:        if (sshkey_perm_ok(fd, filename) != 0) {
1.67      dtucker   236:                if (perm_ok != NULL)
                    237:                        *perm_ok = 0;
1.107   ! djm       238:                r = SSH_ERR_KEY_BAD_PERMISSIONS;
        !           239:                goto out;
1.29      markus    240:        }
1.67      dtucker   241:        if (perm_ok != NULL)
                    242:                *perm_ok = 1;
1.86      djm       243:
1.107   ! djm       244:        if ((buffer = sshbuf_new()) == NULL) {
        !           245:                r = SSH_ERR_ALLOC_FAIL;
        !           246:                goto out;
1.15      markus    247:        }
1.107   ! djm       248:        if ((r = sshkey_load_file(fd, filename, buffer)) != 0)
        !           249:                goto out;
        !           250:        if ((r = sshkey_parse_private_fileblob_type(buffer, type, passphrase,
        !           251:            keyp, commentp)) != 0)
        !           252:                goto out;
        !           253:        r = 0;
        !           254:  out:
1.86      djm       255:        close(fd);
1.107   ! djm       256:        if (buffer != NULL)
        !           257:                sshbuf_free(buffer);
        !           258:        return r;
1.29      markus    259: }
                    260:
1.107   ! djm       261: /* XXX this is almost identical to sshkey_load_private_type() */
        !           262: int
        !           263: sshkey_load_private(const char *filename, const char *passphrase,
        !           264:     struct sshkey **keyp, char **commentp)
1.88      djm       265: {
1.107   ! djm       266:        struct sshbuf *buffer = NULL;
        !           267:        int r, fd;
1.88      djm       268:
1.107   ! djm       269:        *keyp = NULL;
        !           270:        if (commentp != NULL)
        !           271:                *commentp = NULL;
1.88      djm       272:
1.107   ! djm       273:        if ((fd = open(filename, O_RDONLY)) < 0)
        !           274:                return SSH_ERR_SYSTEM_ERROR;
        !           275:        if (sshkey_perm_ok(fd, filename) != 0) {
        !           276:                r = SSH_ERR_KEY_BAD_PERMISSIONS;
        !           277:                goto out;
1.29      markus    278:        }
1.86      djm       279:
1.107   ! djm       280:        if ((buffer = sshbuf_new()) == NULL) {
        !           281:                r = SSH_ERR_ALLOC_FAIL;
        !           282:                goto out;
1.86      djm       283:        }
1.107   ! djm       284:        if ((r = sshkey_load_file(fd, filename, buffer)) != 0 ||
        !           285:            (r = sshkey_parse_private_fileblob(buffer, passphrase, filename,
        !           286:            keyp, commentp)) != 0)
        !           287:                goto out;
        !           288:        r = 0;
        !           289:  out:
1.86      djm       290:        close(fd);
1.107   ! djm       291:        if (buffer != NULL)
        !           292:                sshbuf_free(buffer);
        !           293:        return r;
1.18      markus    294: }
                    295:
1.37      itojun    296: static int
1.107   ! djm       297: sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
1.18      markus    298: {
                    299:        FILE *f;
1.59      dtucker   300:        char line[SSH_MAX_PUBKEY_BYTES];
1.18      markus    301:        char *cp;
1.60      dtucker   302:        u_long linenum = 0;
1.107   ! djm       303:        int r;
1.18      markus    304:
1.107   ! djm       305:        if (commentp != NULL)
        !           306:                *commentp = NULL;
        !           307:        if ((f = fopen(filename, "r")) == NULL)
        !           308:                return SSH_ERR_SYSTEM_ERROR;
        !           309:        while (read_keyfile_line(f, filename, line, sizeof(line),
        !           310:                    &linenum) != -1) {
        !           311:                cp = line;
        !           312:                switch (*cp) {
        !           313:                case '#':
        !           314:                case '\n':
        !           315:                case '\0':
        !           316:                        continue;
        !           317:                }
        !           318:                /* Abort loading if this looks like a private key */
        !           319:                if (strncmp(cp, "-----BEGIN", 10) == 0 ||
        !           320:                    strcmp(cp, "SSH PRIVATE KEY FILE") == 0)
        !           321:                        break;
        !           322:                /* Skip leading whitespace. */
        !           323:                for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
        !           324:                        ;
        !           325:                if (*cp) {
        !           326:                        if ((r = sshkey_read(k, &cp)) == 0) {
        !           327:                                cp[strcspn(cp, "\r\n")] = '\0';
        !           328:                                if (commentp) {
        !           329:                                        *commentp = strdup(*cp ?
        !           330:                                            cp : filename);
        !           331:                                        if (*commentp == NULL)
        !           332:                                                r = SSH_ERR_ALLOC_FAIL;
1.18      markus    333:                                }
1.107   ! djm       334:                                fclose(f);
        !           335:                                return r;
1.18      markus    336:                        }
                    337:                }
                    338:        }
1.107   ! djm       339:        fclose(f);
        !           340:        return SSH_ERR_INVALID_FORMAT;
1.18      markus    341: }
                    342:
1.29      markus    343: /* load public key from ssh v1 private or any pubkey file */
1.107   ! djm       344: int
        !           345: sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
1.18      markus    346: {
1.107   ! djm       347:        struct sshkey *pub = NULL;
1.29      markus    348:        char file[MAXPATHLEN];
1.107   ! djm       349:        int r, fd;
1.18      markus    350:
1.107   ! djm       351:        if (keyp != NULL)
        !           352:                *keyp = NULL;
        !           353:        if (commentp != NULL)
        !           354:                *commentp = NULL;
        !           355:
        !           356:        if ((fd = open(filename, O_RDONLY)) < 0)
        !           357:                goto skip;
1.106     markus    358: #ifdef WITH_SSH1
1.53      markus    359:        /* try rsa1 private key */
1.107   ! djm       360:        r = sshkey_load_public_rsa1(fd, filename, keyp, commentp);
        !           361:        close(fd);
        !           362:        switch (r) {
        !           363:        case SSH_ERR_INTERNAL_ERROR:
        !           364:        case SSH_ERR_ALLOC_FAIL:
        !           365:        case SSH_ERR_INVALID_ARGUMENT:
        !           366:        case SSH_ERR_SYSTEM_ERROR:
        !           367:        case 0:
        !           368:                return r;
        !           369:        }
        !           370: #endif /* WITH_SSH1 */
        !           371:
        !           372:        /* try ssh2 public key */
        !           373:        if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
        !           374:                return SSH_ERR_ALLOC_FAIL;
        !           375:        if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
        !           376:                if (keyp != NULL)
        !           377:                        *keyp = pub;
        !           378:                return 0;
        !           379:        }
        !           380:        sshkey_free(pub);
1.53      markus    381:
1.107   ! djm       382: #ifdef WITH_SSH1
1.53      markus    383:        /* try rsa1 public key */
1.107   ! djm       384:        if ((pub = sshkey_new(KEY_RSA1)) == NULL)
        !           385:                return SSH_ERR_ALLOC_FAIL;
        !           386:        if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
        !           387:                if (keyp != NULL)
        !           388:                        *keyp = pub;
        !           389:                return 0;
        !           390:        }
        !           391:        sshkey_free(pub);
        !           392: #endif /* WITH_SSH1 */
1.53      markus    393:
1.107   ! djm       394:  skip:
        !           395:        /* try .pub suffix */
        !           396:        if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
        !           397:                return SSH_ERR_ALLOC_FAIL;
        !           398:        r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */
1.29      markus    399:        if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
                    400:            (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
1.107   ! djm       401:            (r = sshkey_try_load_public(pub, file, commentp)) == 0) {
        !           402:                if (keyp != NULL)
        !           403:                        *keyp = pub;
        !           404:                return 0;
        !           405:        }
        !           406:        sshkey_free(pub);
        !           407:        return r;
1.81      djm       408: }
                    409:
                    410: /* Load the certificate associated with the named private key */
1.107   ! djm       411: int
        !           412: sshkey_load_cert(const char *filename, struct sshkey **keyp)
1.81      djm       413: {
1.107   ! djm       414:        struct sshkey *pub = NULL;
        !           415:        char *file = NULL;
        !           416:        int r = SSH_ERR_INTERNAL_ERROR;
        !           417:
        !           418:        *keyp = NULL;
1.81      djm       419:
1.107   ! djm       420:        if (asprintf(&file, "%s-cert.pub", filename) == -1)
        !           421:                return SSH_ERR_ALLOC_FAIL;
        !           422:
        !           423:        if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
        !           424:                goto out;
        !           425:        }
        !           426:        if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
        !           427:                goto out;
        !           428:
        !           429:        *keyp = pub;
        !           430:        pub = NULL;
        !           431:        r = 0;
        !           432:
        !           433:  out:
        !           434:        if (file != NULL)
1.97      djm       435:                free(file);
1.107   ! djm       436:        if (pub != NULL)
        !           437:                sshkey_free(pub);
        !           438:        return r;
1.81      djm       439: }
                    440:
                    441: /* Load private key and certificate */
1.107   ! djm       442: int
        !           443: sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
        !           444:     struct sshkey **keyp, int *perm_ok)
1.81      djm       445: {
1.107   ! djm       446:        struct sshkey *key = NULL, *cert = NULL;
        !           447:        int r;
        !           448:
        !           449:        *keyp = NULL;
1.81      djm       450:
                    451:        switch (type) {
1.106     markus    452: #ifdef WITH_OPENSSL
1.81      djm       453:        case KEY_RSA:
                    454:        case KEY_DSA:
1.83      djm       455:        case KEY_ECDSA:
1.101     djm       456:        case KEY_ED25519:
1.107   ! djm       457: #endif /* WITH_OPENSSL */
        !           458:        case KEY_UNSPEC:
1.81      djm       459:                break;
                    460:        default:
1.107   ! djm       461:                return SSH_ERR_KEY_TYPE_UNKNOWN;
1.81      djm       462:        }
                    463:
1.107   ! djm       464:        if ((r = sshkey_load_private_type(type, filename,
        !           465:            passphrase, &key, NULL, perm_ok)) != 0 ||
        !           466:            (r = sshkey_load_cert(filename, &cert)) != 0)
        !           467:                goto out;
1.81      djm       468:
                    469:        /* Make sure the private key matches the certificate */
1.107   ! djm       470:        if (sshkey_equal_public(key, cert) == 0) {
        !           471:                r = SSH_ERR_KEY_CERT_MISMATCH;
        !           472:                goto out;
1.81      djm       473:        }
                    474:
1.107   ! djm       475:        if ((r = sshkey_to_certified(key, sshkey_cert_is_legacy(cert))) != 0 ||
        !           476:            (r = sshkey_cert_copy(cert, key)) != 0)
        !           477:                goto out;
        !           478:        r = 0;
        !           479:        *keyp = key;
        !           480:        key = NULL;
        !           481:  out:
        !           482:        if (key != NULL)
        !           483:                sshkey_free(key);
        !           484:        if (cert != NULL)
        !           485:                sshkey_free(cert);
        !           486:        return r;
1.1       deraadt   487: }
1.80      djm       488:
                    489: /*
1.107   ! djm       490:  * Returns success if the specified "key" is listed in the file "filename",
        !           491:  * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
1.80      djm       492:  * If strict_type is set then the key type must match exactly,
                    493:  * otherwise a comparison that ignores certficiate data is performed.
                    494:  */
                    495: int
1.107   ! djm       496: sshkey_in_file(struct sshkey *key, const char *filename, int strict_type)
1.80      djm       497: {
                    498:        FILE *f;
                    499:        char line[SSH_MAX_PUBKEY_BYTES];
                    500:        char *cp;
                    501:        u_long linenum = 0;
1.107   ! djm       502:        int r = 0;
        !           503:        struct sshkey *pub = NULL;
        !           504:        int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
        !           505:            strict_type ?  sshkey_equal : sshkey_equal_public;
1.80      djm       506:
                    507:        if ((f = fopen(filename, "r")) == NULL) {
1.107   ! djm       508:                if (errno == ENOENT)
        !           509:                        return SSH_ERR_KEY_NOT_FOUND;
        !           510:                else
        !           511:                        return SSH_ERR_SYSTEM_ERROR;
1.80      djm       512:        }
                    513:
                    514:        while (read_keyfile_line(f, filename, line, sizeof(line),
1.107   ! djm       515:            &linenum) != -1) {
1.80      djm       516:                cp = line;
                    517:
                    518:                /* Skip leading whitespace. */
                    519:                for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
                    520:                        ;
                    521:
                    522:                /* Skip comments and empty lines */
                    523:                switch (*cp) {
                    524:                case '#':
                    525:                case '\n':
                    526:                case '\0':
                    527:                        continue;
                    528:                }
                    529:
1.107   ! djm       530:                if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
        !           531:                        r = SSH_ERR_ALLOC_FAIL;
        !           532:                        goto out;
1.80      djm       533:                }
1.107   ! djm       534:                if ((r = sshkey_read(pub, &cp)) != 0)
        !           535:                        goto out;
        !           536:                if (sshkey_compare(key, pub)) {
        !           537:                        r = 0;
        !           538:                        goto out;
1.80      djm       539:                }
1.107   ! djm       540:                sshkey_free(pub);
        !           541:                pub = NULL;
1.80      djm       542:        }
1.107   ! djm       543:        r = SSH_ERR_KEY_NOT_FOUND;
        !           544:  out:
        !           545:        if (pub != NULL)
        !           546:                sshkey_free(pub);
1.80      djm       547:        fclose(f);
1.107   ! djm       548:        return r;
1.80      djm       549: }
1.107   ! djm       550: