[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.2

1.1       deraadt     1: /*
                      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: */
                     15:
                     16: #include "includes.h"
                     17: RCSID("$Id: authfd.c,v 1.2 1999/05/04 11:58:26 bg Exp $");
                     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
        !            32: ssh_get_authentication_fd()
1.1       deraadt    33: {
                     34:   const char *authfd, *authsocket;
                     35:   int sock;
                     36:   struct sockaddr_un sunaddr;
                     37:
                     38:   /* Get the file descriptor number from environment. */
                     39:   authfd = getenv(SSH_AUTHFD_ENV_NAME);
                     40:
                     41:   /* Convert the value to an integer and return it if we got a value. */
                     42:   if (authfd)
                     43:     return atoi(authfd);
                     44:
                     45:   authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
                     46:   if (!authsocket)
                     47:     return -1;
                     48:
                     49:   sunaddr.sun_family = AF_UNIX;
                     50:   strncpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
                     51:
                     52:   sock = socket(AF_UNIX, SOCK_STREAM, 0);
                     53:   if (sock < 0)
                     54:     return -1;
                     55:
                     56:   if (connect(sock, (struct sockaddr *)&sunaddr, AF_UNIX_SIZE(sunaddr)) < 0)
                     57:     {
                     58:       close(sock);
                     59:       return -1;
                     60:     }
                     61:
                     62:   return sock;
                     63: }
                     64:
                     65: /* Closes the agent socket if it should be closed (depends on how it was
                     66:    obtained).  The argument must have been returned by
                     67:    ssh_get_authentication_fd(). */
                     68:
                     69: void ssh_close_authentication_socket(int sock)
                     70: {
                     71:   if (getenv(SSH_AUTHSOCKET_ENV_NAME))
                     72:     close(sock);
                     73: }
                     74:
                     75: /* Dummy alarm used to prevent waiting for connection from the
                     76:    authentication agent indefinitely. */
                     77:
                     78: static RETSIGTYPE dummy_alarm_handler(int sig)
                     79: {
                     80:   /* Do nothing; a cought signal will just cause accept to return. */
                     81: }
                     82:
                     83: /* Opens a socket to the authentication server.  Returns the number of
                     84:    that socket, or -1 if no connection could be made. */
                     85:
                     86: int ssh_get_authentication_connection_fd()
                     87: {
                     88:   int authfd;
                     89:   int listen_sock, sock, port, addrlen;
                     90:   int old_timeout;
                     91:   RETSIGTYPE (*old_handler)();
                     92:   struct sockaddr_in sin;
                     93:   char msg[3];
                     94:
                     95:   /* Get the the socket number from the environment.  This is the socket
                     96:      used to obtain the real authentication socket. */
                     97:   authfd = ssh_get_authentication_fd();
                     98:   if (authfd == -1)
                     99:     return -1;
                    100:
                    101:   /* Create a local socket for listening. */
                    102:   listen_sock = socket(AF_INET, SOCK_STREAM, 0);
                    103:   if (listen_sock == -1)
                    104:     {
                    105:       ssh_close_authentication_socket(authfd);
                    106:       return -1;
                    107:     }
                    108:
                    109:   /* Bind the socket to random unprivileged port. */
                    110:   memset(&sin, 0, sizeof(sin));
                    111:   sin.sin_family = AF_INET;
                    112:   do
                    113:     {
                    114:       port = 32768 + (rand() % 30000);
                    115:       sin.sin_port = htons(port);
                    116:     }
                    117:   while (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0 &&
                    118:         errno == EADDRINUSE);
                    119:
                    120:   /* Start listening for connections on the socket. */
                    121:   if (listen(listen_sock, 1) < 0)
                    122:     {
                    123:       error("listen: %.100s", strerror(errno));
                    124:       close(listen_sock);
                    125:       ssh_close_authentication_socket(authfd);
                    126:       return -1;
                    127:     }
                    128:
                    129:   /* Send a message to the authentication fd requesting the agent or its
                    130:      local representative to connect to the given socket.  Note that
                    131:      we use send() to get the packet sent atomically (there can be several
                    132:      clients trying to use the same authentication fd simultaneously). */
                    133:   msg[0] = (char)SSH_AUTHFD_CONNECT;
                    134:   PUT_16BIT(msg + 1, port);
                    135:   if (send(authfd, msg, 3, 0) < 0)
                    136:     {
                    137:       shutdown(listen_sock, 2);
                    138:       close(listen_sock);
                    139:       ssh_close_authentication_socket(authfd);
                    140:       return -1;
                    141:     }
                    142:
                    143:   /* Setup a timeout so we won't wait for the connection indefinitely. */
                    144:   old_timeout = alarm(120);
                    145:   old_handler = signal(SIGALRM, dummy_alarm_handler);
                    146:
                    147:   /* Wait for the connection from the agent or its representative. */
                    148:   addrlen = sizeof(sin);
                    149:   sock = accept(listen_sock, (struct sockaddr *)&sin, &addrlen);
                    150:
                    151:   /* Remove the alarm (restore its old values). */
                    152:   alarm(old_timeout);
                    153:   signal(SIGALRM, old_handler);
                    154:
                    155:   /* Close the socket we used for listening.  It is no longer needed.
                    156:      (The authentication fd and the new connection still remain open.) */
                    157:   shutdown(listen_sock, 2);
                    158:   close(listen_sock);
                    159:   ssh_close_authentication_socket(authfd);
                    160:
                    161:   return sock;
                    162: }
                    163:
                    164: /* Opens and connects a private socket for communication with the
                    165:    authentication agent.  Returns the file descriptor (which must be
                    166:    shut down and closed by the caller when no longer needed).
                    167:    Returns NULL if an error occurred and the connection could not be
                    168:    opened. */
                    169:
                    170: AuthenticationConnection *ssh_get_authentication_connection()
                    171: {
                    172:   AuthenticationConnection *auth;
                    173:   int sock;
                    174:
                    175:   /* Get a connection to the authentication agent. */
                    176:   sock = ssh_get_authentication_connection_fd();
                    177:
                    178:   /* Fail if we couldn't obtain a connection.  This happens if we exited
                    179:      due to a timeout. */
                    180:   if (sock < 0)
                    181:     return NULL;
                    182:
                    183:   /* Applocate the connection structure and initialize it. */
                    184:   auth = xmalloc(sizeof(*auth));
                    185:   auth->fd = sock;
                    186:   buffer_init(&auth->packet);
                    187:   buffer_init(&auth->identities);
                    188:   auth->howmany = 0;
                    189:
                    190:   return auth;
                    191: }
                    192:
                    193: /* Closes the connection to the authentication agent and frees any associated
                    194:    memory. */
                    195:
                    196: void ssh_close_authentication_connection(AuthenticationConnection *ac)
                    197: {
                    198:   buffer_free(&ac->packet);
                    199:   buffer_free(&ac->identities);
                    200:   close(ac->fd);
                    201: }
                    202:
                    203: /* Returns the first authentication identity held by the agent.
                    204:    Returns true if an identity is available, 0 otherwise.
                    205:    The caller must initialize the integers before the call, and free the
                    206:    comment after a successful call (before calling ssh_get_next_identity). */
                    207:
1.2     ! provos    208: int
        !           209: ssh_get_first_identity(AuthenticationConnection *auth,
        !           210:                       int *bitsp, BIGNUM *e, BIGNUM *n, char **comment)
1.1       deraadt   211: {
                    212:   unsigned char msg[8192];
                    213:   int len, l;
                    214:
                    215:   /* Send a message to the agent requesting for a list of the identities
                    216:      it can represent. */
                    217:   msg[0] = 0;
                    218:   msg[1] = 0;
                    219:   msg[2] = 0;
                    220:   msg[3] = 1;
                    221:   msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
                    222:   if (write(auth->fd, msg, 5) != 5)
                    223:     {
                    224:       error("write auth->fd: %.100s", strerror(errno));
                    225:       return 0;
                    226:     }
                    227:
                    228:   /* Read the length of the response.  XXX implement timeouts here. */
                    229:   len = 4;
                    230:   while (len > 0)
                    231:     {
                    232:       l = read(auth->fd, msg + 4 - len, len);
                    233:       if (l <= 0)
                    234:        {
                    235:          error("read auth->fd: %.100s", strerror(errno));
                    236:          return 0;
                    237:        }
                    238:       len -= l;
                    239:     }
                    240:
                    241:   /* Extract the length, and check it for sanity.  (We cannot trust
                    242:      authentication agents). */
                    243:   len = GET_32BIT(msg);
                    244:   if (len < 1 || len > 256*1024)
                    245:     fatal("Authentication reply message too long: %d\n", len);
                    246:
                    247:   /* Read the packet itself. */
                    248:   buffer_clear(&auth->identities);
                    249:   while (len > 0)
                    250:     {
                    251:       l = len;
                    252:       if (l > sizeof(msg))
                    253:        l = sizeof(msg);
                    254:       l = read(auth->fd, msg, l);
                    255:       if (l <= 0)
                    256:        fatal("Incomplete authentication reply.");
                    257:       buffer_append(&auth->identities, (char *)msg, l);
                    258:       len -= l;
                    259:     }
                    260:
                    261:   /* Get message type, and verify that we got a proper answer. */
                    262:   buffer_get(&auth->identities, (char *)msg, 1);
                    263:   if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
                    264:     fatal("Bad authentication reply message type: %d", msg[0]);
                    265:
                    266:   /* Get the number of entries in the response and check it for sanity. */
                    267:   auth->howmany = buffer_get_int(&auth->identities);
                    268:   if (auth->howmany > 1024)
                    269:     fatal("Too many identities in authentication reply: %d\n", auth->howmany);
                    270:
                    271:   /* Return the first entry (if any). */
                    272:   return ssh_get_next_identity(auth, bitsp, e, n, comment);
                    273: }
                    274:
                    275: /* Returns the next authentication identity for the agent.  Other functions
                    276:    can be called between this and ssh_get_first_identity or two calls of this
                    277:    function.  This returns 0 if there are no more identities.  The caller
                    278:    must free comment after a successful return. */
                    279:
1.2     ! provos    280: int
        !           281: ssh_get_next_identity(AuthenticationConnection *auth,
        !           282:                      int *bitsp, BIGNUM *e, BIGNUM *n, char **comment)
1.1       deraadt   283: {
                    284:   /* Return failure if no more entries. */
                    285:   if (auth->howmany <= 0)
                    286:     return 0;
                    287:
                    288:   /* Get the next entry from the packet.  These will abort with a fatal
                    289:      error if the packet is too short or contains corrupt data. */
                    290:   *bitsp = buffer_get_int(&auth->identities);
1.2     ! provos    291:   buffer_get_bignum(&auth->identities, e);
        !           292:   buffer_get_bignum(&auth->identities, n);
1.1       deraadt   293:   *comment = buffer_get_string(&auth->identities, NULL);
                    294:
                    295:   /* Decrement the number of remaining entries. */
                    296:   auth->howmany--;
                    297:
                    298:   return 1;
                    299: }
                    300:
                    301: /* Generates a random challenge, sends it to the agent, and waits for response
                    302:    from the agent.  Returns true (non-zero) if the agent gave the correct
                    303:    answer, zero otherwise.  Response type selects the style of response
                    304:    desired, with 0 corresponding to protocol version 1.0 (no longer supported)
                    305:    and 1 corresponding to protocol version 1.1. */
                    306:
1.2     ! provos    307: int
        !           308: ssh_decrypt_challenge(AuthenticationConnection *auth,
        !           309:                      int bits, BIGNUM *e, BIGNUM *n, BIGNUM *challenge,
        !           310:                      unsigned char session_id[16],
        !           311:                      unsigned int response_type,
        !           312:                      unsigned char response[16])
1.1       deraadt   313: {
                    314:   Buffer buffer;
                    315:   unsigned char buf[8192];
                    316:   int len, l, i;
                    317:
                    318:   /* Response type 0 is no longer supported. */
                    319:   if (response_type == 0)
                    320:     fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
                    321:
                    322:   /* Format a message to the agent. */
                    323:   buf[0] = SSH_AGENTC_RSA_CHALLENGE;
                    324:   buffer_init(&buffer);
                    325:   buffer_append(&buffer, (char *)buf, 1);
                    326:   buffer_put_int(&buffer, bits);
1.2     ! provos    327:   buffer_put_bignum(&buffer, e);
        !           328:   buffer_put_bignum(&buffer, n);
        !           329:   buffer_put_bignum(&buffer, challenge);
1.1       deraadt   330:   buffer_append(&buffer, (char *)session_id, 16);
                    331:   buffer_put_int(&buffer, response_type);
                    332:
                    333:   /* Get the length of the message, and format it in the buffer. */
                    334:   len = buffer_len(&buffer);
                    335:   PUT_32BIT(buf, len);
                    336:
                    337:   /* Send the length and then the packet to the agent. */
                    338:   if (write(auth->fd, buf, 4) != 4 ||
                    339:       write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
                    340:         buffer_len(&buffer))
                    341:     {
                    342:       error("Error writing to authentication socket.");
                    343:     error_cleanup:
                    344:       buffer_free(&buffer);
                    345:       return 0;
                    346:     }
                    347:
                    348:   /* Wait for response from the agent.  First read the length of the
                    349:      response packet. */
                    350:   len = 4;
                    351:   while (len > 0)
                    352:     {
                    353:       l = read(auth->fd, buf + 4 - len, len);
                    354:       if (l <= 0)
                    355:        {
                    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("Authentication 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:     {
                    371:       l = len;
                    372:       if (l > sizeof(buf))
                    373:        l = sizeof(buf);
                    374:       l = read(auth->fd, buf, l);
                    375:       if (l <= 0)
                    376:        {
                    377:          error("Error reading response from authentication socket.");
                    378:          goto error_cleanup;
                    379:        }
                    380:       buffer_append(&buffer, (char *)buf, l);
                    381:       len -= l;
                    382:     }
                    383:
                    384:   /* Get the type of the packet. */
                    385:   buffer_get(&buffer, (char *)buf, 1);
                    386:
                    387:   /* Check for agent failure message. */
                    388:   if (buf[0] == SSH_AGENT_FAILURE)
                    389:     {
                    390:       log("Agent admitted failure to authenticate using the key.");
                    391:       goto error_cleanup;
                    392:     }
                    393:
                    394:   /* Now it must be an authentication response packet. */
                    395:   if (buf[0] != SSH_AGENT_RSA_RESPONSE)
                    396:     fatal("Bad authentication response: %d", buf[0]);
                    397:
                    398:   /* Get the response from the packet.  This will abort with a fatal error
                    399:      if the packet is corrupt. */
                    400:   for (i = 0; i < 16; i++)
                    401:     response[i] = buffer_get_char(&buffer);
                    402:
                    403:   /* The buffer containing the packet is no longer needed. */
                    404:   buffer_free(&buffer);
                    405:
                    406:   /* Correct answer. */
                    407:   return 1;
                    408: }
                    409:
                    410: /* Adds an identity to the authentication server.  This call is not meant to
                    411:    be used by normal applications. */
                    412:
                    413: int ssh_add_identity(AuthenticationConnection *auth,
1.2     ! provos    414:                     RSA *key, const char *comment)
1.1       deraadt   415: {
                    416:   Buffer buffer;
                    417:   unsigned char buf[8192];
                    418:   int len, l, type;
                    419:
                    420:   /* Format a message to the agent. */
                    421:   buffer_init(&buffer);
                    422:   buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
1.2     ! provos    423:   buffer_put_int(&buffer, BN_num_bits(key->n));
        !           424:   buffer_put_bignum(&buffer, key->n);
        !           425:   buffer_put_bignum(&buffer, key->e);
        !           426:   buffer_put_bignum(&buffer, key->d);
        !           427:   /* To keep within the protocol: p < q for ssh. in SSL p > q */
        !           428:   buffer_put_bignum(&buffer, key->iqmp); /* ssh key->u */
        !           429:   buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */
        !           430:   buffer_put_bignum(&buffer, key->p); /* ssh key->q, SSL key->p */
1.1       deraadt   431:   buffer_put_string(&buffer, comment, strlen(comment));
                    432:
                    433:   /* Get the length of the message, and format it in the buffer. */
                    434:   len = buffer_len(&buffer);
                    435:   PUT_32BIT(buf, len);
                    436:
                    437:   /* Send the length and then the packet to the agent. */
                    438:   if (write(auth->fd, buf, 4) != 4 ||
                    439:       write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
                    440:         buffer_len(&buffer))
                    441:     {
                    442:       error("Error writing to authentication socket.");
                    443:     error_cleanup:
                    444:       buffer_free(&buffer);
                    445:       return 0;
                    446:     }
                    447:
                    448:   /* Wait for response from the agent.  First read the length of the
                    449:      response packet. */
                    450:   len = 4;
                    451:   while (len > 0)
                    452:     {
                    453:       l = read(auth->fd, buf + 4 - len, len);
                    454:       if (l <= 0)
                    455:        {
                    456:          error("Error reading response length from authentication socket.");
                    457:          goto error_cleanup;
                    458:        }
                    459:       len -= l;
                    460:     }
                    461:
                    462:   /* Extract the length, and check it for sanity. */
                    463:   len = GET_32BIT(buf);
                    464:   if (len > 256*1024)
                    465:     fatal("Add identity response too long: %d", len);
                    466:
                    467:   /* Read the rest of the response in tothe buffer. */
                    468:   buffer_clear(&buffer);
                    469:   while (len > 0)
                    470:     {
                    471:       l = len;
                    472:       if (l > sizeof(buf))
                    473:        l = sizeof(buf);
                    474:       l = read(auth->fd, buf, l);
                    475:       if (l <= 0)
                    476:        {
                    477:          error("Error reading response from authentication socket.");
                    478:          goto error_cleanup;
                    479:        }
                    480:       buffer_append(&buffer, (char *)buf, l);
                    481:       len -= l;
                    482:     }
                    483:
                    484:   /* Get the type of the packet. */
                    485:   type = buffer_get_char(&buffer);
                    486:   switch (type)
                    487:     {
                    488:     case SSH_AGENT_FAILURE:
                    489:       buffer_free(&buffer);
                    490:       return 0;
                    491:     case SSH_AGENT_SUCCESS:
                    492:       buffer_free(&buffer);
                    493:       return 1;
                    494:     default:
                    495:       fatal("Bad response to add identity from authentication agent: %d",
                    496:            type);
                    497:     }
                    498:   /*NOTREACHED*/
                    499:   return 0;
                    500: }
                    501:
                    502: /* Removes an identity from the authentication server.  This call is not meant
                    503:    to be used by normal applications. */
                    504:
1.2     ! provos    505: int ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
1.1       deraadt   506: {
                    507:   Buffer buffer;
                    508:   unsigned char buf[8192];
                    509:   int len, l, type;
                    510:
                    511:   /* Format a message to the agent. */
                    512:   buffer_init(&buffer);
                    513:   buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
1.2     ! provos    514:   buffer_put_int(&buffer, BN_num_bits(key->n));
        !           515:   buffer_put_bignum(&buffer, key->e);
        !           516:   buffer_put_bignum(&buffer, key->n);
1.1       deraadt   517:
                    518:   /* Get the length of the message, and format it in the buffer. */
                    519:   len = buffer_len(&buffer);
                    520:   PUT_32BIT(buf, len);
                    521:
                    522:   /* Send the length and then the packet to the agent. */
                    523:   if (write(auth->fd, buf, 4) != 4 ||
                    524:       write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
                    525:         buffer_len(&buffer))
                    526:     {
                    527:       error("Error writing to authentication socket.");
                    528:     error_cleanup:
                    529:       buffer_free(&buffer);
                    530:       return 0;
                    531:     }
                    532:
                    533:   /* Wait for response from the agent.  First read the length of the
                    534:      response packet. */
                    535:   len = 4;
                    536:   while (len > 0)
                    537:     {
                    538:       l = read(auth->fd, buf + 4 - len, len);
                    539:       if (l <= 0)
                    540:        {
                    541:          error("Error reading response length from authentication socket.");
                    542:          goto error_cleanup;
                    543:        }
                    544:       len -= l;
                    545:     }
                    546:
                    547:   /* Extract the length, and check it for sanity. */
                    548:   len = GET_32BIT(buf);
                    549:   if (len > 256*1024)
                    550:     fatal("Remove identity response too long: %d", len);
                    551:
                    552:   /* Read the rest of the response in tothe buffer. */
                    553:   buffer_clear(&buffer);
                    554:   while (len > 0)
                    555:     {
                    556:       l = len;
                    557:       if (l > sizeof(buf))
                    558:        l = sizeof(buf);
                    559:       l = read(auth->fd, buf, l);
                    560:       if (l <= 0)
                    561:        {
                    562:          error("Error reading response from authentication socket.");
                    563:          goto error_cleanup;
                    564:        }
                    565:       buffer_append(&buffer, (char *)buf, l);
                    566:       len -= l;
                    567:     }
                    568:
                    569:   /* Get the type of the packet. */
                    570:   type = buffer_get_char(&buffer);
                    571:   switch (type)
                    572:     {
                    573:     case SSH_AGENT_FAILURE:
                    574:       buffer_free(&buffer);
                    575:       return 0;
                    576:     case SSH_AGENT_SUCCESS:
                    577:       buffer_free(&buffer);
                    578:       return 1;
                    579:     default:
                    580:       fatal("Bad response to remove identity from authentication agent: %d",
                    581:            type);
                    582:     }
                    583:   /*NOTREACHED*/
                    584:   return 0;
                    585: }
                    586:
                    587: /* Removes all identities from the agent.  This call is not meant
                    588:    to be used by normal applications. */
                    589:
                    590: int ssh_remove_all_identities(AuthenticationConnection *auth)
                    591: {
                    592:   Buffer buffer;
                    593:   unsigned char buf[8192];
                    594:   int len, l, type;
                    595:
                    596:   /* Get the length of the message, and format it in the buffer. */
                    597:   PUT_32BIT(buf, 1);
                    598:   buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
                    599:
                    600:   /* Send the length and then the packet to the agent. */
                    601:   if (write(auth->fd, buf, 5) != 5)
                    602:     {
                    603:       error("Error writing to authentication socket.");
                    604:       return 0;
                    605:     }
                    606:
                    607:   /* Wait for response from the agent.  First read the length of the
                    608:      response packet. */
                    609:   len = 4;
                    610:   while (len > 0)
                    611:     {
                    612:       l = read(auth->fd, buf + 4 - len, len);
                    613:       if (l <= 0)
                    614:        {
                    615:          error("Error reading response length from authentication socket.");
                    616:          return 0;
                    617:        }
                    618:       len -= l;
                    619:     }
                    620:
                    621:   /* Extract the length, and check it for sanity. */
                    622:   len = GET_32BIT(buf);
                    623:   if (len > 256*1024)
                    624:     fatal("Remove identity response too long: %d", len);
                    625:
                    626:   /* Read the rest of the response into the buffer. */
                    627:   buffer_init(&buffer);
                    628:   while (len > 0)
                    629:     {
                    630:       l = len;
                    631:       if (l > sizeof(buf))
                    632:        l = sizeof(buf);
                    633:       l = read(auth->fd, buf, l);
                    634:       if (l <= 0)
                    635:        {
                    636:          error("Error reading response from authentication socket.");
                    637:          buffer_free(&buffer);
                    638:          return 0;
                    639:        }
                    640:       buffer_append(&buffer, (char *)buf, l);
                    641:       len -= l;
                    642:     }
                    643:
                    644:   /* Get the type of the packet. */
                    645:   type = buffer_get_char(&buffer);
                    646:   switch (type)
                    647:     {
                    648:     case SSH_AGENT_FAILURE:
                    649:       buffer_free(&buffer);
                    650:       return 0;
                    651:     case SSH_AGENT_SUCCESS:
                    652:       buffer_free(&buffer);
                    653:       return 1;
                    654:     default:
                    655:       fatal("Bad response to remove identity from authentication agent: %d",
                    656:            type);
                    657:     }
                    658:   /*NOTREACHED*/
                    659:   return 0;
                    660: }
                    661:
                    662: /* Closes the connection to the authentication agent. */
                    663:
                    664: void ssh_close_authentication(AuthenticationConnection *auth)
                    665: {
                    666:   /* Close the connection. */
                    667:   shutdown(auth->fd, 2);
                    668:   close(auth->fd);
                    669:
                    670:   /* Free the buffers. */
                    671:   buffer_free(&auth->packet);
                    672:   buffer_free(&auth->identities);
                    673:
                    674:   /* Free the connection data structure. */
                    675:   xfree(auth);
                    676: }