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

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