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

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