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

Annotation of src/usr.bin/ssh/authfd.c, Revision 1.13

1.1       deraadt     1: /*
1.13    ! deraadt     2:  *
        !             3:  * authfd.c
        !             4:  *
        !             5:  * Author: Tatu Ylonen <ylo@cs.hut.fi>
        !             6:  *
        !             7:  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
        !             8:  *                    All rights reserved
        !             9:  *
        !            10:  * Created: Wed Mar 29 01:30:28 1995 ylo
        !            11:  *
        !            12:  * Functions for connecting the local authentication agent.
        !            13:  *
        !            14:  */
1.1       deraadt    15:
                     16: #include "includes.h"
1.13    ! deraadt    17: RCSID("$Id: authfd.c,v 1.12 1999/11/23 22:25:52 markus Exp $");
1.1       deraadt    18:
                     19: #include "ssh.h"
                     20: #include "rsa.h"
                     21: #include "authfd.h"
                     22: #include "buffer.h"
                     23: #include "bufaux.h"
                     24: #include "xmalloc.h"
                     25: #include "getput.h"
                     26:
1.2       provos     27: #include <ssl/rsa.h>
                     28:
1.1       deraadt    29: /* Returns the number of the authentication fd, or -1 if there is none. */
                     30:
1.2       provos     31: int
1.8       markus     32: ssh_get_authentication_socket()
1.1       deraadt    33: {
1.12      markus     34:        const char *authsocket;
                     35:        int sock;
                     36:        struct sockaddr_un sunaddr;
                     37:
                     38:        authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
                     39:        if (!authsocket)
                     40:                return -1;
                     41:
                     42:        sunaddr.sun_family = AF_UNIX;
                     43:        strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
                     44:
                     45:        sock = socket(AF_UNIX, SOCK_STREAM, 0);
                     46:        if (sock < 0)
                     47:                return -1;
                     48:
                     49:        /* close on exec */
                     50:        if (fcntl(sock, F_SETFD, 1) == -1) {
                     51:                close(sock);
                     52:                return -1;
                     53:        }
                     54:        if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
                     55:                close(sock);
                     56:                return -1;
                     57:        }
                     58:        return sock;
1.1       deraadt    59: }
                     60:
                     61: /* Closes the agent socket if it should be closed (depends on how it was
1.12      markus     62:    obtained).  The argument must have been returned by
1.8       markus     63:    ssh_get_authentication_socket(). */
1.1       deraadt    64:
1.12      markus     65: void
                     66: ssh_close_authentication_socket(int sock)
1.1       deraadt    67: {
1.12      markus     68:        if (getenv(SSH_AUTHSOCKET_ENV_NAME))
                     69:                close(sock);
1.1       deraadt    70: }
                     71:
                     72: /* Opens and connects a private socket for communication with the
                     73:    authentication agent.  Returns the file descriptor (which must be
                     74:    shut down and closed by the caller when no longer needed).
                     75:    Returns NULL if an error occurred and the connection could not be
                     76:    opened. */
                     77:
1.12      markus     78: AuthenticationConnection *
                     79: ssh_get_authentication_connection()
1.1       deraadt    80: {
1.12      markus     81:        AuthenticationConnection *auth;
                     82:        int sock;
1.1       deraadt    83:
1.12      markus     84:        sock = ssh_get_authentication_socket();
                     85:
                     86:        /* Fail if we couldn't obtain a connection.  This happens if we
                     87:           exited due to a timeout. */
                     88:        if (sock < 0)
                     89:                return NULL;
                     90:
                     91:        /* Applocate the connection structure and initialize it. */
                     92:        auth = xmalloc(sizeof(*auth));
                     93:        auth->fd = sock;
                     94:        buffer_init(&auth->packet);
                     95:        buffer_init(&auth->identities);
                     96:        auth->howmany = 0;
                     97:
                     98:        return auth;
1.1       deraadt    99: }
                    100:
                    101: /* Closes the connection to the authentication agent and frees any associated
                    102:    memory. */
                    103:
1.12      markus    104: void
                    105: ssh_close_authentication_connection(AuthenticationConnection *ac)
1.1       deraadt   106: {
1.12      markus    107:        buffer_free(&ac->packet);
                    108:        buffer_free(&ac->identities);
                    109:        close(ac->fd);
                    110:        xfree(ac);
1.1       deraadt   111: }
                    112:
                    113: /* Returns the first authentication identity held by the agent.
                    114:    Returns true if an identity is available, 0 otherwise.
                    115:    The caller must initialize the integers before the call, and free the
                    116:    comment after a successful call (before calling ssh_get_next_identity). */
                    117:
1.2       provos    118: int
                    119: ssh_get_first_identity(AuthenticationConnection *auth,
1.9       markus    120:                       BIGNUM *e, BIGNUM *n, char **comment)
1.1       deraadt   121: {
1.12      markus    122:        unsigned char msg[8192];
                    123:        int len, l;
1.1       deraadt   124:
1.12      markus    125:        /* Send a message to the agent requesting for a list of the
                    126:           identities it can represent. */
                    127:        msg[0] = 0;
                    128:        msg[1] = 0;
                    129:        msg[2] = 0;
                    130:        msg[3] = 1;
                    131:        msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
                    132:        if (write(auth->fd, msg, 5) != 5) {
                    133:                error("write auth->fd: %.100s", strerror(errno));
                    134:                return 0;
                    135:        }
                    136:        /* Read the length of the response.  XXX implement timeouts here. */
                    137:        len = 4;
                    138:        while (len > 0) {
                    139:                l = read(auth->fd, msg + 4 - len, len);
                    140:                if (l <= 0) {
                    141:                        error("read auth->fd: %.100s", strerror(errno));
                    142:                        return 0;
                    143:                }
                    144:                len -= l;
                    145:        }
                    146:
                    147:        /* Extract the length, and check it for sanity.  (We cannot trust
                    148:           authentication agents). */
                    149:        len = GET_32BIT(msg);
                    150:        if (len < 1 || len > 256 * 1024)
                    151:                fatal("Authentication reply message too long: %d\n", len);
                    152:
                    153:        /* Read the packet itself. */
                    154:        buffer_clear(&auth->identities);
                    155:        while (len > 0) {
                    156:                l = len;
                    157:                if (l > sizeof(msg))
                    158:                        l = sizeof(msg);
                    159:                l = read(auth->fd, msg, l);
                    160:                if (l <= 0)
                    161:                        fatal("Incomplete authentication reply.");
                    162:                buffer_append(&auth->identities, (char *) msg, l);
                    163:                len -= l;
                    164:        }
1.1       deraadt   165:
1.12      markus    166:        /* Get message type, and verify that we got a proper answer. */
                    167:        buffer_get(&auth->identities, (char *) msg, 1);
                    168:        if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
                    169:                fatal("Bad authentication reply message type: %d", msg[0]);
                    170:
                    171:        /* Get the number of entries in the response and check it for sanity. */
                    172:        auth->howmany = buffer_get_int(&auth->identities);
                    173:        if (auth->howmany > 1024)
                    174:                fatal("Too many identities in authentication reply: %d\n", auth->howmany);
                    175:
                    176:        /* Return the first entry (if any). */
                    177:        return ssh_get_next_identity(auth, e, n, comment);
1.1       deraadt   178: }
                    179:
                    180: /* Returns the next authentication identity for the agent.  Other functions
                    181:    can be called between this and ssh_get_first_identity or two calls of this
                    182:    function.  This returns 0 if there are no more identities.  The caller
                    183:    must free comment after a successful return. */
                    184:
1.2       provos    185: int
                    186: ssh_get_next_identity(AuthenticationConnection *auth,
1.9       markus    187:                      BIGNUM *e, BIGNUM *n, char **comment)
1.1       deraadt   188: {
1.12      markus    189:        unsigned int bits;
1.9       markus    190:
1.12      markus    191:        /* Return failure if no more entries. */
                    192:        if (auth->howmany <= 0)
                    193:                return 0;
                    194:
                    195:        /* Get the next entry from the packet.  These will abort with a
                    196:           fatal error if the packet is too short or contains corrupt data. */
                    197:        bits = buffer_get_int(&auth->identities);
                    198:        buffer_get_bignum(&auth->identities, e);
                    199:        buffer_get_bignum(&auth->identities, n);
                    200:        *comment = buffer_get_string(&auth->identities, NULL);
                    201:
                    202:        if (bits != BN_num_bits(n))
                    203:                error("Warning: keysize mismatch: actual %d, announced %u",
                    204:                      BN_num_bits(n), bits);
1.9       markus    205:
1.12      markus    206:        /* Decrement the number of remaining entries. */
                    207:        auth->howmany--;
1.1       deraadt   208:
1.12      markus    209:        return 1;
1.1       deraadt   210: }
                    211:
                    212: /* Generates a random challenge, sends it to the agent, and waits for response
                    213:    from the agent.  Returns true (non-zero) if the agent gave the correct
                    214:    answer, zero otherwise.  Response type selects the style of response
                    215:    desired, with 0 corresponding to protocol version 1.0 (no longer supported)
                    216:    and 1 corresponding to protocol version 1.1. */
                    217:
1.2       provos    218: int
                    219: ssh_decrypt_challenge(AuthenticationConnection *auth,
1.12      markus    220:                      BIGNUM* e, BIGNUM *n, BIGNUM *challenge,
1.2       provos    221:                      unsigned char session_id[16],
                    222:                      unsigned int response_type,
                    223:                      unsigned char response[16])
1.1       deraadt   224: {
1.12      markus    225:        Buffer buffer;
                    226:        unsigned char buf[8192];
                    227:        int len, l, i;
                    228:
                    229:        /* Response type 0 is no longer supported. */
                    230:        if (response_type == 0)
                    231:                fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
                    232:
                    233:        /* Format a message to the agent. */
                    234:        buf[0] = SSH_AGENTC_RSA_CHALLENGE;
                    235:        buffer_init(&buffer);
                    236:        buffer_append(&buffer, (char *) buf, 1);
                    237:        buffer_put_int(&buffer, BN_num_bits(n));
                    238:        buffer_put_bignum(&buffer, e);
                    239:        buffer_put_bignum(&buffer, n);
                    240:        buffer_put_bignum(&buffer, challenge);
                    241:        buffer_append(&buffer, (char *) session_id, 16);
                    242:        buffer_put_int(&buffer, response_type);
                    243:
                    244:        /* Get the length of the message, and format it in the buffer. */
                    245:        len = buffer_len(&buffer);
                    246:        PUT_32BIT(buf, len);
                    247:
                    248:        /* Send the length and then the packet to the agent. */
                    249:        if (write(auth->fd, buf, 4) != 4 ||
                    250:            write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
                    251:            buffer_len(&buffer)) {
                    252:                error("Error writing to authentication socket.");
                    253: error_cleanup:
                    254:                buffer_free(&buffer);
                    255:                return 0;
                    256:        }
                    257:        /* Wait for response from the agent.  First read the length of the
                    258:           response packet. */
                    259:        len = 4;
                    260:        while (len > 0) {
                    261:                l = read(auth->fd, buf + 4 - len, len);
                    262:                if (l <= 0) {
                    263:                        error("Error reading response length from authentication socket.");
                    264:                        goto error_cleanup;
                    265:                }
                    266:                len -= l;
                    267:        }
                    268:
                    269:        /* Extract the length, and check it for sanity. */
                    270:        len = GET_32BIT(buf);
                    271:        if (len > 256 * 1024)
                    272:                fatal("Authentication response too long: %d", len);
                    273:
                    274:        /* Read the rest of the response in tothe buffer. */
                    275:        buffer_clear(&buffer);
                    276:        while (len > 0) {
                    277:                l = len;
                    278:                if (l > sizeof(buf))
                    279:                        l = sizeof(buf);
                    280:                l = read(auth->fd, buf, l);
                    281:                if (l <= 0) {
                    282:                        error("Error reading response from authentication socket.");
                    283:                        goto error_cleanup;
                    284:                }
                    285:                buffer_append(&buffer, (char *) buf, l);
                    286:                len -= l;
                    287:        }
                    288:
                    289:        /* Get the type of the packet. */
                    290:        buffer_get(&buffer, (char *) buf, 1);
                    291:
                    292:        /* Check for agent failure message. */
                    293:        if (buf[0] == SSH_AGENT_FAILURE) {
                    294:                log("Agent admitted failure to authenticate using the key.");
                    295:                goto error_cleanup;
                    296:        }
                    297:        /* Now it must be an authentication response packet. */
                    298:        if (buf[0] != SSH_AGENT_RSA_RESPONSE)
                    299:                fatal("Bad authentication response: %d", buf[0]);
                    300:
                    301:        /* Get the response from the packet.  This will abort with a fatal
                    302:           error if the packet is corrupt. */
                    303:        for (i = 0; i < 16; i++)
                    304:                response[i] = buffer_get_char(&buffer);
                    305:
                    306:        /* The buffer containing the packet is no longer needed. */
                    307:        buffer_free(&buffer);
                    308:
                    309:        /* Correct answer. */
                    310:        return 1;
                    311: }
1.1       deraadt   312:
                    313: /* Adds an identity to the authentication server.  This call is not meant to
                    314:    be used by normal applications. */
                    315:
1.12      markus    316: int
                    317: ssh_add_identity(AuthenticationConnection *auth,
                    318:                 RSA * key, const char *comment)
1.1       deraadt   319: {
1.12      markus    320:        Buffer buffer;
                    321:        unsigned char buf[8192];
                    322:        int len, l, type;
                    323:
                    324:        /* Format a message to the agent. */
                    325:        buffer_init(&buffer);
                    326:        buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
                    327:        buffer_put_int(&buffer, BN_num_bits(key->n));
                    328:        buffer_put_bignum(&buffer, key->n);
                    329:        buffer_put_bignum(&buffer, key->e);
                    330:        buffer_put_bignum(&buffer, key->d);
                    331:        /* To keep within the protocol: p < q for ssh. in SSL p > q */
                    332:        buffer_put_bignum(&buffer, key->iqmp);  /* ssh key->u */
                    333:        buffer_put_bignum(&buffer, key->q);     /* ssh key->p, SSL key->q */
                    334:        buffer_put_bignum(&buffer, key->p);     /* ssh key->q, SSL key->p */
                    335:        buffer_put_string(&buffer, comment, strlen(comment));
                    336:
                    337:        /* Get the length of the message, and format it in the buffer. */
                    338:        len = buffer_len(&buffer);
                    339:        PUT_32BIT(buf, len);
                    340:
                    341:        /* Send the length and then the packet to the agent. */
                    342:        if (write(auth->fd, buf, 4) != 4 ||
                    343:            write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
                    344:            buffer_len(&buffer)) {
                    345:                error("Error writing to authentication socket.");
                    346: error_cleanup:
                    347:                buffer_free(&buffer);
                    348:                return 0;
                    349:        }
                    350:        /* Wait for response from the agent.  First read the length of the
                    351:           response packet. */
                    352:        len = 4;
                    353:        while (len > 0) {
                    354:                l = read(auth->fd, buf + 4 - len, len);
                    355:                if (l <= 0) {
                    356:                        error("Error reading response length from authentication socket.");
                    357:                        goto error_cleanup;
                    358:                }
                    359:                len -= l;
                    360:        }
                    361:
                    362:        /* Extract the length, and check it for sanity. */
                    363:        len = GET_32BIT(buf);
                    364:        if (len > 256 * 1024)
                    365:                fatal("Add identity response too long: %d", len);
                    366:
                    367:        /* Read the rest of the response in tothe buffer. */
                    368:        buffer_clear(&buffer);
                    369:        while (len > 0) {
                    370:                l = len;
                    371:                if (l > sizeof(buf))
                    372:                        l = sizeof(buf);
                    373:                l = read(auth->fd, buf, l);
                    374:                if (l <= 0) {
                    375:                        error("Error reading response from authentication socket.");
                    376:                        goto error_cleanup;
                    377:                }
                    378:                buffer_append(&buffer, (char *) buf, l);
                    379:                len -= l;
                    380:        }
                    381:
                    382:        /* Get the type of the packet. */
                    383:        type = buffer_get_char(&buffer);
                    384:        switch (type) {
                    385:        case SSH_AGENT_FAILURE:
                    386:                buffer_free(&buffer);
                    387:                return 0;
                    388:        case SSH_AGENT_SUCCESS:
                    389:                buffer_free(&buffer);
                    390:                return 1;
                    391:        default:
                    392:                fatal("Bad response to add identity from authentication agent: %d",
                    393:                      type);
                    394:        }
                    395:        /* NOTREACHED */
                    396:        return 0;
                    397: }
1.1       deraadt   398:
1.12      markus    399: /* Removes an identity from the authentication server.  This call is not meant
1.1       deraadt   400:    to be used by normal applications. */
                    401:
1.12      markus    402: int
                    403: ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
1.1       deraadt   404: {
1.12      markus    405:        Buffer buffer;
                    406:        unsigned char buf[8192];
                    407:        int len, l, type;
                    408:
                    409:        /* Format a message to the agent. */
                    410:        buffer_init(&buffer);
                    411:        buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
                    412:        buffer_put_int(&buffer, BN_num_bits(key->n));
                    413:        buffer_put_bignum(&buffer, key->e);
                    414:        buffer_put_bignum(&buffer, key->n);
                    415:
                    416:        /* Get the length of the message, and format it in the buffer. */
                    417:        len = buffer_len(&buffer);
                    418:        PUT_32BIT(buf, len);
                    419:
                    420:        /* Send the length and then the packet to the agent. */
                    421:        if (write(auth->fd, buf, 4) != 4 ||
                    422:            write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
                    423:            buffer_len(&buffer)) {
                    424:                error("Error writing to authentication socket.");
                    425: error_cleanup:
                    426:                buffer_free(&buffer);
                    427:                return 0;
                    428:        }
                    429:        /* Wait for response from the agent.  First read the length of the
                    430:           response packet. */
                    431:        len = 4;
                    432:        while (len > 0) {
                    433:                l = read(auth->fd, buf + 4 - len, len);
                    434:                if (l <= 0) {
                    435:                        error("Error reading response length from authentication socket.");
                    436:                        goto error_cleanup;
                    437:                }
                    438:                len -= l;
                    439:        }
                    440:
                    441:        /* Extract the length, and check it for sanity. */
                    442:        len = GET_32BIT(buf);
                    443:        if (len > 256 * 1024)
                    444:                fatal("Remove identity response too long: %d", len);
                    445:
                    446:        /* Read the rest of the response in tothe buffer. */
                    447:        buffer_clear(&buffer);
                    448:        while (len > 0) {
                    449:                l = len;
                    450:                if (l > sizeof(buf))
                    451:                        l = sizeof(buf);
                    452:                l = read(auth->fd, buf, l);
                    453:                if (l <= 0) {
                    454:                        error("Error reading response from authentication socket.");
                    455:                        goto error_cleanup;
                    456:                }
                    457:                buffer_append(&buffer, (char *) buf, l);
                    458:                len -= l;
                    459:        }
1.1       deraadt   460:
1.12      markus    461:        /* Get the type of the packet. */
                    462:        type = buffer_get_char(&buffer);
                    463:        switch (type) {
                    464:        case SSH_AGENT_FAILURE:
                    465:                buffer_free(&buffer);
                    466:                return 0;
                    467:        case SSH_AGENT_SUCCESS:
                    468:                buffer_free(&buffer);
                    469:                return 1;
                    470:        default:
                    471:                fatal("Bad response to remove identity from authentication agent: %d",
                    472:                      type);
                    473:        }
                    474:        /* NOTREACHED */
                    475:        return 0;
                    476: }
                    477:
                    478: /* Removes all identities from the agent.  This call is not meant
1.1       deraadt   479:    to be used by normal applications. */
                    480:
1.12      markus    481: int
                    482: ssh_remove_all_identities(AuthenticationConnection *auth)
1.1       deraadt   483: {
1.12      markus    484:        Buffer buffer;
                    485:        unsigned char buf[8192];
                    486:        int len, l, type;
                    487:
                    488:        /* Get the length of the message, and format it in the buffer. */
                    489:        PUT_32BIT(buf, 1);
                    490:        buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
                    491:
                    492:        /* Send the length and then the packet to the agent. */
                    493:        if (write(auth->fd, buf, 5) != 5) {
                    494:                error("Error writing to authentication socket.");
                    495:                return 0;
                    496:        }
                    497:        /* Wait for response from the agent.  First read the length of the
                    498:           response packet. */
                    499:        len = 4;
                    500:        while (len > 0) {
                    501:                l = read(auth->fd, buf + 4 - len, len);
                    502:                if (l <= 0) {
                    503:                        error("Error reading response length from authentication socket.");
                    504:                        return 0;
                    505:                }
                    506:                len -= l;
                    507:        }
                    508:
                    509:        /* Extract the length, and check it for sanity. */
                    510:        len = GET_32BIT(buf);
                    511:        if (len > 256 * 1024)
                    512:                fatal("Remove identity response too long: %d", len);
                    513:
                    514:        /* Read the rest of the response into the buffer. */
                    515:        buffer_init(&buffer);
                    516:        while (len > 0) {
                    517:                l = len;
                    518:                if (l > sizeof(buf))
                    519:                        l = sizeof(buf);
                    520:                l = read(auth->fd, buf, l);
                    521:                if (l <= 0) {
                    522:                        error("Error reading response from authentication socket.");
                    523:                        buffer_free(&buffer);
                    524:                        return 0;
                    525:                }
                    526:                buffer_append(&buffer, (char *) buf, l);
                    527:                len -= l;
                    528:        }
                    529:
                    530:        /* Get the type of the packet. */
                    531:        type = buffer_get_char(&buffer);
                    532:        switch (type) {
                    533:        case SSH_AGENT_FAILURE:
                    534:                buffer_free(&buffer);
                    535:                return 0;
                    536:        case SSH_AGENT_SUCCESS:
                    537:                buffer_free(&buffer);
                    538:                return 1;
                    539:        default:
                    540:                fatal("Bad response to remove identity from authentication agent: %d",
                    541:                      type);
                    542:        }
                    543:        /* NOTREACHED */
                    544:        return 0;
                    545: }