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

1.1       root        1: /*
                      2:  * $Source: /usr/src/kerberosIV/src/lib/krb/RCS/rd_req.c,v $
                      3:  * $Author: kfall $
                      4:  *
                      5:  * Copyright 1985, 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_rd_req_c =
                     14: "$Header: /usr/src/kerberosIV/src/lib/krb/RCS/rd_req.c,v 4.17 90/05/12 00:58:48 kfall Exp $";
                     15: #endif /* lint */
                     16: 
                     17: #include <mit-copyright.h>
                     18: #include <des.h>
                     19: #include <krb.h>
                     20: #include <prot.h>
                     21: #include <sys/time.h>
                     22: #include <strings.h>
                     23: 
                     24: extern int krb_ap_req_debug;
                     25: 
                     26: static struct timeval t_local = { 0, 0 };
                     27: 
                     28: /*
                     29:  * Keep the following information around for subsequent calls
                     30:  * to this routine by the same server using the same key.
                     31:  */
                     32: 
                     33: static Key_schedule serv_key;  /* Key sched to decrypt ticket */
                     34: static C_Block ky;              /* Initialization vector */
                     35: static int st_kvno;            /* version number for this key */
                     36: static char st_rlm[REALM_SZ];  /* server's realm */
                     37: static char st_nam[ANAME_SZ];  /* service name */
                     38: static char st_inst[INST_SZ];  /* server's instance */
                     39: 
                     40: /*
                     41:  * This file contains two functions.  krb_set_key() takes a DES
                     42:  * key or password string and returns a DES key (either the original
                     43:  * key, or the password converted into a DES key) and a key schedule
                     44:  * for it.
                     45:  *
                     46:  * krb_rd_req() reads an authentication request and returns information
                     47:  * about the identity of the requestor, or an indication that the
                     48:  * identity information was not authentic.
                     49:  */
                     50: 
                     51: /*
                     52:  * krb_set_key() takes as its first argument either a DES key or a
                     53:  * password string.  The "cvt" argument indicates how the first
                     54:  * argument "key" is to be interpreted: if "cvt" is null, "key" is
                     55:  * taken to be a DES key; if "cvt" is non-null, "key" is taken to
                     56:  * be a password string, and is converted into a DES key using
                     57:  * string_to_key().  In either case, the resulting key is returned
                     58:  * in the external static variable "ky".  A key schedule is
                     59:  * generated for "ky" and returned in the external static variable
                     60:  * "serv_key".
                     61:  *
                     62:  * This routine returns the return value of des_key_sched.
                     63:  *
                     64:  * krb_set_key() needs to be in the same .o file as krb_rd_req() so that
                     65:  * the key set by krb_set_key() is available in private storage for
                     66:  * krb_rd_req().
                     67:  */
                     68: 
                     69: int
                     70: krb_set_key(key,cvt)
                     71:     char *key;
                     72:     int cvt;
                     73: {
                     74: #ifdef NOENCRYPTION
                     75:     bzero(ky, sizeof(ky));
                     76:     return KSUCCESS;
                     77: #else /* Encrypt */
                     78:     if (cvt)
                     79:         string_to_key(key,ky);
                     80:     else
                     81:         bcopy(key,(char *)ky,8);
                     82:     return(des_key_sched(ky,serv_key));
                     83: #endif /* NOENCRYPTION */
                     84: }
                     85: 
                     86: 
                     87: /*
                     88:  * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or
                     89:  * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(),
                     90:  * checks its integrity and returns a judgement as to the requestor's
                     91:  * identity.
                     92:  *
                     93:  * The "authent" argument is a pointer to the received message.
                     94:  * The "service" and "instance" arguments name the receiving server,
                     95:  * and are used to get the service's ticket to decrypt the ticket
                     96:  * in the message, and to compare against the server name inside the
                     97:  * ticket.  "from_addr" is the network address of the host from which
                     98:  * the message was received; this is checked against the network
                     99:  * address in the ticket.  If "from_addr" is zero, the check is not
                    100:  * performed.  "ad" is an AUTH_DAT structure which is
                    101:  * filled in with information about the sender's identity according
                    102:  * to the authenticator and ticket sent in the message.  Finally,
                    103:  * "fn" contains the name of the file containing the server's key.
                    104:  * (If "fn" is NULL, the server's key is assumed to have been set
                    105:  * by krb_set_key().  If "fn" is the null string ("") the default
                    106:  * file KEYFILE, defined in "krb.h", is used.)
                    107:  *
                    108:  * krb_rd_req() returns RD_AP_OK if the authentication information
                    109:  * was genuine, or one of the following error codes (defined in
                    110:  * "krb.h"):
                    111:  *
                    112:  *     RD_AP_VERSION           - wrong protocol version number
                    113:  *     RD_AP_MSG_TYPE          - wrong message type
                    114:  *     RD_AP_UNDEC             - couldn't decipher the message
                    115:  *     RD_AP_INCON             - inconsistencies found
                    116:  *     RD_AP_BADD              - wrong network address
                    117:  *     RD_AP_TIME              - client time (in authenticator)
                    118:  *                               too far off server time
                    119:  *     RD_AP_NYV               - Kerberos time (in ticket) too
                    120:  *                               far off server time
                    121:  *     RD_AP_EXP               - ticket expired
                    122:  *
                    123:  * For the message format, see krb_mk_req().
                    124:  *
                    125:  * Mutual authentication is not implemented.
                    126:  */
                    127: 
                    128: krb_rd_req(authent,service,instance,from_addr,ad,fn)
                    129:     register KTEXT authent;    /* The received message */
                    130:     char *service;             /* Service name */
                    131:     char *instance;            /* Service instance */
                    132:     long from_addr;            /* Net address of originating host */
                    133:     AUTH_DAT *ad;              /* Structure to be filled in */
                    134:     char *fn;                  /* Filename to get keys from */
                    135: {
                    136:     static KTEXT_ST ticket;     /* Temp storage for ticket */
                    137:     static KTEXT tkt = &ticket;
                    138:     static KTEXT_ST req_id_st;  /* Temp storage for authenticator */
                    139:     register KTEXT req_id = &req_id_st;
                    140: 
                    141:     char realm[REALM_SZ];      /* Realm of issuing kerberos */
                    142:     static Key_schedule seskey_sched; /* Key sched for session key */
                    143:     unsigned char skey[KKEY_SZ]; /* Session key from ticket */
                    144:     char sname[SNAME_SZ];      /* Service name from ticket */
                    145:     char iname[INST_SZ];       /* Instance name from ticket */
                    146:     char r_aname[ANAME_SZ];    /* Client name from authenticator */
                    147:     char r_inst[INST_SZ];      /* Client instance from authenticator */
                    148:     char r_realm[REALM_SZ];    /* Client realm from authenticator */
                    149:     unsigned int r_time_ms;     /* Fine time from authenticator */
                    150:     unsigned long r_time_sec;   /* Coarse time from authenticator */
                    151:     register char *ptr;                /* For stepping through */
                    152:     unsigned long delta_t;      /* Time in authenticator - local time */
                    153:     long tkt_age;              /* Age of ticket */
                    154:     static int swap_bytes;     /* Need to swap bytes? */
                    155:     static int mutual;         /* Mutual authentication requested? */
                    156:     static unsigned char s_kvno;/* Version number of the server's key
                    157:                                 * Kerberos used to encrypt ticket */
                    158:     int status;
                    159: 
                    160:     if (authent->length <= 0)
                    161:        return(RD_AP_MODIFIED);
                    162: 
                    163:     ptr = (char *) authent->dat;
                    164: 
                    165:     /* get msg version, type and byte order, and server key version */
                    166: 
                    167:     /* check version */
                    168:     if (KRB_PROT_VERSION != (unsigned int) *ptr++)
                    169:         return(RD_AP_VERSION);
                    170: 
                    171:     /* byte order */
                    172:     swap_bytes = 0;
                    173:     if ((*ptr & 1) != HOST_BYTE_ORDER)
                    174:         swap_bytes++;
                    175: 
                    176:     /* check msg type */
                    177:     mutual = 0;
                    178:     switch (*ptr++ & ~1) {
                    179:     case AUTH_MSG_APPL_REQUEST:
                    180:         break;
                    181:     case AUTH_MSG_APPL_REQUEST_MUTUAL:
                    182:         mutual++;
                    183:         break;
                    184:     default:
                    185:         return(RD_AP_MSG_TYPE);
                    186:     }
                    187: 
                    188: #ifdef lint
                    189:     /* XXX mutual is set but not used; why??? */
                    190:     /* this is a crock to get lint to shut up */
                    191:     if (mutual)
                    192:         mutual = 0;
                    193: #endif /* lint */
                    194:     s_kvno = *ptr++;           /* get server key version */
                    195:     (void) strcpy(realm,ptr);   /* And the realm of the issuing KDC */
                    196:     ptr += strlen(ptr) + 1;     /* skip the realm "hint" */
                    197: 
                    198:     /*
                    199:      * If "fn" is NULL, key info should already be set; don't
                    200:      * bother with ticket file.  Otherwise, check to see if we
                    201:      * already have key info for the given server and key version
                    202:      * (saved in the static st_* variables).  If not, go get it
                    203:      * from the ticket file.  If "fn" is the null string, use the
                    204:      * default ticket file.
                    205:      */
                    206:     if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) ||
                    207:                strcmp(st_rlm,realm) || (st_kvno != s_kvno))) {
                    208:         if (*fn == 0) fn = KEYFILE;
                    209:         st_kvno = s_kvno;
                    210: #ifndef NOENCRYPTION
                    211:         if (read_service_key(service,instance,realm,(int) s_kvno,
                    212:                             fn,(char *)skey))
                    213:             return(RD_AP_UNDEC);
                    214:         if (status = krb_set_key((char *)skey,0))
                    215:            return(status);
                    216: #endif /* !NOENCRYPTION */
                    217:         (void) strcpy(st_rlm,realm);
                    218:         (void) strcpy(st_nam,service);
                    219:         (void) strcpy(st_inst,instance);
                    220:     }
                    221: 
                    222:     /* Get ticket from authenticator */
                    223:     tkt->length = (int) *ptr++;
                    224:     if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length)
                    225:        return(RD_AP_MODIFIED);
                    226:     bcopy(ptr+1,(char *)(tkt->dat),tkt->length);
                    227: 
                    228:     if (krb_ap_req_debug)
                    229:         log("ticket->length: %d",tkt->length);
                    230: 
                    231: #ifndef NOENCRYPTION
                    232:     /* Decrypt and take apart ticket */
                    233: #endif
                    234: 
                    235:     if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm,
                    236:                       &(ad->address),ad->session, &(ad->life),
                    237:                       &(ad->time_sec),sname,iname,ky,serv_key))
                    238:         return(RD_AP_UNDEC);
                    239: 
                    240:     if (krb_ap_req_debug) {
                    241:         log("Ticket Contents.");
                    242:         log(" Aname:   %s.%s",ad->pname,
                    243:             ((int)*(ad->prealm) ? ad->prealm : "Athena"));
                    244:         log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname);
                    245:     }
                    246: 
                    247:     /* Extract the authenticator */
                    248:     req_id->length = (int) *(ptr++);
                    249:     if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) >
                    250:        authent->length)
                    251:        return(RD_AP_MODIFIED);
                    252:     bcopy(ptr + tkt->length, (char *)(req_id->dat),req_id->length);
                    253: 
                    254: #ifndef NOENCRYPTION
                    255:     /* And decrypt it with the session key from the ticket */
                    256:     if (krb_ap_req_debug) log("About to decrypt authenticator");
                    257:     key_sched(ad->session,seskey_sched);
                    258:     pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat,
                    259:                  (long) req_id->length, seskey_sched,ad->session,DES_DECRYPT);
                    260:     if (krb_ap_req_debug) log("Done.");
                    261: #endif /* NOENCRYPTION */
                    262: 
                    263: #define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED);
                    264: 
                    265:     ptr = (char *) req_id->dat;
                    266:     (void) strcpy(r_aname,ptr);        /* Authentication name */
                    267:     ptr += strlen(r_aname)+1;
                    268:     check_ptr();
                    269:     (void) strcpy(r_inst,ptr); /* Authentication instance */
                    270:     ptr += strlen(r_inst)+1;
                    271:     check_ptr();
                    272:     (void) strcpy(r_realm,ptr);        /* Authentication name */
                    273:     ptr += strlen(r_realm)+1;
                    274:     check_ptr();
                    275:     bcopy(ptr,(char *)&ad->checksum,4);        /* Checksum */
                    276:     ptr += 4;
                    277:     check_ptr();
                    278:     if (swap_bytes) swap_u_long(ad->checksum);
                    279:     r_time_ms = *(ptr++);      /* Time (fine) */
                    280: #ifdef lint
                    281:     /* XXX r_time_ms is set but not used.  why??? */
                    282:     /* this is a crock to get lint to shut up */
                    283:     if (r_time_ms)
                    284:         r_time_ms = 0;
                    285: #endif /* lint */
                    286:     check_ptr();
                    287:     /* assume sizeof(r_time_sec) == 4 ?? */
                    288:     bcopy(ptr,(char *)&r_time_sec,4); /* Time (coarse) */
                    289:     if (swap_bytes) swap_u_long(r_time_sec);
                    290: 
                    291:     /* Check for authenticity of the request */
                    292:     if (krb_ap_req_debug)
                    293:         log("Pname:   %s %s",ad->pname,r_aname);
                    294:     if (strcmp(ad->pname,r_aname) != 0)
                    295:         return(RD_AP_INCON);
                    296:     if (strcmp(ad->pinst,r_inst) != 0)
                    297:         return(RD_AP_INCON);
                    298:     if (krb_ap_req_debug)
                    299:         log("Realm:   %s %s",ad->prealm,r_realm);
                    300:     if ((strcmp(ad->prealm,r_realm) != 0))
                    301:         return(RD_AP_INCON);
                    302: 
                    303:     if (krb_ap_req_debug)
                    304:         log("Address: %d %d",ad->address,from_addr);
                    305:     if (from_addr && (ad->address != from_addr))
                    306:         return(RD_AP_BADD);
                    307: 
                    308:     (void) gettimeofday(&t_local,(struct timezone *) 0);
                    309:     delta_t = abs((int)(t_local.tv_sec - r_time_sec));
                    310:     if (delta_t > CLOCK_SKEW) {
                    311:         if (krb_ap_req_debug)
                    312:             log("Time out of range: %d - %d = %d",
                    313:                 t_local.tv_sec,r_time_sec,delta_t);
                    314:         return(RD_AP_TIME);
                    315:     }
                    316: 
                    317:     /* Now check for expiration of ticket */
                    318: 
                    319:     tkt_age = t_local.tv_sec - ad->time_sec;
                    320:     if (krb_ap_req_debug)
                    321:         log("Time: %d Issue Date: %d Diff: %d Life %x",
                    322:             t_local.tv_sec,ad->time_sec,tkt_age,ad->life);
                    323: 
                    324:     if (t_local.tv_sec < ad->time_sec) {
                    325:         if ((ad->time_sec - t_local.tv_sec) > CLOCK_SKEW)
                    326:             return(RD_AP_NYV);
                    327:     }
                    328:     else if ((t_local.tv_sec - ad->time_sec) > 5 * 60 * ad->life)
                    329:         return(RD_AP_EXP);
                    330: 
                    331:     /* All seems OK */
                    332:     ad->reply.length = 0;
                    333: 
                    334:     return(RD_AP_OK);
                    335: }

unix.superglobalmegacorp.com

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