Annotation of 43BSDReno/kerberosIV/krb/krb_get_in_tkt.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * $Source: /usr/src/kerberosIV/krb/RCS/krb_get_in_tkt.c,v $
                      3:  * $Author: kfall $
                      4:  *
                      5:  * Copyright 1986, 1987, 1988 by the Massachusetts Institute
                      6:  * of Technology.
                      7:  *
                      8:  * For copying and distribution information, please see the file
                      9:  * <mit-copyright.h>.
                     10:  */
                     11: 
                     12: #ifndef lint
                     13: static char *rcsid_krb_get_in_tkt_c =
                     14: "$Header: /usr/src/kerberosIV/krb/RCS/krb_get_in_tkt.c,v 4.20 90/06/25 20:56:45 kfall Exp $";
                     15: #endif /* lint */
                     16: 
                     17: #include <mit-copyright.h>
                     18: #include <des.h>
                     19: #include <krb.h>
                     20: #include <prot.h>
                     21: 
                     22: #include <stdio.h>
                     23: #include <strings.h>
                     24: #include <errno.h>
                     25: 
                     26: /* use the bsd time.h struct defs for PC too! */
                     27: #include <sys/time.h>
                     28: #include <sys/types.h>
                     29: 
                     30: int     swap_bytes;
                     31: 
                     32: /*
                     33:  * decrypt_tkt(): Given user, instance, realm, passwd, key_proc
                     34:  * and the cipher text sent from the KDC, decrypt the cipher text
                     35:  * using the key returned by key_proc.
                     36:  */
                     37: 
                     38: static int decrypt_tkt(user, instance, realm, arg, key_proc, cipp)
                     39:   char *user;
                     40:   char *instance;
                     41:   char *realm;
                     42:   char *arg;
                     43:   int (*key_proc)();
                     44:   KTEXT *cipp;
                     45: {
                     46:     KTEXT cip = *cipp;
                     47:     C_Block key;               /* Key for decrypting cipher */
                     48:     Key_schedule key_s;
                     49: 
                     50: #ifndef NOENCRYPTION
                     51:     /* Attempt to decrypt it */
                     52: #endif
                     53:     
                     54:     /* generate a key */
                     55:     
                     56:     {
                     57:        register int rc;
                     58:        rc = (*key_proc)(user,instance,realm,arg,key);
                     59:        if (rc)
                     60:            return(rc);
                     61:     }
                     62:     
                     63: #ifndef NOENCRYPTION
                     64:     key_sched(key,key_s);
                     65:     pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat,
                     66:                 (long) cip->length,key_s,key,0);
                     67: #endif /* !NOENCRYPTION */
                     68:     /* Get rid of all traces of key */
                     69:     bzero((char *)key,sizeof(key));
                     70:     bzero((char *)key_s,sizeof(key_s));
                     71: 
                     72:     return(0);
                     73: }
                     74: 
                     75: /*
                     76:  * krb_get_in_tkt() gets a ticket for a given principal to use a given
                     77:  * service and stores the returned ticket and session key for future
                     78:  * use.
                     79:  *
                     80:  * The "user", "instance", and "realm" arguments give the identity of
                     81:  * the client who will use the ticket.  The "service" and "sinstance"
                     82:  * arguments give the identity of the server that the client wishes
                     83:  * to use.  (The realm of the server is the same as the Kerberos server
                     84:  * to whom the request is sent.)  The "life" argument indicates the
                     85:  * desired lifetime of the ticket; the "key_proc" argument is a pointer
                     86:  * to the routine used for getting the client's private key to decrypt
                     87:  * the reply from Kerberos.  The "decrypt_proc" argument is a pointer
                     88:  * to the routine used to decrypt the reply from Kerberos; and "arg"
                     89:  * is an argument to be passed on to the "key_proc" routine.
                     90:  *
                     91:  * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it
                     92:  * returns an error code:  If an AUTH_MSG_ERR_REPLY packet is returned
                     93:  * by Kerberos, then the error code it contains is returned.  Other
                     94:  * error codes returned by this routine include INTK_PROT to indicate
                     95:  * wrong protocol version, INTK_BADPW to indicate bad password (if
                     96:  * decrypted ticket didn't make sense), INTK_ERR if the ticket was for
                     97:  * the wrong server or the ticket store couldn't be initialized.
                     98:  *
                     99:  * The format of the message sent to Kerberos is as follows:
                    100:  *
                    101:  * Size                        Variable                Field
                    102:  * ----                        --------                -----
                    103:  *
                    104:  * 1 byte              KRB_PROT_VERSION        protocol version number
                    105:  * 1 byte              AUTH_MSG_KDC_REQUEST |  message type
                    106:  *                     HOST_BYTE_ORDER         local byte order in lsb
                    107:  * string              user                    client's name
                    108:  * string              instance                client's instance
                    109:  * string              realm                   client's realm
                    110:  * 4 bytes             tlocal.tv_sec           timestamp in seconds
                    111:  * 1 byte              life                    desired lifetime
                    112:  * string              service                 service's name
                    113:  * string              sinstance               service's instance
                    114:  */
                    115: 
                    116: krb_get_in_tkt(user, instance, realm, service, sinstance, life,
                    117:               key_proc, decrypt_proc, arg)
                    118:     char *user;
                    119:     char *instance;
                    120:     char *realm;
                    121:     char *service;
                    122:     char *sinstance;
                    123:     int life;
                    124:     int (*key_proc)();
                    125:     int (*decrypt_proc)();
                    126:     char *arg;
                    127: {
                    128:     KTEXT_ST pkt_st;
                    129:     KTEXT pkt = &pkt_st;       /* Packet to KDC */
                    130:     KTEXT_ST rpkt_st;
                    131:     KTEXT rpkt = &rpkt_st;     /* Returned packet */
                    132:     KTEXT_ST cip_st;
                    133:     KTEXT cip = &cip_st;       /* Returned Ciphertext */
                    134:     KTEXT_ST tkt_st;
                    135:     KTEXT tkt = &tkt_st;       /* Current ticket */
                    136:     C_Block ses;                /* Session key for tkt */
                    137:     int kvno;                  /* Kvno for session key */
                    138:     unsigned char *v = pkt->dat; /* Prot vers no */
                    139:     unsigned char *t = (pkt->dat+1); /* Prot msg type */
                    140: 
                    141:     char s_name[SNAME_SZ];
                    142:     char s_instance[INST_SZ];
                    143:     char rlm[REALM_SZ];
                    144:     int lifetime;
                    145:     int msg_byte_order;
                    146:     int kerror;
                    147:     unsigned long exp_date;
                    148:     char *ptr;
                    149: 
                    150:     struct timeval t_local;
                    151: 
                    152:     unsigned long rep_err_code;
                    153: 
                    154:     unsigned long kdc_time;   /* KDC time */
                    155: 
                    156:     /* BUILD REQUEST PACKET */
                    157: 
                    158:     /* Set up the fixed part of the packet */
                    159:     *v = (unsigned char) KRB_PROT_VERSION;
                    160:     *t = (unsigned char) AUTH_MSG_KDC_REQUEST;
                    161:     *t |= HOST_BYTE_ORDER;
                    162: 
                    163:     /* Now for the variable info */
                    164:     (void) strcpy((char *)(pkt->dat+2),user); /* aname */
                    165:     pkt->length = 3 + strlen(user);
                    166:     (void) strcpy((char *)(pkt->dat+pkt->length),
                    167:                  instance);    /* instance */
                    168:     pkt->length += 1 + strlen(instance);
                    169:     (void) strcpy((char *)(pkt->dat+pkt->length),realm); /* realm */
                    170:     pkt->length += 1 + strlen(realm);
                    171: 
                    172:     (void) gettimeofday(&t_local,(struct timezone *) 0);
                    173:     /* timestamp */
                    174:     bcopy((char *)&(t_local.tv_sec),(char *)(pkt->dat+pkt->length), 4);
                    175:     pkt->length += 4;
                    176: 
                    177:     *(pkt->dat+(pkt->length)++) = (char) life;
                    178:     (void) strcpy((char *)(pkt->dat+pkt->length),service);
                    179:     pkt->length += 1 + strlen(service);
                    180:     (void) strcpy((char *)(pkt->dat+pkt->length),sinstance);
                    181:     pkt->length += 1 + strlen(sinstance);
                    182: 
                    183:     rpkt->length = 0;
                    184: 
                    185:     /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */
                    186: 
                    187:     if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror);
                    188: 
                    189:     /* check packet version of the returned packet */
                    190:     if (pkt_version(rpkt) != KRB_PROT_VERSION)
                    191:         return(INTK_PROT);
                    192: 
                    193:     /* Check byte order */
                    194:     msg_byte_order = pkt_msg_type(rpkt) & 1;
                    195:     swap_bytes = 0;
                    196:     if (msg_byte_order != HOST_BYTE_ORDER) {
                    197:         swap_bytes++;
                    198:     }
                    199: 
                    200:     switch (pkt_msg_type(rpkt) & ~1) {
                    201:     case AUTH_MSG_KDC_REPLY:
                    202:         break;
                    203:     case AUTH_MSG_ERR_REPLY:
                    204:         bcopy(pkt_err_code(rpkt),(char *) &rep_err_code,4);
                    205:         if (swap_bytes) swap_u_long(rep_err_code);
                    206:         return((int)rep_err_code);
                    207:     default:
                    208:         return(INTK_PROT);
                    209:     }
                    210: 
                    211:     /* EXTRACT INFORMATION FROM RETURN PACKET */
                    212: 
                    213:     /* get the principal's expiration date */
                    214:     bcopy(pkt_x_date(rpkt),(char *) &exp_date,sizeof(exp_date));
                    215:     if (swap_bytes) swap_u_long(exp_date);
                    216: 
                    217:     /* Extract the ciphertext */
                    218:     cip->length = pkt_clen(rpkt);       /* let clen do the swap */
                    219: 
                    220:     if ((cip->length < 0) || (cip->length > sizeof(cip->dat)))
                    221:        return(INTK_ERR);               /* no appropriate error code
                    222:                                         currently defined for INTK_ */
                    223:     /* copy information from return packet into "cip" */
                    224:     bcopy((char *) pkt_cipher(rpkt),(char *)(cip->dat),cip->length);
                    225: 
                    226:     /* Attempt to decrypt the reply. */
                    227:     if (decrypt_proc == NULL)
                    228:        decrypt_proc = decrypt_tkt;
                    229:     (*decrypt_proc)(user, instance, realm, arg, key_proc, &cip);
                    230: 
                    231:     ptr = (char *) cip->dat;
                    232: 
                    233:     /* extract session key */
                    234:     bcopy(ptr,(char *)ses,8);
                    235:     ptr += 8;
                    236: 
                    237:     if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
                    238:        return(INTK_BADPW);
                    239: 
                    240:     /* extract server's name */
                    241:     (void) strcpy(s_name,ptr);
                    242:     ptr += strlen(s_name) + 1;
                    243: 
                    244:     if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
                    245:        return(INTK_BADPW);
                    246: 
                    247:     /* extract server's instance */
                    248:     (void) strcpy(s_instance,ptr);
                    249:     ptr += strlen(s_instance) + 1;
                    250: 
                    251:     if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
                    252:        return(INTK_BADPW);
                    253: 
                    254:     /* extract server's realm */
                    255:     (void) strcpy(rlm,ptr);
                    256:     ptr += strlen(rlm) + 1;
                    257: 
                    258:     /* extract ticket lifetime, server key version, ticket length */
                    259:     /* be sure to avoid sign extension on lifetime! */
                    260:     lifetime = (unsigned char) ptr[0];
                    261:     kvno = (unsigned char) ptr[1];
                    262:     tkt->length = (unsigned char) ptr[2];
                    263:     ptr += 3;
                    264:     
                    265:     if ((tkt->length < 0) ||
                    266:        ((tkt->length + (ptr - (char *) cip->dat)) > cip->length))
                    267:        return(INTK_BADPW);
                    268: 
                    269:     /* extract ticket itself */
                    270:     bcopy(ptr,(char *)(tkt->dat),tkt->length);
                    271:     ptr += tkt->length;
                    272: 
                    273:     if (strcmp(s_name, service) || strcmp(s_instance, sinstance) ||
                    274:         strcmp(rlm, realm))    /* not what we asked for */
                    275:        return(INTK_ERR);       /* we need a better code here XXX */
                    276: 
                    277:     /* check KDC time stamp */
                    278:     bcopy(ptr,(char *)&kdc_time,4); /* Time (coarse) */
                    279:     if (swap_bytes) swap_u_long(kdc_time);
                    280: 
                    281:     ptr += 4;
                    282: 
                    283:     (void) gettimeofday(&t_local,(struct timezone *) 0);
                    284:     if (abs((int)(t_local.tv_sec - kdc_time)) > CLOCK_SKEW) {
                    285:         return(RD_AP_TIME);            /* XXX should probably be better
                    286:                                           code */
                    287:     }
                    288: 
                    289:     /* initialize ticket cache */
                    290:     if (in_tkt(user,instance) != KSUCCESS)
                    291:        return(INTK_ERR);
                    292: 
                    293:     /* stash ticket, session key, etc. for future use */
                    294:     if (kerror = save_credentials(s_name, s_instance, rlm, ses,
                    295:                                  lifetime, kvno, tkt, t_local.tv_sec))
                    296:        return(kerror);
                    297: 
                    298:     return(INTK_OK);
                    299: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.