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

Annotation of src/usr.bin/ssh/auth-krb4.c, Revision 1.8

1.1       deraadt     1: /*
                      2:
                      3:    auth-kerberos.c
                      4:
1.2       dugsong     5:    Dug Song <dugsong@UMICH.EDU>
1.1       deraadt     6:
1.2       dugsong     7:    Kerberos v4 authentication and ticket-passing routines.
1.1       deraadt     8:
1.8     ! markus      9:    $Id: auth-krb4.c,v 1.7 1999/11/14 22:58:44 markus Exp $
1.1       deraadt    10: */
                     11:
                     12: #include "includes.h"
                     13: #include "packet.h"
                     14: #include "xmalloc.h"
                     15: #include "ssh.h"
                     16:
                     17: #ifdef KRB4
1.6       markus     18: char *ticket = NULL;
                     19:
                     20: void
                     21: krb4_cleanup_proc(void *ignore)
1.1       deraadt    22: {
1.6       markus     23:   debug("krb4_cleanup_proc called");
                     24:
                     25:   if (ticket) {
                     26:     (void) dest_tkt();
                     27:     xfree(ticket);
                     28:     ticket = NULL;
                     29:   }
                     30: }
                     31:
                     32: int krb4_init(uid_t uid)
                     33: {
                     34:   static int cleanup_registered = 0;
1.1       deraadt    35:   char *tkt_root = TKT_ROOT;
                     36:   struct stat st;
                     37:   int fd;
1.6       markus     38:
                     39:   if (!ticket) {
                     40:     /* Set unique ticket string manually since we're still root. */
                     41:     ticket = xmalloc(MAXPATHLEN);
1.1       deraadt    42: #ifdef AFS
1.6       markus     43:     if (lstat("/ticket", &st) != -1)
                     44:       tkt_root = "/ticket/";
1.1       deraadt    45: #endif /* AFS */
1.6       markus     46:     snprintf(ticket, MAXPATHLEN, "%s%d_%d", tkt_root, uid, getpid());
                     47:     (void) krb_set_tkt_string(ticket);
                     48:   }
                     49:   /* Register ticket cleanup in case of fatal error. */
                     50:   if (!cleanup_registered) {
                     51:     fatal_add_cleanup(krb4_cleanup_proc, NULL);
                     52:     cleanup_registered = 1;
                     53:   }
                     54:   /* Try to create our ticket file. */
                     55:   if ((fd = mkstemp(ticket)) != -1) {
                     56:     close(fd);
                     57:     return 1;
1.1       deraadt    58:   }
1.6       markus     59:   /* Ticket file exists - make sure user owns it (just passed ticket). */
                     60:   if (lstat(ticket, &st) != -1) {
1.1       deraadt    61:     if (st.st_mode == (S_IFREG|S_IRUSR|S_IWUSR) && st.st_uid == uid)
                     62:       return 1;
                     63:   }
1.6       markus     64:   /* Failure - cancel cleanup function, leaving bad ticket for inspection. */
1.2       dugsong    65:   log("WARNING: bad ticket file %s", ticket);
1.6       markus     66:   fatal_remove_cleanup(krb4_cleanup_proc, NULL);
                     67:   cleanup_registered = 0;
                     68:   xfree(ticket);
                     69:   ticket = NULL;
                     70:
1.1       deraadt    71:   return 0;
                     72: }
                     73:
                     74: int auth_krb4(const char *server_user, KTEXT auth, char **client)
                     75: {
                     76:   AUTH_DAT adat   = { 0 };
                     77:   KTEXT_ST reply;
                     78:   char instance[INST_SZ];
                     79:   int r, s;
1.4       deraadt    80:   u_int cksum;
1.1       deraadt    81:   Key_schedule schedule;
                     82:   struct sockaddr_in local, foreign;
                     83:
                     84:   s = packet_get_connection_in();
                     85:
                     86:   r = sizeof(local);
                     87:   memset(&local, 0, sizeof(local));
                     88:   if (getsockname(s, (struct sockaddr *) &local, &r) < 0)
                     89:     debug("getsockname failed: %.100s", strerror(errno));
                     90:   r = sizeof(foreign);
                     91:   memset(&foreign, 0, sizeof(foreign));
1.8     ! markus     92:   if (getpeername(s, (struct sockaddr *)&foreign, &r) < 0) {
1.1       deraadt    93:     debug("getpeername failed: %.100s", strerror(errno));
1.8     ! markus     94:     fatal_cleanup();
        !            95:   }
1.1       deraadt    96:
                     97:   instance[0] = '*'; instance[1] = 0;
                     98:
                     99:   /* Get the encrypted request, challenge, and session key. */
1.2       dugsong   100:   if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) {
1.1       deraadt   101:     packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]);
                    102:     return 0;
                    103:   }
                    104:   des_key_sched((des_cblock *)adat.session, schedule);
                    105:
                    106:   *client = xmalloc(MAX_K_NAME_SZ);
1.2       dugsong   107:   (void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname,
                    108:                   *adat.pinst ? "." : "", adat.pinst, adat.prealm);
1.1       deraadt   109:
                    110:   /* Check ~/.klogin authorization now. */
                    111:   if (kuserok(&adat, (char *)server_user) != KSUCCESS) {
                    112:     packet_send_debug("Kerberos V4 .klogin authorization failed!");
1.2       dugsong   113:     log("Kerberos V4 .klogin authorization failed for %s to account %s",
1.1       deraadt   114:        *client, server_user);
1.7       markus    115:     xfree(*client);
1.1       deraadt   116:     return 0;
                    117:   }
                    118:   /* Increment the checksum, and return it encrypted with the session key. */
                    119:   cksum = adat.checksum + 1;
                    120:   cksum = htonl(cksum);
                    121:
                    122:   /* If we can't successfully encrypt the checksum, we send back an empty
                    123:      message, admitting our failure. */
                    124:   if ((r = krb_mk_priv((u_char *)&cksum, reply.dat, sizeof(cksum)+1,
                    125:                       schedule, &adat.session, &local, &foreign)) < 0) {
1.2       dugsong   126:     packet_send_debug("Kerberos V4 mk_priv: (%d) %s", r, krb_err_txt[r]);
1.1       deraadt   127:     reply.dat[0] = 0;
                    128:     reply.length = 0;
                    129:   }
1.6       markus    130:   else reply.length = r;
1.1       deraadt   131:
                    132:   /* Clear session key. */
                    133:   memset(&adat.session, 0, sizeof(&adat.session));
                    134:
                    135:   packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
                    136:   packet_put_string((char *) reply.dat, reply.length);
                    137:   packet_send();
                    138:   packet_write_wait();
                    139:   return 1;
                    140: }
                    141: #endif /* KRB4 */
                    142:
                    143: #ifdef AFS
                    144: int auth_kerberos_tgt(struct passwd *pw, const char *string)
                    145: {
                    146:   CREDENTIALS creds;
                    147:
                    148:   if (!radix_to_creds(string, &creds)) {
                    149:     log("Protocol error decoding Kerberos V4 tgt");
                    150:     packet_send_debug("Protocol error decoding Kerberos V4 tgt");
                    151:     goto auth_kerberos_tgt_failure;
                    152:   }
                    153:   if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
1.3       deraadt   154:     strlcpy(creds.service, "krbtgt", sizeof creds.service);
1.1       deraadt   155:
                    156:   if (strcmp(creds.service, "krbtgt")) {
1.6       markus    157:     log("Kerberos V4 tgt (%s%s%s@%s) rejected for %s", creds.pname,
                    158:        creds.pinst[0] ? "." : "", creds.pinst, creds.realm, pw->pw_name);
                    159:     packet_send_debug("Kerberos V4 tgt (%s%s%s@%s) rejected for %s",
1.1       deraadt   160:                      creds.pname, creds.pinst[0] ? "." : "", creds.pinst,
1.6       markus    161:                      creds.realm, pw->pw_name);
1.1       deraadt   162:     goto auth_kerberos_tgt_failure;
                    163:   }
1.6       markus    164:   if (!krb4_init(pw->pw_uid))
                    165:     goto auth_kerberos_tgt_failure;
                    166:
                    167:   if (in_tkt(creds.pname, creds.pinst) != KSUCCESS)
                    168:     goto auth_kerberos_tgt_failure;
                    169:
                    170:   if (save_credentials(creds.service, creds.instance, creds.realm,
                    171:                       creds.session, creds.lifetime, creds.kvno,
                    172:                       &creds.ticket_st, creds.issue_date) != KSUCCESS) {
1.1       deraadt   173:     packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials");
                    174:     goto auth_kerberos_tgt_failure;
                    175:   }
                    176:   /* Successful authentication, passed all checks. */
1.6       markus    177:   chown(tkt_string(), pw->pw_uid, pw->pw_gid);
                    178:
1.2       dugsong   179:   packet_send_debug("Kerberos V4 tgt accepted (%s.%s@%s, %s%s%s@%s)",
1.6       markus    180:                    creds.service, creds.instance, creds.realm, creds.pname,
                    181:                    creds.pinst[0] ? "." : "", creds.pinst, creds.realm);
                    182:   memset(&creds, 0, sizeof(creds));
1.1       deraadt   183:   packet_start(SSH_SMSG_SUCCESS);
                    184:   packet_send();
                    185:   packet_write_wait();
                    186:   return 1;
1.6       markus    187:
                    188:  auth_kerberos_tgt_failure:
                    189:   krb4_cleanup_proc(NULL);
1.1       deraadt   190:   memset(&creds, 0, sizeof(creds));
                    191:   packet_start(SSH_SMSG_FAILURE);
                    192:   packet_send();
                    193:   packet_write_wait();
                    194:   return 0;
                    195: }
                    196:
1.5       markus    197: int auth_afs_token(struct passwd *pw, const char *token_string)
1.1       deraadt   198: {
                    199:   CREDENTIALS creds;
1.5       markus    200:   uid_t uid = pw->pw_uid;
1.1       deraadt   201:
1.5       markus    202:   if (!radix_to_creds(token_string, &creds)) {
1.1       deraadt   203:     log("Protocol error decoding AFS token");
                    204:     packet_send_debug("Protocol error decoding AFS token");
                    205:     packet_start(SSH_SMSG_FAILURE);
                    206:     packet_send();
                    207:     packet_write_wait();
                    208:     return 0;
                    209:   }
                    210:   if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
1.3       deraadt   211:     strlcpy(creds.service, "afs", sizeof creds.service);
1.1       deraadt   212:
                    213:   if (strncmp(creds.pname, "AFS ID ", 7) == 0)
                    214:     uid = atoi(creds.pname + 7);
                    215:
                    216:   if (kafs_settoken(creds.realm, uid, &creds)) {
1.6       markus    217:     log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm,
                    218:        pw->pw_name);
                    219:     packet_send_debug("AFS token (%s@%s) rejected for %s", creds.pname,
                    220:                      creds.realm, pw->pw_name);
                    221:     memset(&creds, 0, sizeof(creds));
1.1       deraadt   222:     packet_start(SSH_SMSG_FAILURE);
                    223:     packet_send();
                    224:     packet_write_wait();
                    225:     return 0;
                    226:   }
1.2       dugsong   227:   packet_send_debug("AFS token accepted (%s@%s, %s@%s)", creds.service,
1.1       deraadt   228:                    creds.realm, creds.pname, creds.realm);
1.6       markus    229:   memset(&creds, 0, sizeof(creds));
1.1       deraadt   230:   packet_start(SSH_SMSG_SUCCESS);
                    231:   packet_send();
                    232:   packet_write_wait();
                    233:   return 1;
                    234: }
                    235: #endif /* AFS */