Annotation of 43BSDReno/kerberosIV/krb/rd_req.c, revision 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.