static afs_int32 kvno_admin_key(void *rock, afs_int32 kvno, struct ktc_encryptionKey *key) { return ka_LookupKvno(0, KA_ADMIN_NAME, KA_ADMIN_INST, kvno, key); /* we would like to start a Ubik transaction to fill the cache if that * fails, but may deadlock as Rx is now organized. */ }
afs_int32 ka_FillKeyCache(struct ubik_trans *tt) { int nfound; afs_int32 ko; int code; int i; struct ktc_encryptionKey k; struct kaOldKeys okeys; struct kaentry tentry; /* this is a little marginal, but... */ if (keyCacheVersion == ntohl(cheader.specialKeysVersion)) return 0; nfound = 0; for (ko = ntohl(cheader.kvnoPtr); ko; ko = ntohl(okeys.next)) { code = karead(tt, ko, (char *)&okeys, sizeof(okeys)); if (code) return KAIO; /* get name & instance */ code = karead(tt, ntohl(okeys.entry), (char *)&tentry, sizeof(tentry)); if (code) return KAIO; /* get all the old keys in this block */ for (i = 0; i < NOLDKEYS; i++) if (okeys.keys[i].superseded) { code = ka_LookupKvno(tt, tentry.userID.name, tentry.userID.instance, ntohl(okeys.keys[i].version), &k); if (code) return code; } } if (++nfound > maxCachedKeys) return KADATABASEINCONSISTENT; return 0; }
afs_int32 UDP_GetTicket(int ksoc, struct packet *pkt, afs_int32 kvno, char *authDomain, char *ticket, int ticketLen, char *auth, int authLen) { afs_int32 code; struct ktc_encryptionKey tgskey; char name[MAXKTCNAMELEN]; char inst[MAXKTCNAMELEN]; char cell[MAXKTCREALMLEN]; struct ktc_encryptionKey authSessionKey; afs_int32 host; Date start; Date authEnd; Date now = time(0); int celllen; int import; char *packet; int slen; int byteOrder = pkt->byteOrder; char sname[MAXKTCNAMELEN]; char sinst[MAXKTCNAMELEN]; afs_int32 time_ws; unsigned char life; struct ubik_trans *tt; afs_int32 to; struct kaentry caller; struct kaentry server; Date reqEnd; struct ktc_encryptionKey sessionKey; int newTicketLen; char newTicket[MAXKTCTICKETLEN]; char cipher[2 * MAXKTCTICKETLEN]; /* put encrypted part of answer here */ int cipherLen; struct packet ans; COUNT_REQ(UGetTicket); if ((code = InitAuthServ(&tt, LOCKREAD, this_op))) goto fail; code = ka_LookupKvno(tt, KA_TGS_NAME, ((strlen(authDomain) > 0) ? authDomain : lrealm), kvno, &tgskey); if (code) goto abort; code = tkt_DecodeTicket(ticket, ticketLen, &tgskey, name, inst, cell, &authSessionKey, &host, &start, &authEnd); pkt->name = name; pkt->inst = inst; pkt->realm = cell; if (code) { code = KERB_ERR_AUTH_EXP; /* was KANOAUTH */ goto abort; } save_principal(udptgsPrincipal, name, inst, cell); code = tkt_CheckTimes(start, authEnd, now); if (code <= 0) { if (code == -1) { code = KERB_ERR_SERVICE_EXP; /* was RXKADEXPIRED */ goto abort; } code = KERB_ERR_AUTH_EXP; /* was KANOAUTH */ goto abort; } celllen = strlen(cell); import = 0; if ((strlen(authDomain) > 0) && (strcmp(authDomain, lrealm) != 0)) import = 1; if (import && (celllen == 0)) { code = KERB_ERR_PKT_VER; /* was KABADTICKET */ goto abort; } if (celllen == 0) { strncpy(cell, lrealm, MAXKTCREALMLEN - 1); cell[MAXKTCREALMLEN - 1] = 0; }; if (!krb4_cross && strcmp(lrealm, cell) != 0) { code = KERB_ERR_PRINCIPAL_UNKNOWN; goto abort; } if (krb_udp_debug) { printf("UGetTicket: got ticket from '%s'.'%s'@'%s'\n", name, inst, cell); } code = check_auth(pkt, auth, authLen, &authSessionKey, name, inst, cell); if (code) goto abort; /* authenticator and all is OK so read actual request */ packet = pkt->rest; getint(time_ws); life = *(unsigned char *)packet++; getstr(sname); getstr(sinst); start = now; reqEnd = life_to_time(start, life); if (krb_udp_debug) { printf("UGetTicket: request for server '%s'.'%s'\n", sname, sinst); } save_principal(udptgsServerPrincipal, sname, sinst, 0); if (import) { strcpy(caller.userID.name, name); strcpy(caller.userID.instance, inst); caller.max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME); } else { code = FindBlock(tt, name, inst, &to, &caller); if (code) goto abort; if (to == 0) { ka_PrintUserID("GetTicket: User ", name, inst, " unknown.\n"); code = KERB_ERR_PRINCIPAL_UNKNOWN; /* KANOENT */ goto abort; } if (ntohl(caller.flags) & KAFNOTGS) { code = KERB_ERR_AUTH_EXP; /* was KABADUSER */ goto abort; } } code = FindBlock(tt, sname, sinst, &to, &server); /* get server's entry */ if (code) goto abort; if (to == 0) { /* entry not found */ ka_PrintUserID("GetTicket: Server ", sname, sinst, " unknown.\n"); code = KERB_ERR_PRINCIPAL_UNKNOWN; /* KANOENT */ goto abort; } code = ubik_EndTrans(tt); if (code) goto fail; if (ntohl(server.flags) & KAFNOSEAL) return KABADSERVER; code = DES_new_random_key(ktc_to_cblock(&sessionKey)); if (code) { code = KERB_ERR_NULL_KEY; /* was KANOKEYS */ goto fail; } reqEnd = umin(umin(reqEnd, authEnd), umin(start + ntohl(caller.max_ticket_lifetime), start + ntohl(server.max_ticket_lifetime))); code = tkt_MakeTicket(newTicket, &newTicketLen, &server.key, caller.userID.name, caller.userID.instance, cell, start, reqEnd, &sessionKey, htonl(pkt->from.sin_addr.s_addr), server.userID.name, server.userID.instance); if (code) goto fail; cipherLen = sizeof(cipher); code = create_cipher(cipher, &cipherLen, &sessionKey, sname, sinst, start, reqEnd, ntohl(server.key_version), newTicket, newTicketLen, &authSessionKey); if (code) goto fail; code = create_reply(&ans, name, inst, start, reqEnd, 0, cipher, cipherLen); if (code) goto fail; code = sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)&pkt->from, sizeof(pkt->from)); if (code != ans.len) { perror("calling sendto"); code = -1; goto fail; } if (cipherLen != 0) { KALOG(name, inst, sname, sinst, NULL, host, LOG_GETTICKET); } osi_audit(UDPGetTicketEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_STR, cell, AUD_STR, sname, AUD_STR, sinst, AUD_END); return 0; abort: ubik_AbortTrans(tt); fail: osi_audit(UDPGetTicketEvent, code, AUD_STR, name, AUD_STR, inst, AUD_STR, NULL, AUD_STR, NULL, AUD_STR, NULL, AUD_END); return code; }